Spring Security Oauth2 permitAll()方法小記


黃鼠狼在養雞場山崖邊立了塊碑,寫道:“不勇敢地飛下去,你怎么知道自己原來是一只搏擊長空的鷹?!”

從此以后

黃鼠狼每天都能在崖底吃到那些摔死的雞!

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/spring-security-OAuth207.png

前言

上周五有網友問道,在使用spring-security-oauth2時,雖然配置了.antMatchers("/permitAll").permitAll(),但如果在header 中 攜帶 Authorization Bearer xxxxOAuth2AuthenticationProcessingFilter還是會去校驗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時

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/security/spring-security-oauth207.gif

配置permitAllSecurityConfig時

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/security/spring-security-oauth208.gif

代碼下載

推薦文章

  1. Java創建區塊鏈系列
  2. Spring Security源碼分析系列
  3. Spring Data Jpa 系列
  4. 【譯】數據結構中關於樹的一切(java版)
  5. SpringBoot+Docker+Git+Jenkins實現簡易的持續集成和持續部署

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/wechat/xiaochengxu.png

🙂🙂🙂關注微信小程序java架構師歷程
上下班的路上無聊嗎?還在看小說、新聞嗎?不知道怎樣提高自己的技術嗎?來吧這里有你需要的java架構文章,1.5w+的java工程師都在看,你還在等什么?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM