Spring Cloud OAuth2中/oauth/token的返回內(nèi)容格式
背景
在前后端分離的項(xiàng)目中,一般后端返回給前端的格式是一個(gè)固定的json格式。在這個(gè)前提下,Spring Cloud OAuth2 生成access token的請(qǐng)求/oauth/token的返回內(nèi)容就需要自定義。
訪問(wèn)/oauth/token示例如下:

原始返回值的格式如下:

我們希望使用我們自己固定的json格式,如下:

實(shí)現(xiàn)原理
原理就是通過(guò)切面編程實(shí)現(xiàn)對(duì)/oauth/token端點(diǎn)請(qǐng)求的結(jié)果進(jìn)行攔截封裝處理,由于/oauth/token是Spring Cloud OAuth2的內(nèi)部端點(diǎn),因此需要對(duì)相關(guān)的Spring源碼進(jìn)行分析。最終定位到
org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken()
方法上。
代碼實(shí)現(xiàn)
相關(guān)類
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);
}
}
關(guān)鍵切面攔截器
在uaa項(xiàng)目中定義OauthTokenAspect.java
package com.wongoing.oauth2.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.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.stereotype.Component;
import java.security.Principal;
import java.util.Map;
/**
* @description: oauth-token攔截器
* 1. 賦值租戶
* 2. 統(tǒng)一返回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.oauth2.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(OAuth2Utils.GRANT_TYPE);
//保存租戶id
TenantContextHolder.setTenant(clientId);
Object proceed = joinPoint.proceed();
if (SecurityConstants.AUTHORIZATION_CODE.equals(grantType)) {
/**
* 如果使用 @EnableOAuth2Sso 注解不能修改返回格式,否則授權(quán)碼模式可以統(tǒng)一改
* 因?yàn)楸卷?xiàng)目的 sso-demo/ss-sso 里面使用了 @EnableOAuth2Sso 注解,所以這里就不修改授權(quán)碼模式的token返回值了
*/
return proceed;
} else {
ResponseEntity<OAuth2AccessToken> responseEntity = (ResponseEntity<OAuth2AccessToken>) proceed;
OAuth2AccessToken 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 OAuth2Authentication) {
clientId = ((OAuth2Authentication) client).getOAuth2Request().getClientId();
}
return clientId;
}
}
其中的常量值:
public abstract class OAuth2Utils {
public static final String GRANT_TYPE = "grant_type";
}
public interface SecurityConstants {
/**
* 授權(quán)碼模式
*/
String AUTHORIZATION_CODE = "authorization_code";
}
到此這篇關(guān)于Spring Cloud OAuth2中/oauth/token的返回內(nèi)容格式的文章就介紹到這了,更多相關(guān)Spring Cloud OAuth2返回內(nèi)容格式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot+hutool批量生成二維碼壓縮導(dǎo)出功能
這篇文章主要介紹了springboot+hutool批量生成二維碼壓縮導(dǎo)出功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-10-10
Mybatis 動(dòng)態(tài)表名+Map參數(shù)傳遞+批量操作詳解
這篇文章主要介紹了Mybatis 動(dòng)態(tài)表名+Map參數(shù)傳遞+批量操作詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
在eclipse導(dǎo)入Java的jar包的方法JDBC(圖文說(shuō)明)
這篇文章主要介紹了在eclipse導(dǎo)入Java 的jar包的方法 JDBC 圖文說(shuō)明 ,需要的朋友可以參考下2015-09-09
Java每隔兩個(gè)數(shù)刪掉一個(gè)數(shù)問(wèn)題詳解
這篇文章主要介紹了Java每隔兩個(gè)數(shù)刪掉一個(gè)數(shù)問(wèn)題詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
關(guān)于ArrayList初始化容量的問(wèn)題
這篇文章主要介紹了關(guān)于ArrayList初始化容量的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
MyBatis使用注解開(kāi)發(fā)實(shí)現(xiàn)過(guò)程詳解
這篇文章主要介紹了MyBatis使用注解開(kāi)發(fā)實(shí)現(xiàn)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
Java中數(shù)學(xué)相關(guān)類的使用教程
Java是一種廣泛使用的編程語(yǔ)言,它提供了許多數(shù)學(xué)運(yùn)算的函數(shù)和方法,使得開(kāi)發(fā)者可以輕松地進(jìn)行各種數(shù)學(xué)計(jì)算,下面這篇文章主要給大家介紹了關(guān)于Java中數(shù)學(xué)相關(guān)類使用的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05

