一文解决Security中访问静态资源和web.ignoring()和perimitAll()不起作用

本文参考

【1】江南一点雨的SpringSecurity配置
【2】WebMvcConfiguer配置

问题需求

学习微人事项目中,我想在后端加入静态资源,我的静态资源就在static目录下,可怎么配置都返回需要权限认证,调试后发现,如下代码访问的所有路径,都会进到FilterInvocationSecurityMetadataSource中进行处理,松哥原话

getAttributes(Object o)方法返回null的话,意味着当前这个请求不需要任何角色就能访问,甚至不需要登录

在这里插入图片描述
代码可修改如下(初始版本),后有通用解决方案

@Component
public class CusomFilterIncovationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

    @Autowired
    MenuService menuService;
    // ant路径匹配的类
    AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
        String requestUrl = ((FilterInvocation) o).getRequestUrl();
        List<Menu> menus = menuService.getAllMenusRole();
        System.out.println("开始匹配路径");
        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);
            }
        }
        //静态资源配置,返回null表示不要任何角色即可访问
        for(String url: StaticSource.source){
            //System.out.println(url);
            //System.out.println(requestUrl);
            if(antPathMatcher.match(url,requestUrl)){
                return null;
            }
        }
        // 标记而已
        return SecurityConfig.createList("ROLE_LOGIN");
    }

    @Override
    // 不用管
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}
@Component
public class CustomUrlDecisionManager implements AccessDecisionManager {
    @Override
    /**
     * @param:
     * authentication 用户登陆信息
     * collection Filter的返回值
     */
    public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
        //System.out.println(collection.size());
        //System.out.println(collection);
        // 修改内容
        if(collection == null || collection.isEmpty()){
            return;
        }
        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();
            // A,B两个角色有一个即可访问
            for (GrantedAuthority authority:authorities) {
                // 匹配到角色,立刻返回
                if(authority.getAuthority().equals(needRole)){
                    return;
                }
            }
        }
        throw new AccessDeniedException("权限不足,请联系管理员");
    }

    @Override
    public boolean supports(ConfigAttribute configAttribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}
public class StaticSource {
     public static final String[] source = new String[]{"/img/**","/js/**","/css/**","/favicon.ico"};
}
通用解决
 // 不起作用的配置
 @Override
 public void configure(WebSecurity web) throws Exception {
     web.ignoring().antMatchers("/img/**");
 }
 protected void configure(HttpSecurity http) throws Exception {
 	http.authorizeRequests().antMatchers("/img/**").permitAll()
 }

根据参考资料【2】的描述,在SpringBoot2.0中WebMvcConfigurerAdapter已被废弃,访问静态资源就会被HandlerInterceptor拦截,为了防止静态资源被拦截,我们需要实现自己的inteceptor的规则

通用解决方案:

// 创建自己的拦截器类,实现HandlerInterceptor 接口
public class MyInterceptor implements HandlerInterceptor {
}
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/swagger-ui.html","/js/**","/css/**","/img/**");
    }
}

版权声明:本文为weixin_41492426原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。