本篇内容介绍了“Spring Cloud OAuth2中/oauth/token返回的内容格式是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
背景
实现原理
代码实现
相关类
关键切面拦截器
在前后端分离的项目中,一般后端返回给前端的格式是一个固定的json格式。在这个前提下,Spring Cloud OAuth3 生成access token的请求/oauth/token的返回内容就需要自定义。
访问/oauth/token示例如下:
原始返回值的格式如下:
我们希望使用我们自己固定的json格式,如下:
原理就是通过切面编程实现对/oauth/token端点请求的结果进行拦截封装处理,由于/oauth/token是Spring Cloud OAuth3的内部端点,因此需要对相关的Spring源码进行分析。最终定位到
org.springframework.security.oauth3.provider.endpoint.TokenEndpoint.postAccessToken()
方法上。
CodeEnum.java
package com.wongoing.common.model;
/**
* @description: 代码枚举
* @author: zheng
* @date: Created in 2021/1/26 11:18
* @version: 0.0.1
* @modified By:
*/
public enum CodeEnum {
SUCCESS(0),
ERROR(1);
private Integer code;
CodeEnum(Integer code) {
this.code = code;
}
public Integer getCode() {
return this.code;
}
}
Result.java
package com.wongoing.common.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @description: Rest API 接口方法返回类型定义
* @author: zheng
* @date: Created in 2021/1/26 13:25
* @version: 0.0.1
* @modified By:
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> implements Serializable {
private T data;
private Integer code;
private String msg;
public static <T> Result<T> of(T data, Integer code, String msg) {
return new Result<>(data, code, msg);
}
public static <T> Result<T> succeed(String msg) {
return of(null, CodeEnum.SUCCESS.getCode(), msg);
}
public static <T> Result<T> succeed(T model, String msg) {
return of(model, CodeEnum.SUCCESS.getCode(), msg);
}
public static <T> Result<T> succeed(T model) {
return of(model, CodeEnum.SUCCESS.getCode(), "");
}
public static <T> Result<T> failed(String msg) {
return of(null, CodeEnum.ERROR.getCode(), msg);
}
public static <T> Result<T> failed(T model, String msg) {
return of(model, CodeEnum.ERROR.getCode(), msg);
}
}
在uaa项目中定义OauthTokenAspect.java
package com.wongoing.oauth3.filter;
import com.wongoing.common.constant.SecurityConstants;
import com.wongoing.common.context.TenantContextHolder;
import com.wongoing.common.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth3.common.OAuth3AccessToken;
import org.springframework.security.oauth3.common.util.OAuth3Utils;
import org.springframework.security.oauth3.provider.OAuth3Authentication;
import org.springframework.stereotype.Component;
import java.security.Principal;
import java.util.Map;
/**
* @description: oauth-token拦截器
* 1. 赋值租户
* 2. 统一返回token格式
*
* @author: zheng
* @date: Created in 2021/7/12 16:25
* @version: 0.0.1
* @modified By:
*/
@Slf4j
@Component
@Aspect
public class OauthTokenAspect {
@Around("execution(* org.springframework.security.oauth3.provider.endpoint.TokenEndpoint.postAccessToken(..))")
public Object handleControllerMethod(ProceedingJoinPoint joinPoint) throws Throwable {
try {
Object[] args = joinPoint.getArgs();
Principal principal = (Principal) args[0];
if (!(principal instanceof Authentication)) {
throw new InsufficientAuthenticationException("There is no client authentication. Try adding an appropriate authentication filter.");
}
String clientId = this.getClientId(principal);
Map<String, String> parameters = (Map<String, String>) args[1];
String grantType = parameters.get(OAuth3Utils.GRANT_TYPE);
//保存租户id
TenantContextHolder.setTenant(clientId);
Object proceed = joinPoint.proceed();
if (SecurityConstants.AUTHORIZATION_CODE.equals(grantType)) {
/**
* 如果使用 @EnableOAuth3Sso 注解不能修改返回格式,否则授权码模式可以统一改
* 因为本项目的 sso-demo/ss-sso 里面使用了 @EnableOAuth3Sso 注解,所以这里就不修改授权码模式的token返回值了
*/
return proceed;
} else {
ResponseEntity<OAuth3AccessToken> responseEntity = (ResponseEntity<OAuth3AccessToken>) proceed;
OAuth3AccessToken body = responseEntity.getBody();
return ResponseEntity
.status(HttpStatus.OK)
.body(Result.succeed(body));
}
} finally {
TenantContextHolder.clear();
}
}
private String getClientId(Principal principal) {
Authentication client = (Authentication) principal;
if (!client.isAuthenticated()) {
throw new InsufficientAuthenticationException("The client is not authenticated.");
}
String clientId = client.getName();
if (client instanceof OAuth3Authentication) {
clientId = ((OAuth3Authentication) client).getOAuth3Request().getClientId();
}
return clientId;
}
}
其中的常量值:
public abstract class OAuth3Utils {
public static final String GRANT_TYPE = "grant_type";
}
public interface SecurityConstants {
/**
* 授权码模式
*/
String AUTHORIZATION_CODE = "authorization_code";
}
“Spring Cloud OAuth2中/oauth/token返回的内容格式是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。