黄鼠狼在养鸡场山崖边立了块碑,写道:“不勇敢地飞下去,你怎么知道自己原来是一只搏击长空的鹰?!” 从此以后 黄鼠狼每天都能在崖底吃到那些摔死的鸡!
 
 
 前言
 上周五有网友问道,在使用spring-security-oauth2时,虽然配置了.antMatchers("/permitAll").permitAll(),但如果在header 中 携带 Authorization Bearer xxxx,OAuth2AuthenticationProcessingFilter还是会去校验Token的正确性,如果Token合法,可以正常访问,否则,请求失败。他的需求是当配置.permitAll()时,即使携带Token,也可以直接访问。
 解决思路
 根据Spring Security源码分析一:Spring Security认证过程得知spring-security的认证为一系列过滤器链。我们只需定义一个比OAuth2AuthenticationProcessingFilter更早的过滤器拦截指定请求,去除header中的Authorization Bearer xxxx即可。
 代码修改
 添加PermitAuthenticationFilter类
 添加PermitAuthenticationFilter类拦截指定请求,清空header中的Authorization Bearer xxxx
 @Component("permitAuthenticationFilter") @Slf4j public class PermitAuthenticationFilter extends OncePerRequestFilter {      @Override     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {          log.info("当前访问的地址:{}", request.getRequestURI());         if ("/permitAll".equals(request.getRequestURI())) {              request = new HttpServletRequestWrapper(request) {                 private Set<String> headerNameSet;                  @Override                 public Enumeration<String> getHeaderNames() {                     if (headerNameSet == null) {                         // first time this method is called, cache the wrapped request's header names:                         headerNameSet = new HashSet<>();                         Enumeration<String> wrappedHeaderNames = super.getHeaderNames();                         while (wrappedHeaderNames.hasMoreElements()) {                             String headerName = wrappedHeaderNames.nextElement();                             if (!"Authorization".equalsIgnoreCase(headerName)) {                                 headerNameSet.add(headerName);                             }                         }                     }                     return Collections.enumeration(headerNameSet);                 }                  @Override                 public Enumeration<String> getHeaders(String name) {                     if ("Authorization".equalsIgnoreCase(name)) {                         return Collections.<String>emptyEnumeration();                     }                     return super.getHeaders(name);                 }                  @Override                 public String getHeader(String name) {                     if ("Authorization".equalsIgnoreCase(name)) {                         return null;                     }                     return super.getHeader(name);                 }             };          }         filterChain.doFilter(request, response);      } }  
 添加PermitAllSecurityConfig配置
 添加PermitAllSecurityConfig配置用于配置PermitAuthenticationFilter
 @Component("permitAllSecurityConfig") public class PermitAllSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain,HttpSecurity> {      @Autowired     private Filter permitAuthenticationFilter;      @Override     public void configure(HttpSecurity http) throws Exception {         http.addFilterBefore(permitAuthenticationFilter, OAuth2AuthenticationProcessingFilter.class);     } }  
 修改MerryyouResourceServerConfig,增加对制定路径的授权
  @Override     public void configure(HttpSecurity http) throws Exception {          // @formatter:off         http.formLogin()                 .successHandler(appLoginInSuccessHandler)//登录成功处理器                 .and()                 .apply(permitAllSecurityConfig)                 .and()                 .authorizeRequests()                 .antMatchers("/user").hasRole("USER")                 .antMatchers("/forbidden").hasRole("ADMIN")                 .antMatchers("/permitAll").permitAll()                 .anyRequest().authenticated().and()                 .csrf().disable();          // @formatter:ON     } 
  修改测试类SecurityOauth2Test
 添加permitAllWithTokenTest方法
     @Test     public void permitAllWithTokenTest() throws Exception{         final String accessToken = obtainAccessToken();         log.info("access_token={}", accessToken);         String content = mockMvc.perform(get("/permitAll").header("Authorization", "bearer " + accessToken+"11"))                 .andExpect(status().isOk())                 .andReturn().getResponse().getContentAsString();         log.info(content);     } 
  - Authorization bearer xxx 11后面随机跟了两个参数
效果如下
 不配置permitAllSecurityConfig时
 
 配置permitAllSecurityConfig时
 
 代码下载
  推荐文章
  - Java创建区块链系列
- Spring Security源码分析系列
- Spring Data Jpa 系列
- 【译】数据结构中关于树的一切(java版)
- SpringBoot+Docker+Git+Jenkins实现简易的持续集成和持续部署
 