1

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:

  1. Use AOP to intercept and modify the result of this interface /oauth/token
  2. 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.


码猿技术专栏
486 声望105 粉丝