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

每天学习一点点,每天进步一点点。

posted @ 2021-03-31 18:21  爱吃西瓜的番茄酱  阅读(4132)  评论(0编辑  收藏  举报