说明 springboot 版本 2.0.3
源码地址:点击跳转
系列
这篇讲解如何自定义鉴权过程,实现根据数据库查询出的 url 和 method 是否匹配当前请求的 url 和 method 来决定有没有权限。security 鉴权过程如下:

- 编写 MyGranteAuthority 类,让权限包含 url 和 method 两个部分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class MyGrantedAuthority implements GrantedAuthority { private String method; private String url;
public MyGrantedAuthority(String method, String url) { this.method = method; this.url = url; }
@Override public String getAuthority() { return url; }
public String getMethod() { return method; }
public String getUrl() { return url; }
@Override public boolean equals(Object obj) { if(this==obj) return true; if(obj==null||getClass()!= obj.getClass()) return false; MyGrantedAuthority grantedAuthority = (MyGrantedAuthority)obj; if(this.method.equals(grantedAuthority.getMethod())&&this.url.equals(grantedAuthority.getUrl())) return true; return false; } }
|
- 编写 MyConfigAttribute 类,实现 ConfigAttribute 接口,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class MyConfigAttribute implements ConfigAttribute { private HttpServletRequest httpServletRequest; private MyGrantedAuthority myGrantedAuthority;
public MyConfigAttribute(HttpServletRequest httpServletRequest) { this.httpServletRequest = httpServletRequest; }
public MyConfigAttribute(HttpServletRequest httpServletRequest, MyGrantedAuthority myGrantedAuthority) { this.httpServletRequest = httpServletRequest; this.myGrantedAuthority = myGrantedAuthority; }
public HttpServletRequest getHttpServletRequest() { return httpServletRequest; }
@Override public String getAttribute() { return myGrantedAuthority.getUrl(); }
public MyGrantedAuthority getMyGrantedAuthority() { return myGrantedAuthority; } }
|
- 编写 MySecurityMetadataSource 类,获取当前 url 所需要的权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| @Component public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
private Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired private JurisdictionMapper jurisdictionMapper; private List<Jurisdiction> jurisdictions;
private void loadResource() { this.jurisdictions = jurisdictionMapper.selectAllPermission(); }
@Override public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { if (jurisdictions == null) this.loadResource(); HttpServletRequest request = ((FilterInvocation) object).getRequest(); Set<ConfigAttribute> allConfigAttribute = new HashSet<>(); AntPathRequestMatcher matcher; for (Jurisdiction jurisdiction : jurisdictions) { matcher = new AntPathRequestMatcher(jurisdiction.getUrl(), jurisdiction.getMethod()); if (matcher.matches(request)) { ConfigAttribute configAttribute = new MyConfigAttribute(request,new MyGrantedAuthority(jurisdiction.getMethod(),jurisdiction.getUrl())); allConfigAttribute.add(configAttribute); return allConfigAttribute; } } return null; }
@Override public Collection<ConfigAttribute> getAllConfigAttributes() { return null; }
@Override public boolean supports(Class<?> clazz) { return FilterInvocation.class.isAssignableFrom(clazz); } }
|
二、 编写 MyAccessDecisionManager 类
实现 AccessDecisionManager 接口以实现权限判断,直接 return 说明验证通过,如不通过需要抛出对应错误,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| @Component public class MyAccessDecisionManager implements AccessDecisionManager{ private Logger log = LoggerFactory.getLogger(this.getClass());
@Override public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { if(configAttributes==null || configAttributes.size()==0) return; if(!authentication.isAuthenticated()){ throw new InsufficientAuthenticationException("未登录"); } Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities(); for(ConfigAttribute attribute : configAttributes){ MyConfigAttribute urlConfigAttribute = (MyConfigAttribute)attribute; for(GrantedAuthority authority: authorities){ MyGrantedAuthority myGrantedAuthority = (MyGrantedAuthority)authority; if(urlConfigAttribute.getMyGrantedAuthority().equals(myGrantedAuthority)) return; } } throw new AccessDeniedException("无权限"); }
@Override public boolean supports(ConfigAttribute attribute) { return true; }
@Override public boolean supports(Class<?> clazz) { return true; } }
|
三、 编写 MyFilterSecurityInterceptor 类
该类继承 AbstractSecurityInterceptor 类,实现 Filter 接口,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| @Component public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
@Autowired private MySecurityMetadataSource mySecurityMetadataSource;
@Autowired public void setMyAccessDecisionManager(MyAccessDecisionManager myAccessDecisionManager) { super.setAccessDecisionManager(myAccessDecisionManager); }
@Override public void init(FilterConfig arg0) throws ServletException { }
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response, chain); invoke(fi); }
public void invoke(FilterInvocation fi) throws IOException, ServletException { InterceptorStatusToken token = super.beforeInvocation(fi); try { fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } finally { super.afterInvocation(token, null); } }
@Override public void destroy() { }
@Override public Class<?> getSecureObjectClass() { return FilterInvocation.class; }
@Override public SecurityMetadataSource obtainSecurityMetadataSource() { return this.mySecurityMetadataSource; } }
|
四、 加入到 security 的过滤器链中
1
| .addFilterBefore(urlFilterSecurityInterceptor,FilterSecurityInterceptor.class)
|
完成
如果本篇文章对您有帮助欢迎打赏哦!
关注公众号(烦嚣的人)