黄鼠狼在养鸡场山崖边立了块碑,写道:“不勇敢地飞下去,你怎么知道自己原来是一只搏击长空的鹰?!”
从此以后
黄鼠狼每天都能在崖底吃到那些摔死的鸡!
上周五有网友问道,在使用 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
类拦截指定请求,清空 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
配置用于配置 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); } }
@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 }
添加 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
后面随机跟了两个参数