当前位置: 首页 > 后端技术 > Java

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

时间:2023-04-01 20:54:51 Java

大家好,我是陈老师~最近订阅《Spring Cloud Alibaba 项目实战》的朋友想给陈老师补充一些关于SpringSecurityOAuth2.0的知识,如下:今天这篇文章是回答其中一个问题:如何自定义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{}那么就很容易知道在哪里定义了,自己模仿它的接口重新定义一个overwrite,如下:@Api(value="OAuth接口")@RestController@RequestMapping("/oauth")@Slf4j公共类AuthControllerimplementsInitializingBean{//令牌请求端点@AutowiredprivateTokenEndpointtokenEndpoint;//自定义异常翻译器,处理用户名、密码异常、授权类型不支持的异常privateOAuthServerWebResponseExceptionTranslatortranslate;/***Rewrite/oauth/token为默认接口,返回数据格式统一*/@PostMapping(value="/token")publicResultMsgpostAccessToken(Principalprincipal,@RequestParamMap参数)抛出HttpRequestMethodNotSupportedException{OAuth2AccessTokenaccess=tokenEndpoint.postAccessToken(principal,parameters).getBody();返回ResultMsg.resultSuccess(accessToken);可以看到接口本身不需要重写逻辑,调用TokenEndpoint中的方法即可注:由于TokenEndpoint中的端点被重写了,所以之前定义的翻译类(OAuthServerWebResponseExceptionTranslator)用于捕获用户名和密码等异常会失效,需要在全局异常中捕获。上面的接口是/oauth/token,学校的/oauth/check_token也是可以自定义token验证接口的。对应的类是org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint。改写后的代码如下:@Api(value="OAuthinterface")@RestController@RequestMapping("/oauth")@Slf4jpublicclassAuthControllerimplementsInitializingBean{@AutowiredprivateCheckTokenEndpointcheckTokenEndpoint;//自定义异常翻译器,用于用户名密码异常,授权类型不支持的异常ProcessprivateOAuthServerWebResponseExceptionTranslatortranslate;/***重写/oauth/check_token默认接口,用于验证token,返回数据格式统一*/@PostMapping(value="/check_token")publicResultMsg>checkToken(@RequestParam("token")Stringvalue){Mapmap=checkTokenEndpoint.checkToken(value);returnResultMsg.resultSuccess(map);}这种方式是不是很优雅?也是在符合SpringSecurity的设计思路,AOP方式需要解析参数,重新打包,关于测试,自己动手。总结本文介绍了认证服务中token返回格式的自定义。总的来说还是比较简单的,有兴趣的也可以去网上了解一下AOP的方法。