關於Oauth2的微服務接口:正常數據和異常數據如何自定義統一的數據格式


在基於Oauth2的微服務項目中,往往希望有統一格式的數據返回,包括以下四種情況:

  • Oauth2異常數據的封裝
    {
        "code": 0,
        "message": "請求失敗",
        "result": "無效token"
    }  
  • Oauth2正常數據的封裝
    {
        "code": 1,
        "message": "請求成功",
        "result": {
            "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
            "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
            "exp": "1596721265802"
        }
    }
  • 接口異常數據的封裝
    {
        "code": 0,
        "message": "請求失敗",
        "result": "異常信息"
    }
  • 接口正常數據的封裝
    {
        "code": 1,
        "message": "請求成功",
        "result": "接口數據"
    } 

針對上述四種情況進行處理:

1.Oauth2異常數據的封裝:

是四種情況中相對最為復雜的部分:分為認證服務器的異常信息處理和資源服務器的異常信息處理

1.1認證服務器的異常信息處理(通常是獲取token時拋出的異常)

①需要在AuthorizationServerConfigurerAdapter的AuthorizationServerEndpointsConfigurer進行配置

   endpoints.exceptionTranslator(customWebResponseExceptionTranslator)//自定義異常處理
   //配置WebResponseExceptionTranslator自定義異常,並重寫translate方法返回自定義Oauth2認證異常信息

②由於在AuthorizationServerEndpointsConfigurer無法重寫客戶端配置信息異常,需要進行另行處理

 需要在AuthorizationServerConfigurerAdapter的AuthorizationServerSecurityConfigurer進行配置  

   CustomClientCredentialsTokenEndpointFilter endpointFilter = new CustomClientCredentialsTokenEndpointFilter(security);
   endpointFilter.afterPropertiesSet();
   endpointFilter.setAuthenticationEntryPoint(customAuthenticationEntryPoint);
   security.addTokenEndpointAuthenticationFilter(endpointFilter);//自定義異常過濾器和客戶端端點過濾器
   //配置ClientCredentialsTokenEndpointFilter自定義過濾器,並加入AuthenticationEntryPoint重寫commence方法,自定義返回Oauth2異常信息。

1.2資源服務器的異常信息處理(驗證token時拋出的異常):包括認證異常和授權異常的配置

   //在資源服務器ResourceServerConfigurerAdapter的ResourceServerSecurityConfigurer中配置
   resources.authenticationEntryPoint(customAuthExceptionEntryPoint)//認證異常處理類
   resources.accessDeniedHandler(customAccessDeniedHandler)//權限異常處理類

配置認證異常處理AuthenticationEntryPoint,重寫commence方法,自定義Oauth2異常信息。

配置授權異常處理AccessDeniedHandler,重寫handle方法,自定義Oauth2異常信息。

2.Oauth2正常數據的封裝

使用aop重寫oauth2的TokenEndpoint.postAccessToken結果

  //類注解@Component和@Aspect
  @Around("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))")
  //獲取原有方法返回值為ResponseEntity<OAuth2AccessToken> responseEntity 
  //將responseEntity 中需要的信息放入map中,返回
  return ResponseEntity.status(HttpStatus.OK).body(map);
  //這里直接返回map,數據格式會在后續統一處理。
  //同樣如果需要也可以通過aop重寫CheckTokenEndpoint.checkToken

3.接口異常數據和正常數據的封裝 

//這里為了方便將異常和數據放在一起進行處理(RestResponse為定義的統一數據類)
  @ControllerAdvice
  public class GlobalExceptionHandler implements ResponseBodyAdvice {
    private ObjectMapper objectMapper = new ObjectMapper();
   //統一異常處理
  @ExceptionHandler(value = Exception.class)
  @ResponseBody
  public RestResponse<Object> exceptionHandler(HttpServletRequest req, Exception e){
  return RestResponse.failure(e.getMessage());
  }

   //統一數據處理
  @Override
  public boolean supports(MethodParameter methodParameter, Class aClass) {
  return true;
  }
  
  @Override
  public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass,
    ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {   
//String類型返回會發生類型轉換異常,額外處理     if (o instanceof String) {       try {         serverHttpResponse.getHeaders().set("Content-Type", "application/json;charset=utf-8");         return objectMapper.writeValueAsString(RestResponse.success(o));       } catch (JsonProcessingException e) {         e.printStackTrace();       }     }else if(o instanceof RestResponse){       //原有部分接口已經使用RestResponse包裝過,防止重復包裝。       return o;     }     //統一數據包裝,包括Oauth2的正常數據(Oauth2的異常數據已經直接),Oauth2的異常數據已經直接httpServletResponse.getWriter().write()不需要處理     return RestResponse.success(o);    } }

4.總結

整理總結了在處理基於Oauth2的微服務接口中,正常數據和異常數據自定義統一數據格式的問題。


免責聲明!

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



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