当前位置: 首页 > 科技观察

一个接口SpringCloudOAuth2自定义token返回格式的优雅实现_0

时间:2023-03-13 16:21:42 科技观察

今天这篇文章就是回答其中一个问题:如何自定义token返回格式?本文对应视频,介绍的比较详细:问题描述SpringSecurityOAuth的token返回格式是默认的,但往往这种格式不适合系统。/oauth/token返回的格式如下:{"access_token":token"token_type":"bearer","refresh_token":xxxx"expires_in":xxx,"scope":"xxx","jti":xxxx.......................}但是此时系统中统一的返回格式为:{"code":xxx"data":xxx"msg":xxx}那么如何修改默认格式呢?解决方案其实解决方案有很多种。据Chen介绍,解决方案有两种:使用AOP拦截修改/oauth/token接口的结果;重新定义接口以覆盖默认值;第一种方案可以实现,但是对Chen来说不够优雅,实现起来比较简单,没有说服力。所以Chen今天介绍了第二种方案,比较优雅的方式;如果你想理解第二种方式,你必须对SpringSecurity的底层源码有一定的了解。/oauth/token接口在哪里定义的?通过源码我们知道在org.springframework.security.oauth2.provider.endpoint.TokenEndpoint中定义,如下:@RequestMapping(value="/oauth/token",method=RequestMethod.GET)publicResponseEntitygetAccessToken(Principalprincipal,@RequestParamMapparameters)throwsHttpRequestMethodNotSupportedException{}@RequestMapping(value="/oauth/token",method=RequestMethod.POST)公共ResponseEntitypostAccessToken(Principalprincipal,@String,StringParam>)throwsHttpRequestMethodNotSupportedException{}可以看到这个接口有两种定义,一种是GET请求,一种是POST请求。TokenEndpoint其实是一个接口,标注了@FrameworkEndpoint注解,这个注解和@Controller的作用是一样的,如下:@FrameworkEndpointpublicclassTokenEndpointextendsAbstractEndpoint{}然后就很容易知道在哪里定义了,模仿自己的interface重新定义一个override,如下:@Api(value="OAuthinterface")@RestController@RequestMapping("/oauth")@Slf4jpublicclassAuthControllerimplementsInitializingBean{//Token请求端点@AutowiredprivateTokenEndpointtokenEndpoint;//自定义异常翻译器,处理用户名、密码、授权类型不支持的异常privateOAuthServerWebResponseExceptionTranslatortranslate;/***重写/oauth/token默认接口,返回数据格式统一*/@PostMapping(value="/token")publicResultMsgpostAccessToken(Principalprincipal,@RequestParamMapparameters)throwsHttpRequestMethodNotSupportedException{OAuth2AccessTokenaccessToken=tokenEndpoint.postAccessToken).parameter(ResultMsg.resultSuccess(accessToken);}}可以看到不需要重写接口里面的逻辑,调用TokenEndpoint即可注意中的方法:由于重写了TokenEndpoint中的endpoint,之前定义的捕获用户名密码等异常的翻译类(OAuthServerWebResponseExceptionTranslator)将失效,需要在全局异常中捕获。以上是/oauth/token的接口,验证token的/oauth/check_token的接口也可以自定义。对应的类是org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint。改写后的代码如下:@Api(value="OAuthinterface")@RestController@RequestMapping("/oauth")@Slf4jpublicclassAuthControllerimplementsInitializingBean{@AutowiredprivateCheckTokenEndpointcheckTokenEndpoint;//用户名、密码异常的自定义异常翻译器,授权类型不支持的异常处理privateOAuthServerWebResponseExceptionTranslatortranslate;/***重写/oauth/check_token默认接口,用于验证token,返回数据格式统一*/@PostMapping(value="/check_token")publicResultMsg>checkToken(@RequestParam("token")Stringvalue){Mapmap=checkTokenEndpoint.checkToken(value);返回ResultMsg.resultSuccess(地图);这不是很优雅吗?也符合SpringSecurity的设计思路。AOP方式需要对参数进行解析,重新打包。如果你想自己做测试,就自己做。总结本文介绍了认证服务中token返回格式的定制。总的来说,还是比较简单的。有兴趣的也可以去网上搜索一下AOP的方法。