个性化token 背景
oauth2.0 接口默认返回的报文格式如下:
1 2 3 4 5 6 7
| { "access_token": "e6669cdf-b6cd-43fe-af5c-f91a65041382", "token_type": "bearer", "refresh_token": "da91294d-446c-4a89-bdcf-88aee15a75e8", "expires_in": 43199, "scope": "server" }
|
可以扩展增加部分业务字段。
1 2 3 4 5 6 7 8 9 10 11 12
| { "access_token":"a6f3b6d6-93e6-4eb8-a97d-3ae72240a7b0", "token_type":"bearer", "refresh_token":"710ab162-a482-41cd-8bad-26456af38e4f", "expires_in":42396, "scope":"server", "tenant_id":1, "license":"made by pigx", "dept_id":1, "user_id":1, "username":"admin" }
|
在一些场景下我们需要自定义一下返回报文的格式,例如使用R 对象返回,全部包含code业务码信息
1 2 3 4 5 6 7 8 9 10 11
| { "code":1, "msg":"", "data":{ "access_token":"e6669cdf-b6cd-43fe-af5c-f91a65041382", "token_type":"bearer", "refresh_token":"da91294d-446c-4a89-bdcf-88aee15a75e8", "expires_in":43199, "scope":"server" } }
|
1. 方法一:HandlerMethodReturnValueHandler
顾名思义这是 Spring MVC 提供给我们修改方法返回值的接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class FormatterToken implements HandlerMethodReturnValueHandler {
private static final String POST_ACCESS_TOKEN = "postAccessToken";
@Override public boolean supportsReturnType(MethodParameter returnType) { return POST_ACCESS_TOKEN.equals(Objects .requireNonNull(returnType.getMethod()).getName()); } @Override public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer container, NativeWebRequest request) throws Exception { ResponseEntity<OAuth2AccessToken> responseEntity = (ResponseEntity) returnValue; OAuth2AccessToken body = responseEntity.getBody();
HttpServletResponse response = request.getNativeResponse(HttpServletResponse.class); assert response != null; WebUtils.renderJson(response, R.ok(body)); } }
|
- 注入FormatterToken,一定要这么处理,不要直接使用 MVCconfig 注入,保证此Handler比 SpringMVC 默认的提前执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class FormatterTokenAutoConfiguration implements ApplicationContextAware, InitializingBean { private ApplicationContext applicationContext;
@Override public void afterPropertiesSet() { RequestMappingHandlerAdapter handlerAdapter = applicationContext.getBean(RequestMappingHandlerAdapter.class); List<HandlerMethodReturnValueHandler> returnValueHandlers = handlerAdapter.getReturnValueHandlers();
List<HandlerMethodReturnValueHandler> newHandlers = new ArrayList<>(); newHandlers.add(new FormatterToken()); assert returnValueHandlers != null; newHandlers.addAll(returnValueHandlers); handlerAdapter.setReturnValueHandlers(newHandlers); }
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
|
2. 方法二:aop 拦截增强 /oauth/token 接口
1 2 3 4 5 6 7 8 9 10 11 12
| @Around("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))") public Object handlePostAccessTokenMethod(ProceedingJoinPoint joinPoint) throws Throwable { Object proceed = joinPoint.proceed();
ResponseEntity<OAuth2AccessToken> responseEntity = (ResponseEntity<OAuth2AccessToken>) proceed; OAuth2AccessToken body = responseEntity.getBody(); return ResponseEntity .status(HttpStatus.OK) .body(R.ok(body)); } }
|
总结
- 实际项目中不建议修改此接口的访问格式,不兼容oauth2协议 导致其他组件不能正常使用
- swagger 自带的认证授权
- 其他网关组件自带的oauth2
都将失效总体来权衡 弊大于利