Spring Security -- FilterInvocationSecurityMetadataSource 与 AccessDecisionManager
FilterInvocationSecurityMetadataSource
前言
FilterInvocationSecurityMetadataSource 翻译过来叫做:过滤器调用安全元数据源。一般情况下,我们如果需要自定义权限拦截,则需要涉及到 FilterInvocationSecurityMetadataSource 这个接口了。
继承关系
FilterInvocationSecurityMetadataSource 有一个默认的实现类 DefaultFilterInvocationSecurityMetadataSource,该类的主要功能就是通过当前的请求地址,获取该地址需要的用户角色。
FilterInvocationSecurityMetadataSource 接口是一个空接口,没有任何方法,它继承自接口 SecurityMetadataSource,接口 SecurityMetadataSource 的源码如下:
public interface SecurityMetadataSource extends AopInfrastructureBean {
Collection<ConfigAttribute> getAttributes(Object var1) throws IllegalArgumentException;
Collection<ConfigAttribute> getAllConfigAttributes();
boolean supports(Class<?> var1);
}
用法
示例:
@Component
public class CustomFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
@Autowired
MenuService menuService;
// AntPathMatcher 是一个正则匹配工具
AntPathMatcher antPathMatcher = new AntPathMatcher();
@Override
public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
String requestUrl = ((FilterInvocation) o).getFullRequestUrl();
List<Menu> menus = menuService.getAllMenusWithRole();
for (Menu menu: menus){
if (antPathMatcher.match(menu.getUrl(), requestUrl)){
List<Role> roles = menu.getRoles();
String[] str = new String[roles.size()];
for (int i=0; i<roles.size(); i++){
str[i] = roles.get(i).getName();
}
return SecurityConfig.createList(str);
}
}
// 没有匹配上的,只要登录之后就可以访问,这里“ROLE_LOGIN”只是一个标记,有待进一步处理。
return SecurityConfig.createList("ROLE_LOGIN");
}
...
}
这个类的作用是根据用户传来的请求地址,分析请求需要的角色,并将所需要的角色放在 Collection
中
AccessDecisionManager
前言
AccessDecisionManager 顾名思义,访问决策管理器。AccessDecisionManager 是一个接口,它有三个实现类:
- AffirmativeBased (默认使用这个)
- ConsensusBased
- UnanimousBased
用法
示例
@Component
public class CustomUrlDecisionManager implements AccessDecisionManager {
@Override
// 用户的角色在 authentication里,资源需要的角色在 collection 中
public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
for (ConfigAttribute configAttribute : collection) {
String needRole = configAttribute.getAttribute();
if ("ROLE_LOGIN".equals(needRole)){
if (authentication instanceof AnonymousAuthenticationToken){
throw new AccessDeniedException("尚未登录,请登录!");
}else {
return;
}
}
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
for (GrantedAuthority authority : authorities) {
if (authority.getAuthority().equals(needRole)){
return;
}
}
}
throw new AccessDeniedException("权限不足,请联系管理员!");
}
...
}
这个类的作用:判断当前用户是否具备指定的角色。
当前用户的角色在 authentication
中,需要的角色在 collection
中,
参考资源
https://blog.csdn.net/lichuangcsdn/article/details/95041605
https://wangsong.blog.csdn.net/article/details/79019510
https://blog.csdn.net/liuminglei1987/article/details/107904526
每天学习一点点,每天进步一点点。