完整适配拆分式路由写法

This commit is contained in:
click33
2024-08-19 23:29:05 +08:00
parent 25b24414ff
commit 174a94db01
13 changed files with 335 additions and 160 deletions

View File

@@ -1,5 +1,6 @@
package com.pj;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -12,7 +13,8 @@ public class SaOAuth2ServerApplication {
public static void main(String[] args) {
SpringApplication.run(SaOAuth2ServerApplication.class, args);
System.out.println("\nSa-Token-OAuth Server端启动成功");
System.out.println("\nSa-Token-OAuth Server端启动成功,配置如下:");
System.out.println(SaOAuth2Manager.getConfig());
}
}

View File

@@ -22,7 +22,11 @@ public class SaOAuth2DataLoaderImpl implements SaOAuth2DataLoader {
.setClientSecret("aaaa-bbbb-cccc-dddd-eeee") // client 秘钥
.addAllowUrls("*") // 所有允许授权的 url
.addContractScopes("openid", "userid", "userinfo") // 所有签约的权限
.setIsAutoMode(true); // 是否自动判断开放的授权模式
.setEnableCode(true) // 是否开启授权模式
.setEnableImplicit(true) // 是否开启隐式模式
.setEnablePassword(true) // 是否开启密码模式
.setEnableClient(true) // 是否开启客户端模式
;
}
return null;
}

View File

