spring boot spring security 自定义 filter FilterSecurityInterceptor 访问资源 静态资源 和 不需要权限访问都失效了

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/laokaizzz/article/details/82460319

问题:spring boot security 中, filters="none"  对应哪个?

自定义AbstractSecurityInterceptor后  静态资源也进入拦截器,登陆页面,permitall 也失效,
还是进入了filter

参考:http://blog.51cto.com/winters1224/2052034

调试源代码发现,采用默认的 FilterSecurityInterceptor 过滤器 时,使用默认的DefaultFilterInvocationSecurityMetadataSource

里面的requestmap加载了对应的antMatchers("xxxx","xxx").permitAll()  里面的url 作为key,并且value 里面设置为permitAll

,后面默认的决策器就是因为这个permitAll,所以容许访问。

(FilterSecurityInterceptor 里的

AbstractSecurityInterceptor 里的beforeInvocation 会调用  DefaultFilterInvocationSecurityMetadataSource 的getAttributes
然后 里面会访问
private final Map<RequestMatcher, Collection<ConfigAttribute>> requestMap;
刚好是permitall。所以ok.

antMatchers permitall 这种是 对应这个ExpressionUrlAuthorizationConfigurer,而这个是对应的过滤器 FilterSecurityInterceptor,所以自己定义的里面没有?是这个原因么?

如果自定义FilterSecurityInterceptor 确实是走的自己的decide方法,那肯定默认的FilterSecurityInterceptor就没走了。默认的decide方法 AffirmativeBased 类中的decide方法

于是想了一下,自定义FilterSecurityInterceptor 如果放到 默认的FilterSecurityInterceptor 后面,如下

http.addFilterAfter(customFilterSecurityInterceptor, FilterSecurityInterceptor.class)

先走的 默认的FilterSecurityInterceptor ,那么应该就可以了。结果发现,是默认的FilterSecurityInterceptor 是通过了,但是还是会接着往下走剩余的过滤器(自定义的FilterSecurityInterceptor),又卡住了。

于是想着要么重写他的decide吧。复制过来。可是一看太麻烦了。算了。如下:
public void decide(Authentication authentication, Object object,
      Collection<ConfigAttribute> configAttributes) throws AccessDeniedException {
   int deny = 0;

   for (AccessDecisionVoter voter : getDecisionVoters()) {
      int result = voter.vote(authentication, object, configAttributes);

      if (logger.isDebugEnabled()) {
         logger.debug("Voter: " + voter + ", returned: " + result);
      }

      switch (result) {
      case AccessDecisionVoter.ACCESS_GRANTED:
         return;

      case AccessDecisionVoter.ACCESS_DENIED:
         deny++;

         break;

      default:
         break;
      }
   }

   if (deny > 0) {
      throw new AccessDeniedException(messages.getMessage(
            "AbstractAccessDecisionManager.accessDenied", "Access is denied"));
   }

   // To get this far, every AccessDecisionVoter abstained
   checkAllowIfAllAbstainDecisions();
}

具体再细一点的细节,跟的脑袋晕,不跟了,先到这里。

)

参考:http://www.tianshouzhi.com/api/tutorials/spring_security_4/264

public class DefaultFilterInvocationSecurityMetadataSource implements
      FilterInvocationSecurityMetadataSource {

   protected final Log logger = LogFactory.getLog(getClass());

   private final Map<RequestMatcher, Collection<ConfigAttribute>> requestMap;

.......................................

public Collection<ConfigAttribute> getAttributes(Object object) {
   final HttpServletRequest request = ((FilterInvocation) object).getRequest();
   for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : requestMap
         .entrySet()) {
      if (entry.getKey().matches(request)) {
         return entry.getValue();
      }
   }
   return null;
}

另外要说的就是permitall 还是要走所有的过滤器,直到最后一个过滤器FilterSecurityInterceptor 认定是可以放过的,才能访问。

所以如果有些不需要设置权限的,就放到web.ignoring() 中。因为总的是两个大的过滤器,一个是忽略的过滤器,一个是11个过滤器链。

@Override
public void configure(WebSecurity web) throws Exception {
    //解决静态资源被拦截的问题
    web.ignoring().antMatchers("/res/**");
}

如图,

断点是org.springframework.security.web的 FilterChainProxy类,从chain中看得到,4是springsecurity的过滤链。其他是系统的。

然后springsecurity 里面有两个大的,第一个就是对应不拦截的,filters是0,表示匹配"/res/**" 路径的不用任何拦截器。

第二个,就是大的过滤链,一共12个,里面有我自己定义的一个。原始的是11个。

结论就是就放到web.ignoring() 中 不进入这些过滤器就是最好最高效的。

其他参考:http://www.blogjava.net/SpartaYew/archive/2011/06/15/350630.html

猜你喜欢

转载自blog.csdn.net/laokaizzz/article/details/82460319
今日推荐