Hello everyone, I'm not Cai Chen~
Friends who recently subscribed to "Spring Cloud Alibaba Project Combat" want Chen to add some knowledge about Spring Security OAuth2.0, as follows:
Today's article will answer one of the questions: How to customize the return format of the token?
Problem Description
The token return format of Spring Security OAuth is the default, but often this format is not suitable for the system, /oauth/token
The returned format is as follows:
{
"access_token": token
"token_type": "bearer",
"refresh_token": xxxx
"expires_in": xxx,
"scope": "xxx",
"jti": xxxx
....................
}
However, the unified return format in the system at this time is:
{
"code":xxx
"data":xxx
"msg":xxx
}
So how to modify the default format?
solution
In fact, there are still many solutions. According to Chen, there are two solutions as follows:
- Use AOP to intercept and modify the result of this interface
/oauth/token
- Redefine the interface to override the default
The first solution can be implemented, but it is not elegant enough for Chen, the implementation is relatively simple, and it is not overwhelming
So Chen introduced the second solution today, a more elegant way; to understand the second way, you must have some understanding of the underlying source code of Spring Security.
/oauth/token
Where is this interface defined? Through the source code, we know that the definition is in org.springframework.security.oauth2.provider.endpoint.TokenEndpoint
, as follows:
@RequestMapping(value = "/oauth/token", method=RequestMethod.GET)
public ResponseEntity<OAuth2AccessToken> getAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {}
@RequestMapping(value = "/oauth/token", method=RequestMethod.POST)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {}
You can see that two are defined for this interface, one is a GET request and the other is a POST request
TokenEndpoint
is actually an interface, using the annotation @FrameworkEndpoint
annotation, this annotation and @Controller
function the same, as follows:
@FrameworkEndpoint
public class TokenEndpoint extends AbstractEndpoint {}
Then it's easy to know where to define it, and it's better to redefine an overwrite by imitating the interface, as follows:
@Api(value = "OAuth接口")
@RestController
@RequestMapping("/oauth")
@Slf4j
public class AuthController implements InitializingBean {
//令牌请求的端点
@Autowired
private TokenEndpoint tokenEndpoint;
//自定义异常翻译器,针对用户名、密码异常,授权类型不支持的异常进行处理
private OAuthServerWebResponseExceptionTranslator translate;
/**
* 重写/oauth/token这个默认接口,返回的数据格式统一
*/
@PostMapping(value = "/token")
public ResultMsg<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
OAuth2AccessToken accessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody();
return ResultMsg.resultSuccess(accessToken);
}
}
It can be seen that there is no need to rewrite the logic inside the interface, just call the method in TokenEndpoint
Note: Since the endpoint in TokenEndpoint has been rewritten, the previously defined translation class ( OAuthServerWebResponseExceptionTranslator ) for exception capture such as username and password will be invalid and need to be captured in the global exception
The above is the interface of ---a91b73d17ad1c92617b5bac9b4cca36c---, /oauth/check_token
/oauth/token
the interface of this verification token can also be customized, the corresponding class is org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint
The rewritten code is as follows:
@Api(value = "OAuth接口")
@RestController
@RequestMapping("/oauth")
@Slf4j
public class AuthController implements InitializingBean {
@Autowired
private CheckTokenEndpoint checkTokenEndpoint;
//自定义异常翻译器,针对用户名、密码异常,授权类型不支持的异常进行处理
private OAuthServerWebResponseExceptionTranslator translate;
/**
* 重写/oauth/check_token这个默认接口,用于校验令牌,返回的数据格式统一
*/
@PostMapping(value = "/check_token")
public ResultMsg<Map<String,?>> checkToken(@RequestParam("token") String value) {
Map<String, ?> map = checkTokenEndpoint.checkToken(value);
return ResultMsg.resultSuccess(map);
}
Isn't this way very elegant? It is also in line with the design idea of Spring Security. The AOP method also needs to parse and repackage the parameters.
Okay, let's do it yourself when it comes to testing
Summarize
This article introduces the customization of the return format of the token in the authentication service. Generally speaking, it is relatively simple. If you are interested, you can also go to the Internet to find out about the AOP method.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。