激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - JAVA教程 - SpringCloud Alibaba實戰之 Oauth2認證服務器自定義異常

SpringCloud Alibaba實戰之 Oauth2認證服務器自定義異常

2021-02-05 01:07JAVA日知錄單一色調 JAVA教程

今天內容主要是解決一位粉絲提的問題:在使用 Spring Security OAuth2 時如何自定義認證服務器返回異常。

SpringCloud Alibaba實戰之 Oauth2認證服務器自定義異常

前言

今天內容主要是解決一位粉絲提的問題:在使用 Spring Security OAuth2 時如何自定義認證服務器返回異常。

那么首先我們先以 Password模式為例看看在認證時會出現哪些異常情況。

授權模式錯誤

這里我們故意將授權模式 password 修改成 password1,認證服務器返回如下所示的異常

  "error""unsupported_grant_type"

  "error_description""Unsupported grant type: password1" 

密碼錯誤

在認證時故意輸錯 username 或 password 會出現如下異常錯誤:

  "error""invalid_grant"

  "error_description""Bad credentials" 

客戶端錯誤

在認證時故意輸錯 client_id 或 client

  "error""invalid_client"

  "error_description""Bad client credentials" 

上面的返回結 

上面的返回結果很不友好,而且前端代碼也很難判斷是什么錯誤,所以我們需要對返回的錯誤進行統一的異常處理,讓其返回統一的異常格式。

問題剖析

如果只關注解決方案,可以直接跳轉到解決方案模塊!

OAuth2Exception異常處理

在Oauth2認證服務器中認證邏輯最終調用的是 TokenEndpoint#postAccessToken()方法,而一旦認證出現 OAuth2Exception異常則會被 handleException()捕獲到異常。如下圖展示的是當出現用戶密碼異常時debug截圖:

SpringCloud Alibaba實戰之 Oauth2認證服務器自定義異常

認證服務器在捕獲到 OAuth2Exception后會調用 WebResponseExceptionTranslator#translate()方法對異常進行翻譯處理。

默認的翻譯處理實現類是 DefaultWebResponseExceptionTranslator,處理完成后會調用 handleOAuth2Exception()方法將處理后的異常返回給前端,這就是我們之前看到的異常效果。

處理方法熟悉Oauth2套路的同學應該知道了如何處理此類異常,就是「自定義一個異常翻譯類讓其返回我們需要的自定義格式,然后將其注入到認證服務器中?!?/p>

但是這種處理邏輯只能解決 OAuth2Exception異常,即前言部分中的「授權模式異常」和「賬號密碼類的異?!?,并不能解決我們客戶端的異常。

客戶端異常處理

客戶端認證的異常是發生在過濾器 ClientCredentialsTokenEndpointFilter上,其中有后置添加失敗處理方法,最后把異常交給 OAuth2AuthenticationEntryPoint這個所謂認證入口處理。執行順序如下所示:

SpringCloud Alibaba實戰之 Oauth2認證服務器自定義異常

然后跳轉到父類的 AbstractOAuth2SecurityExceptionHandler#doHandle()進行處理:

SpringCloud Alibaba實戰之 Oauth2認證服務器自定義異常

最終由 DefaultOAuth2ExceptionRenderer#handleHttpEntityResponse()方法將異常輸出給客戶端

SpringCloud Alibaba實戰之 Oauth2認證服務器自定義異常

處理方法

通過上面的分析我們得知客戶端的認證失敗異常是過濾器 ClientCredentialsTokenEndpointFilter轉交給 OAuth2AuthenticationEntryPoint得到響應結果的,既然這樣我們就可以重寫 ClientCredentialsTokenEndpointFilter然后使用自定義的 AuthenticationEntryPoint替換原生的 OAuth2AuthenticationEntryPoint,在自定義 AuthenticationEntryPoint處理得到我們想要的異常數據。

解決方案

為了解決上面這些異常,我們首先需要編寫不同異常的錯誤代碼:ReturnCode.java

  • CLIENT_AUTHENTICATION_FAILED(1001,"客戶端認證失敗"), 
  • USERNAME_OR_PASSWORD_ERROR(1002,"用戶名或密碼錯誤"), 
  • UNSUPPORTED_GRANT_TYPE(1003, "不支持的認證模式"); 

OAuth2Exception異常

@Slf4j 

public class CustomWebResponseExceptionTranslator implements WebResponseExceptionTranslator { 

 

    @Override 

    public ResponseEntity<ResultData<String>> translate(Exception e) throws Exception { 

        log.error("認證服務器異常",e); 

 

        ResultData<String> response = resolveException(e); 

 

        return new ResponseEntity<>(response, HttpStatus.valueOf(response.getHttpStatus())); 

    } 

 

    /** 

     * 構建返回異常 

     * @param e exception 

     * @return 

     */ 

    private ResultData<String> resolveException(Exception e) { 

        // 初始值 500 

        ReturnCode returnCode = ReturnCode.RC500; 

        int httpStatus = HttpStatus.UNAUTHORIZED.value(); 

        //不支持的認證方式 

        if(e instanceof UnsupportedGrantTypeException){ 

            returnCode = ReturnCode.UNSUPPORTED_GRANT_TYPE; 

        //用戶名或密碼異常 

        }else if(e instanceof InvalidGrantException){ 

            returnCode = ReturnCode.USERNAME_OR_PASSWORD_ERROR; 

        } 

 

        ResultData<String> failResponse = ResultData.fail(returnCode.getCode(), returnCode.getMessage()); 

        failResponse.setHttpStatus(httpStatus); 

 

        return failResponse; 

    } 

 

然后在認證服務器配置類中注入自定義異常翻譯類

@Override 

public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 