@@ -7,7 +7,6 @@ import cn.dev33.satoken.oauth2.template.SaOAuth2Util;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
@@ -17,20 +16,20 @@ import java.util.LinkedHashMap;
import java.util.Map;
/**
* Sa-OAuth2 Server端 控制器
* Sa-Token-OAuth2 Server端 Controller
*
* @author click33
*
*/
@RestController
public class SaOAuth2ServerController {
// 处理所有OAuth相关请求
// OAuth2-Server 端:处理所有OAuth相关请求
@RequestMapping("/oauth2/*")
public Object request() {
System.out.println("------- 进入请求: " + SaHolder.getRequest().getUrl());
return SaOAuth2ServerProcessor.instance.dister();
}
// Sa-OAuth2 定制化配置
@Autowired
public void configOAuth2Server(SaOAuth2Config cfg) {
@@ -57,13 +56,6 @@ public class SaOAuth2ServerController {
};
}
// 全局异常拦截
@ExceptionHandler
public SaResult handlerException(Exception e) {
e.printStackTrace();
return SaResult.error(e.getMessage());
}
// ---------- 开放相关资源接口: Client端根据 Access-Token ,置换相关资源 ------------

View File

@@ -3,15 +3,19 @@ server:
# sa-token配置
sa-token:
# token名称 (同时也是cookie名称)
token-name: satoken-server
# token名称 (同时也是 Cookie 名称)
token-name: satoken-oauth2-server
# OAuth2.0 配置
oauth2:
is-code: true
is-implicit: true
is-password: true
is-client: true
oauth2:
# 是否全局开启授权码模式
enable-code: true
# 是否全局开启 Implicit 模式
enable-implicit: true
# 是否全局开启密码模式
enable-password: true
# 是否全局开启客户端模式
enable-client: true
spring:
# redis配置
redis:

View File

@@ -57,7 +57,7 @@
- [OAuth2-Server端开放 API 接口](/oauth2/oauth2-apidoc)
- [配置 client 域名校验 ](/oauth2/oauth2-check-domain)
- [定制化登录页面与授权页面](/oauth2/oauth2-custom-login)
- [拆分式路由](/oauth2/3)
- [自定义 API 路由 ](/oauth2/oauth2-custom-api)
- [前后端分离模式整合方案](/oauth2/4)
- [平台中心模式开发](/oauth2/5)
- [自定义 Scope 权限以处理器](/oauth2/6)

View File

@@ -0,0 +1,104 @@
# OAuth2-自定义 API 路由
---
### 方式一:修改全局变量
在之前的章节中,我们演示了如何搭建一个 OAuth2 认证中心:
``` java
/**
* Sa-Token-OAuth2 Server端 Controller
*/
@RestController
public class SaOAuth2ServerController {
// OAuth2-Server 端:处理所有 OAuth 相关请求
@RequestMapping("/oauth2/*")
public Object request() {
return SaOAuth2ServerProcessor.instance.dister();
}
// ... 其它代码
}
```
这种写法集成简单但却不够灵活。例如获取 code 授权码地址只能是:`http://{host}:{port}/oauth2/authorize`如果我们想要自定义其API地址应该怎么做呢
打开 OAuth2 模块相关源码,有关 API 的设计都定义在:
[SaOAuth2Consts.java](https://gitee.com/dromara/sa-token/blob/master/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/consts/SaOAuth2Consts.java)
中,我们可以对其进行二次修改。
例如,我们可以在 Main 方法启动类或者 OAuth2 配置方法中修改变量值:
``` java
// 配置 OAuth2 相关参数
@Autowired
private void configOAuth2Server(SaOAuth2Config cfg) {
// 自定义API地址
SaOAuth2Consts.Api.authorize = "/oauth2/authorize2";
// ...
}
```
启动项目,统一认证地址就被我们修改成了:`http://{host}:{port}/oauth2/authorize2`
### 方式二:拆分路由入口
根据上述路由入口:`@RequestMapping("/oauth2/*")`,我们给它起一个合适的名字 —— 聚合式路由。
与之对应的,我们可以将其修改为拆分式路由:
``` java
/**
* Sa-Token-OAuth2 Server端 Controller
*/
@RestController
public class SaOAuth2ServerController {
// 模式一Code授权码 || 模式二:隐藏式
@RequestMapping("/oauth2/authorize")
public Object authorize() {
return SaOAuth2ServerProcessor.instance.authorize();
}
// 用户登录
@RequestMapping("/oauth2/doLogin")
public Object doLogin() {
return SaOAuth2ServerProcessor.instance.doLogin();
}
// 用户确认授权
@RequestMapping("/oauth2/doConfirm")
public Object doConfirm() {
return SaOAuth2ServerProcessor.instance.doConfirm();
}
// Code 换 Access-Token || 模式三:密码式
@RequestMapping("/oauth2/token")
public Object token() {
return SaOAuth2ServerProcessor.instance.tokenOrPassword();
}
// Refresh-Token 刷新 Access-Token
@RequestMapping("/oauth2/refresh")
public Object refresh() {
return SaOAuth2ServerProcessor.instance.refresh();
}
// 回收 Access-Token
@RequestMapping("/oauth2/revoke")
public Object revoke() {
return SaOAuth2ServerProcessor.instance.revoke();
}
// 模式四:凭证式
@RequestMapping("/oauth2/client_token")
public Object clientToken() {
return SaOAuth2ServerProcessor.instance.clientToken();
}
}
```
拆分式路由 与 聚合式路由 在功能上完全等价,且提供了更为细致的路由管控。

View File

@@ -34,16 +34,16 @@ public class SaOAuth2Config implements Serializable {
private static final long serialVersionUID = -6541180061782004705L;
/** 是否打开模式授权码Authorization Code */
public Boolean isCode = true;
public Boolean enableCode = true;
/** 是否打开模式隐藏式Implicit */
public Boolean isImplicit = true;
public Boolean enableImplicit = true;
/** 是否打开模式密码式Password */
public Boolean isPassword = true;
public Boolean enablePassword = true;
/** 是否打开模式凭证式Client Credentials */
public Boolean isClient = true;
public Boolean enableClient = true;
/** 是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token */
public Boolean isNewRefresh = false;
@@ -69,59 +69,59 @@ public class SaOAuth2Config implements Serializable {
/**
* @return isCode
* @return enableCode
*/
public Boolean getIsCode() {
return isCode;
public Boolean getEnableCode() {
return enableCode;
}
/**
* @param isCode 要设置的 isCode
* @param enableCode 要设置的 enableCode
*/
public void setIsCode(Boolean isCode) {
this.isCode = isCode;
public void setEnableCode(Boolean enableCode) {
this.enableCode = enableCode;
}
/**
* @return isImplicit
* @return enableImplicit
*/
public Boolean getIsImplicit() {
return isImplicit;
public Boolean getEnableImplicit() {
return enableImplicit;
}
/**
* @param isImplicit 要设置的 isImplicit
* @param enableImplicit 要设置的 enableImplicit
*/
public void setIsImplicit(Boolean isImplicit) {
this.isImplicit = isImplicit;
public void setEnableImplicit(Boolean enableImplicit) {
this.enableImplicit = enableImplicit;
}
/**
* @return isPassword
* @return enablePassword
*/
public Boolean getIsPassword() {
return isPassword;
public Boolean getEnablePassword() {
return enablePassword;
}
/**
* @param isPassword 要设置的 isPassword
* @param enablePassword 要设置的 enablePassword
*/
public void setIsPassword(Boolean isPassword) {
this.isPassword = isPassword;
public void setEnablePassword(Boolean enablePassword) {
this.enablePassword = enablePassword;
}
/**
* @return isClient
* @return enableClient
*/
public Boolean getIsClient() {
return isClient;
public Boolean getEnableClient() {
return enableClient;
}
/**
* @param isClient 要设置的 isClient
* @param enableClient 要设置的 enableClient
*/
public void setIsClient(Boolean isClient) {
this.isClient = isClient;
public void setEnableClient(Boolean enableClient) {
this.enableClient = enableClient;
}
/**
@@ -254,8 +254,11 @@ public class SaOAuth2Config implements Serializable {
@Override
public String toString() {
return "SaOAuth2Config [isCode=" + isCode + ", isImplicit=" + isImplicit + ", isPassword=" + isPassword
+ ", isClient=" + isClient
return "SaOAuth2Config [" +
"enableCode=" + enableCode
+ ", enableImplicit=" + enableImplicit
+ ", enablePassword=" + enablePassword
+ ", enableClient=" + enableClient
+ ", isNewRefresh=" + isNewRefresh
+ ", codeTimeout=" + codeTimeout
+ ", accessTokenTimeout=" + accessTokenTimeout

View File

@@ -100,8 +100,8 @@ public class SaOAuth2DataConverterDefaultImpl implements SaOAuth2DataConverter {
rt.expiresTime = System.currentTimeMillis() + (clientModel.getRefreshTokenTimeout() * 1000);
rt.extraData = new LinkedHashMap<>(at.extraData);
// 改变 at 属性
at.refreshToken = rt.refreshToken;
at.refreshExpiresTime = rt.expiresTime;
// at.refreshToken = rt.refreshToken;
// at.refreshExpiresTime = rt.expiresTime;
return rt;
}

View File

@@ -87,10 +87,10 @@ public class SaOAuth2DataGenerateDefaultImpl implements SaOAuth2DataGenerate {
// 3、生成token
AccessTokenModel at = dataConverter.convertCodeToAccessToken(cm);
SaOAuth2Strategy.instance.workAccessTokenByScope.accept(at);
RefreshTokenModel rt = dataConverter.convertAccessTokenToRefreshToken(at);
at.refreshToken = rt.refreshToken;
at.refreshExpiresTime = rt.expiresTime;
SaOAuth2Strategy.instance.workAccessTokenByScope.accept(at);
// 4、保存token
dao.saveAccessToken(at);
@@ -166,14 +166,20 @@ public class SaOAuth2DataGenerateDefaultImpl implements SaOAuth2DataGenerate {
// 2、生成 新Access-Token
String newAtValue = SaOAuth2Strategy.instance.createAccessToken.execute(ra.clientId, ra.loginId, ra.scopes);
AccessTokenModel at = new AccessTokenModel(newAtValue, ra.clientId, ra.loginId, ra.scopes);
// TODO 此处的 openid 应该怎么加载?
// at.openid = SaOAuth2Manager.getDataLoader().getOpenid(ra.clientId, ra.loginId);
// 3、根据权限构建额外参数
at.extraData = new LinkedHashMap<>();
SaOAuth2Strategy.instance.workAccessTokenByScope.accept(at);
SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(ra.clientId);
at.expiresTime = System.currentTimeMillis() + (clientModel.getAccessTokenTimeout() * 1000);
// 3、生成&保存 Refresh-Token
if(isCreateRt) {
RefreshTokenModel rt = SaOAuth2Manager.getDataConverter().convertAccessTokenToRefreshToken(at);
at.refreshToken = rt.refreshToken;
at.refreshExpiresTime = rt.expiresTime;
dao.saveRefreshToken(rt);
dao.saveRefreshTokenIndex(rt);
}

View File

@@ -54,23 +54,23 @@ public class SaClientModel implements Serializable {
public List<String> allowUrls;
/** 此 Client 是否打开模式授权码Authorization Code */
public Boolean isCode = false;
public Boolean enableCode = false;
/** 此 Client 是否打开模式隐藏式Implicit */
public Boolean isImplicit = false;
public Boolean enableImplicit = false;
/** 此 Client 是否打开模式密码式Password */
public Boolean isPassword = false;
public Boolean enablePassword = false;
/** 此 Client 是否打开模式凭证式Client Credentials */
public Boolean isClient = false;
public Boolean enableClient = false;
/**
* 是否自动判断此 Client 开放的授权模式
* <br> 此值为true时四种模式isCode、isImplicit、isPassword、isClient是否生效依靠全局设置
* <br> 此值为false时四种模式isCode、isImplicit、isPassword、isClient是否生效依靠局部配置+全局配置
*/
public Boolean isAutoMode = true;
// /**
// * 是否自动判断此 Client 开放的授权模式
// * <br> 此值为true时四种模式isCode、isImplicit、isPassword、isClient是否生效依靠全局设置
// * <br> 此值为false时四种模式isCode、isImplicit、isPassword、isClient是否生效依靠局部配置+全局配置
// */
// public Boolean isAutoMode = true;
/** 单独配置此Client是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token [默认取全局配置] */
public Boolean isNewRefresh;
@@ -171,83 +171,83 @@ public class SaClientModel implements Serializable {
/**
* @return 此 Client 是否打开模式授权码Authorization Code
*/
public Boolean getIsCode() {
return isCode;
public Boolean getEnableCode() {
return enableCode;
}
/**
* @param isCode 此 Client 是否打开模式授权码Authorization Code
* @param enableCode 此 Client 是否打开模式授权码Authorization Code
* @return 对象自身
*/
public SaClientModel setIsCode(Boolean isCode) {
this.isCode = isCode;
public SaClientModel setEnableCode(Boolean enableCode) {
this.enableCode = enableCode;
return this;
}
/**
* @return 此 Client 是否打开模式隐藏式Implicit
*/
public Boolean getIsImplicit() {
return isImplicit;
public Boolean getEnableImplicit() {
return enableImplicit;
}
/**
* @param isImplicit 此 Client 是否打开模式隐藏式Implicit
* @param enableImplicit 此 Client 是否打开模式隐藏式Implicit
* @return 对象自身
*/
public SaClientModel setIsImplicit(Boolean isImplicit) {
this.isImplicit = isImplicit;
public SaClientModel setEnableImplicit(Boolean enableImplicit) {
this.enableImplicit = enableImplicit;
return this;
}
/**
* @return 此 Client 是否打开模式密码式Password
*/
public Boolean getIsPassword() {
return isPassword;
public Boolean getEnablePassword() {
return enablePassword;
}
/**
* @param isPassword 此 Client 是否打开模式密码式Password
* @param enablePassword 此 Client 是否打开模式密码式Password
* @return 对象自身
*/
public SaClientModel setIsPassword(Boolean isPassword) {
this.isPassword = isPassword;
public SaClientModel setEnablePassword(Boolean enablePassword) {
this.enablePassword = enablePassword;
return this;
}
/**
* @return 此 Client 是否打开模式凭证式Client Credentials
*/
public Boolean getIsClient() {
return isClient;
public Boolean getEnableClient() {
return enableClient;
}
/**
* @param isClient 此 Client 是否打开模式凭证式Client Credentials
* @param enableClient 此 Client 是否打开模式凭证式Client Credentials
* @return 对象自身
*/
public SaClientModel setIsClient(Boolean isClient) {
this.isClient = isClient;
public SaClientModel setEnableClient(Boolean enableClient) {
this.enableClient = enableClient;
return this;
}
/**
* @return 是否自动判断此 Client 开放的授权模式
*/
public Boolean getIsAutoMode() {
return isAutoMode;
}
/**
* @param isAutoMode 是否自动判断此 Client 开放的授权模式
* @return 对象自身
*/
public SaClientModel setIsAutoMode(Boolean isAutoMode) {
this.isAutoMode = isAutoMode;
return this;
}
//
// /**
// * @return 是否自动判断此 Client 开放的授权模式
// */
// public Boolean getIsAutoMode() {
// return isAutoMode;
// }
//
// /**
// * @param isAutoMode 是否自动判断此 Client 开放的授权模式
// * @return 对象自身
// */
// public SaClientModel setIsAutoMode(Boolean isAutoMode) {
// this.isAutoMode = isAutoMode;
// return this;
// }
//
/**
* @return 此Client是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token [默认取全局配置]
@@ -338,11 +338,11 @@ public class SaClientModel implements Serializable {
", clientSecret='" + clientSecret + '\'' +
", contractScopes=" + contractScopes +
", allowUrls=" + allowUrls +
", isCode=" + isCode +
", isImplicit=" + isImplicit +
", isPassword=" + isPassword +
", isClient=" + isClient +
", isAutoMode=" + isAutoMode +
", isCode=" + enableCode +
", isImplicit=" + enableImplicit +
", isPassword=" + enablePassword +
", isClient=" + enableClient +
// ", isAutoMode=" + isAutoMode +
", isNewRefresh=" + isNewRefresh +
", accessTokenTimeout=" + accessTokenTimeout +
", refreshTokenTimeout=" + refreshTokenTimeout +

View File

@@ -113,7 +113,7 @@ public class SaOAuth2DataResolverDefaultImpl implements SaOAuth2DataResolver {
public Map<String, Object> buildClientTokenReturnValue(ClientTokenModel ct) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("client_token", ct.clientToken);
map.put("access_token", ct.clientToken); // 兼容 OAuth2 协议
// map.put("access_token", ct.clientToken); // 兼容 OAuth2 协议
map.put("expires_in", ct.getExpiresIn());
map.put("client_id", ct.clientId);
map.put("scope", SaOAuth2Manager.getDataConverter().convertScopeListToString(ct.scopes));

View File

@@ -98,6 +98,9 @@ public interface SaOAuth2ErrorCode {
/** 无效response_type */
int CODE_30125 = 30125;
/** 无效grant_type */
int CODE_30126 = 30126;
/** 暂未开放授权码模式 */
int CODE_30131 = 30131;

View File

@@ -71,28 +71,24 @@ public class SaOAuth2ServerProcessor {
// ------------------ 路由分发 ------------------
// 模式一Code授权码
if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.code)) {
SaClientModel cm = currClientModel();
if(cfg.getIsCode() && (cm.isCode || cm.isAutoMode)) {
return authorize();
}
throw new SaOAuth2Exception("暂未开放的授权模式").setCode(SaOAuth2ErrorCode.CODE_30131);
// 模式一Code授权码 || 模式二:隐藏式
if(req.isPath(Api.authorize)) {
return authorize();
}
// Code授权码 获取 Access-Token
if(req.isPath(Api.token) && req.isParam(Param.grant_type, GrantType.authorization_code)) {
return token();
// Code Access-Token || 模式三:密码式
if(req.isPath(Api.token)) {
return tokenOrPassword();
}
// Refresh-Token 刷新 Access-Token
if(req.isPath(Api.refresh) && req.isParam(Param.grant_type, GrantType.refresh_token)) {
return refreshToken();
if(req.isPath(Api.refresh)) {
return refresh();
}
// 回收 Access-Token
if(req.isPath(Api.revoke)) {
return revokeToken();
return revoke();
}
// doLogin 登录接口
@@ -105,31 +101,9 @@ public class SaOAuth2ServerProcessor {
return doConfirm();
}
// 模式二:隐藏式
if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.token)) {
SaClientModel cm = currClientModel();
if(cfg.getIsImplicit() && (cm.isImplicit || cm.isAutoMode)) {
return authorize();
}
throw new SaOAuth2Exception("暂未开放的授权模式").setCode(SaOAuth2ErrorCode.CODE_30132);
}
// 模式三:密码式
if(req.isPath(Api.token) && req.isParam(Param.grant_type, GrantType.password)) {
SaClientModel cm = currClientModel();
if(cfg.getIsPassword() && (cm.isPassword || cm.isAutoMode)) {
return password();
}
throw new SaOAuth2Exception("暂未开放的授权模式").setCode(SaOAuth2ErrorCode.CODE_30133);
}
// 模式四:凭证式
if(req.isPath(Api.client_token) && req.isParam(Param.grant_type, GrantType.client_credentials)) {
SaClientModel cm = currClientModel();
if(cfg.getIsClient() && (cm.isClient || cm.isAutoMode)) {
return clientToken();
}
throw new SaOAuth2Exception("暂未开放的授权模式").setCode(SaOAuth2ErrorCode.CODE_30134);
if(req.isPath(Api.client_token)) {
return clientToken();
}
// 默认返回
@@ -141,42 +115,67 @@ public class SaOAuth2ServerProcessor {
* @return 处理结果
*/
public Object authorize() {
// 获取变量
SaRequest req = SaHolder.getRequest();
SaResponse res = SaHolder.getResponse();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
SaOAuth2DataGenerate dataGenerate = SaOAuth2Manager.getDataGenerate();
String responseType = req.getParamNotNull(Param.response_type);
// 1、如果尚未登录, 则先去登录
// 1、先判断是否开启了指定的授权模式
// 模式一Code授权码
if(responseType.equals(ResponseType.code)) {
if(!cfg.enableCode) {
throwErrorSystemNotEnableModel();
}
if(!currClientModel().enableCode) {
throwErrorClientNotEnableModel();
}
}
// 模式二:隐藏式
else if(responseType.equals(ResponseType.token)) {
if(!cfg.enableImplicit) {
throwErrorSystemNotEnableModel();
}
if(!currClientModel().enableImplicit) {
throwErrorClientNotEnableModel();
}
}
// 其它
else {
throw new SaOAuth2Exception("无效 response_type: " + req.getParam(Param.response_type)).setCode(SaOAuth2ErrorCode.CODE_30125);
}
// 2、如果尚未登录, 则先去登录
if( ! getStpLogic().isLogin()) {
return cfg.notLoginView.get();
}
// 2、构建请求 Model
// 3、构建请求 Model
RequestAuthModel ra = SaOAuth2Manager.getDataResolver().readRequestAuthModel(req, getStpLogic().getLoginId());
// 3、校验:重定向域名是否合法
// 4、校验:重定向域名是否合法
oauth2Template.checkRightUrl(ra.clientId, ra.redirectUri);
// 4、校验此次申请的Scope该Client是否已经签约
// 5、校验此次申请的Scope该Client是否已经签约
oauth2Template.checkContract(ra.clientId, ra.scopes);
// 5、判断如果此次申请的Scope该用户尚未授权则转到授权页面
// 6、判断如果此次申请的Scope该用户尚未授权则转到授权页面
boolean isGrant = oauth2Template.isGrant(ra.loginId, ra.clientId, ra.scopes);
if( ! isGrant) {
return cfg.confirmView.apply(ra.clientId, ra.scopes);
}
// 6、判断授权类型
// 如果是 授权码式开始重定向授权下放code
// 7、判断授权类型重定向到不同地址
// 如果是 授权码式开始重定向授权下放code
if(ResponseType.code.equals(ra.responseType)) {
CodeModel codeModel = dataGenerate.generateCode(ra);
String redirectUri = dataGenerate.buildRedirectUri(ra.redirectUri, codeModel.code, ra.state);
return res.redirect(redirectUri);
}
// 如果是 隐藏式,则:开始重定向授权,下放 token
// 如果是 隐藏式,则:开始重定向授权,下放 token
if(ResponseType.token.equals(ra.responseType)) {
AccessTokenModel at = dataGenerate.generateAccessToken(ra, false);
String redirectUri = dataGenerate.buildImplicitRedirectUri(ra.redirectUri, at.accessToken, ra.state);
@@ -187,6 +186,34 @@ public class SaOAuth2ServerProcessor {
throw new SaOAuth2Exception("无效response_type: " + ra.responseType).setCode(SaOAuth2ErrorCode.CODE_30125);
}
/**
* Code 换 Access-Token || 模式三:密码式
* @return 处理结果
*/
public Object tokenOrPassword() {
String grantType = SaHolder.getRequest().getParamNotNull(Param.grant_type);
// Code 换 Access-Token
if(grantType.equals(GrantType.authorization_code)) {
return token();
}
// 模式三:密码式
if(grantType.equals(GrantType.password)) {
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
if(!cfg.enablePassword) {
throwErrorSystemNotEnableModel();
}
if(!currClientModel().enablePassword) {
throwErrorClientNotEnableModel();
}
return password();
}
throw new SaOAuth2Exception("无效 grant_type" + grantType);
}
/**
* Code授权码 获取 Access-Token
* @return 处理结果
@@ -216,9 +243,13 @@ public class SaOAuth2ServerProcessor {
* Refresh-Token 刷新 Access-Token
* @return 处理结果
*/
public Object refreshToken() {
public Object refresh() {
// 获取变量
SaRequest req = SaHolder.getRequest();
String grantType = req.getParamNotNull(Param.grant_type);
if(!grantType.equals(GrantType.refresh_token)) {
throw new SaOAuth2Exception("无效 grant_type" + grantType).setCode(SaOAuth2ErrorCode.CODE_30126);
}
// 获取参数
@@ -241,7 +272,7 @@ public class SaOAuth2ServerProcessor {
* 回收 Access-Token
* @return 处理结果
*/
public Object revokeToken() {
public Object revoke() {
// 获取变量
SaRequest req = SaHolder.getRequest();
@@ -344,6 +375,18 @@ public class SaOAuth2ServerProcessor {
public Object clientToken() {
// 获取变量
SaRequest req = SaHolder.getRequest();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
String grantType = req.getParamNotNull(Param.grant_type);
if(!grantType.equals(GrantType.client_credentials)) {
throw new SaOAuth2Exception("无效 grant_type" + grantType).setCode(SaOAuth2ErrorCode.CODE_30126);
}
if(!cfg.enableClient) {
throwErrorSystemNotEnableModel();
}
if(!currClientModel().enableClient) {
throwErrorClientNotEnableModel();
}
// 获取参数
ClientIdAndSecretModel clientIdAndSecret = SaOAuth2Manager.getDataResolver().readClientIdAndSecret(req);
@@ -383,4 +426,18 @@ public class SaOAuth2ServerProcessor {
return StpUtil.stpLogic;
}
/**
* 系统未开放此授权模式时抛出异常
*/
public void throwErrorSystemNotEnableModel() {
throw new SaOAuth2Exception("系统暂未开放此授权模式").setCode(SaOAuth2ErrorCode.CODE_30131);
}
/**
* 应用未开放此授权模式时抛出异常
*/
public void throwErrorClientNotEnableModel() {
throw new SaOAuth2Exception("应用暂未开放此授权模式").setCode(SaOAuth2ErrorCode.CODE_30131);
}
}