java中如何实现自定义SpringSecurity权限
今天就跟大家聊聊有关java中如何实现自定义Spring Security权限,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
成都创新互联公司专业为企业提供永济网站建设、永济做网站、永济网站设计、永济网站制作等企业网站建设、网页设计与制作、永济企业网站模板建站服务,10余年永济做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。
背景描述
项目中需要做细粒的权限控制,细微至url + httpmethod (满足restful,例如: https://.../xxx/users/1, 某些角色只能查看(HTTP GET), 而无权进行增改删(POST, PUT, DELETE))。
表设计
为避嫌,只列出要用到的关键字段,其余敬请自行脑补。
1.admin_user 管理员用户表, 关键字段( id, role_id )。
2.t_role 角色表, 关键字段( id, privilege_id )。
3.t_privilege 权限表, 关键字段( id, url, method )
三个表的关联关系就不用多说了吧,看字段一眼就能看出。
实现前分析
我们可以逆向思考:
要实现我们的需求,最关键的一步就是让Spring Security的AccessDecisionManager来判断所请求的url + httpmethod 是否符合我们数据库中的配置。然而,AccessDecisionManager并没有来判定类似需求的相关Voter, 因此,我们需要自定义一个Voter的实现(默认注册的AffirmativeBased的策略是只要有Voter投出ACCESS_GRANTED票,则判定为通过,这也正符合我们的需求)。实现voter后,有一个关键参数(Collection
总结一下思路步骤:
1.自定义voter实现。
2.自定义ConfigAttribute实现。
3.自定义SecurityMetadataSource实现。
4.Authentication包含用户实例(这个其实不用说,大家应该都已经这么做了)。
5.自定义GrantedAuthority实现。
项目实战
1.自定义GrantedAuthority实现
UrlGrantedAuthority.java
public class UrlGrantedAuthority implements GrantedAuthority { private final String httpMethod; private final String url; public UrlGrantedAuthority(String httpMethod, String url) { this.httpMethod = httpMethod; this.url = url; } @Override public String getAuthority() { return url; } public String getHttpMethod() { return httpMethod; } public String getUrl() { return url; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; UrlGrantedAuthority target = (UrlGrantedAuthority) o; if (httpMethod.equals(target.getHttpMethod()) && url.equals(target.getUrl())) return true; return false; } @Override public int hashCode() { int result = httpMethod != null ? httpMethod.hashCode() : 0; result = 31 * result + (url != null ? url.hashCode() : 0); return result; } }
2.自定义认证用户实例
public class SystemUser implements UserDetails { private final Admin admin; private ListmenuOutputList; private final List grantedAuthorities; public SystemUser(Admin admin, List grantedPrivileges, List menuOutputList) { this.admin = admin; this.grantedAuthorities = grantedPrivileges.stream().map(it -> { String method = it.getMethod() != null ? it.getMethod().getLabel() : null; return new UrlGrantedAuthority(method, it.getUrl()); }).collect(Collectors.toList()); this.menuOutputList = menuOutputList; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return this.grantedAuthorities; } @Override public String getPassword() { return admin.getPassword(); } @Override public String getUsername() { return null; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } public Long getId() { return admin.getId(); } public Admin getAdmin() { return admin; } public List getMenuOutputList() { return menuOutputList; } public String getSalt() { return admin.getSalt(); } }
3.自定义UrlConfigAttribute实现
public class UrlConfigAttribute implements ConfigAttribute { private final HttpServletRequest httpServletRequest; public UrlConfigAttribute(HttpServletRequest httpServletRequest) { this.httpServletRequest = httpServletRequest; } @Override public String getAttribute() { return null; } public HttpServletRequest getHttpServletRequest() { return httpServletRequest; } }
4.自定义SecurityMetadataSource实现
public class UrlFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource { @Override public CollectiongetAttributes(Object object) throws IllegalArgumentException { final HttpServletRequest request = ((FilterInvocation) object).getRequest(); Set allAttributes = new HashSet<>(); ConfigAttribute configAttribute = new UrlConfigAttribute(request); allAttributes.add(configAttribute); return allAttributes; } @Override public Collection getAllConfigAttributes() { return null; } @Override public boolean supports(Class<?> clazz) { return FilterInvocation.class.isAssignableFrom(clazz); } }
5.自定义voter实现
public class UrlMatchVoter implements AccessDecisionVoter