    //如果需要使用refresh_token模式則需要注入userDetailService 

    endpoints 

            .authenticationManager(this.authenticationManager) 

            .userDetailsService(userDetailService) 

//                注入tokenGranter 

            .tokenGranter(tokenGranter); 

            //注入自定義的tokenservice,如果不使用自定義的tokenService那么就需要將tokenServce里的配置移到這里 

//                .tokenServices(tokenServices()); 

    // 自定義異常轉換類 

    endpoints.exceptionTranslator(new CustomWebResponseExceptionTranslator()); 

客戶端異常

重寫客戶端認證過濾器,不使用默認的 OAuth2AuthenticationEntryPoint處理異常

public class CustomClientCredentialsTokenEndpointFilter extends ClientCredentialsTokenEndpointFilter { 

 

    private final AuthorizationServerSecurityConfigurer configurer; 

 

    private AuthenticationEntryPoint authenticationEntryPoint; 

 

    public CustomClientCredentialsTokenEndpointFilter(AuthorizationServerSecurityConfigurer configurer) { 

        this.configurer = configurer; 

    } 

 

    @Override 

    public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) { 

        super.setAuthenticationEntryPoint(null); 

        this.authenticationEntryPoint = authenticationEntryPoint; 

    } 

 

    @Override 

    protected AuthenticationManager getAuthenticationManager() { 

        return configurer.and().getSharedObject(AuthenticationManager.class); 

    } 

 

    @Override 

    public void afterPropertiesSet() { 

        setAuthenticationFailureHandler((request, response, e) -> authenticationEntryPoint.commence(request, response, e)); 

        setAuthenticationSuccessHandler((request, response, authentication) -> { 

        }); 

    } 

在認證服務器注入異常處理邏輯,自定義異常返回結果。(代碼位于 AuthorizationServerConfig)

@Bean 

public AuthenticationEntryPoint authenticationEntryPoint() { 

    return (request, response, e) -> { 

        response.setStatus(HttpStatus.UNAUTHORIZED.value()); 

        ResultData<String> resultData = ResultData.fail(ReturnCode.CLIENT_AUTHENTICATION_FAILED.getCode(), ReturnCode.CLIENT_AUTHENTICATION_FAILED.getMessage()); 

        WebUtils.writeJson(response,resultData); 

    }; 

修改認證服務器配置,注入自定義過濾器

@Override 

public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { 

 CustomClientCredentialsTokenEndpointFilter endpointFilter = new CustomClientCredentialsTokenEndpointFilter(security); 

 endpointFilter.afterPropertiesSet(); 

 endpointFilter.setAuthenticationEntryPoint(authenticationEntryPoint()); 

 security.addTokenEndpointAuthenticationFilter(endpointFilter); 

 

 security 

   .authenticationEntryPoint(authenticationEntryPoint()) 

     /* .allowFormAuthenticationForClients()*/ //如果使用表單認證則需要加上 

   .tokenKeyAccess("permitAll()"

   .checkTokenAccess("isAuthenticated()"); 

此時需要刪除 allowFormAuthenticationForClients()配置,否則自定義的過濾器不生效,至于為什么不生效大家看看源碼就知道了。

測試

授權模式錯誤

SpringCloud Alibaba實戰之 Oauth2認證服務器自定義異常

賬號密碼錯誤

SpringCloud Alibaba實戰之 Oauth2認證服務器自定義異常

客戶端錯誤

SpringCloud Alibaba實戰之 Oauth2認證服務器自定義異常

以上,希望對你有所幫助!

原文地址:https://mp.weixin.qq.com/s/JwDTdone_8DV7wlr_CWZpw

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 亚洲国产成人久久成人52 | 欧美性受xxxx人人本视频 | 午夜视频在线观看免费视频 | 欧美另类视频在线 | 久久久久一本一区二区青青蜜月 | 日本68xxxx | 久久久成人精品 | 亚洲不卡| 国产乱色精品成人免费视频 | av免费在线观看免费 | 国产亚洲精品久久久久久久久久 | 国产一国产精品一级毛片 | 久久精品国产久精国产 | 99精品国产成人一区二区 | 成人毛片视频在线观看 | 国产亚洲精品视频中文字幕 | 72pao成人国产永久免费视频 | 国产一区二区国产 | 日本在线看| 高清中文字幕在线 | 国产亚洲精品久久久久久网站 | 性欧美在线视频 | 毛片视频网站 | 精品亚洲视频在线 | 天堂在线资源av | 欧美xxxwww | 久久网站热最新地址4 | 国产午夜精品久久久久久免费视 | 日本高清电影在线播放 | 欧美性猛交xxxxx按摩国内 | 一区二区精品视频 | 中午日产幕无线码1区 | 亚洲三区精品 | 成人在线视频免费播放 | 综合国产在线 | 精精国产xxxx视频在线播放7 | 极品大长腿啪啪高潮露脸 | 久久污| 欧美日韩一 | 国内自拍网址 | 欧美成人精品一区二区三区 |