sa-token-oauth2 新增自定义 grant_type 能力

This commit is contained in:
click33 2024-08-23 03:24:30 +08:00
parent 4aa4941598
commit 3345e3aaf9
22 changed files with 778 additions and 277 deletions

View File

@ -75,6 +75,17 @@ public class SaFoxUtil {
return sb.toString();
}
/**
* 生成指定区间的 int
*
* @param min 最小值包括
* @param max 最大值包括
* @return /
*/
public static int getRandomNumber(int min, int max) {
return ThreadLocalRandom.current().nextInt(min, max + 1);
}
/**
* 指定元素是否为null或者空字符串
* @param str 指定元素

View File

@ -1,5 +1,6 @@
package com.pj.oauth2;
import cn.dev33.satoken.oauth2.consts.GrantType;
import cn.dev33.satoken.oauth2.data.loader.SaOAuth2DataLoader;
import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel;
import org.springframework.stereotype.Component;
@ -22,10 +23,14 @@ public class SaOAuth2DataLoaderImpl implements SaOAuth2DataLoader {
.setClientSecret("aaaa-bbbb-cccc-dddd-eeee") // client 秘钥
.addAllowUrls("*") // 所有允许授权的 url
.addContractScopes("openid", "userid", "userinfo") // 所有签约的权限
.setEnableCode(true) // 是否开启授权码模式
.setEnableImplicit(true) // 是否开启隐式模式
.setEnablePassword(true) // 是否开启密码模式
.setEnableClient(true) // 是否开启客户端模式
.addAllowGrantTypes( // 所有允许的授权模式
GrantType.authorization_code, // 授权码式
GrantType.implicit, // 隐式式
GrantType.refresh_token, // 刷新令牌
GrantType.password, // 密码式
GrantType.client_credentials, // 客户端模式
"phone_code" // 自定义授权模式 手机号验证码登录
)
;
}
return null;

View File

@ -0,0 +1,56 @@
package com.pj.oauth2.custom;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.data.model.request.RequestAuthModel;
import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
import cn.dev33.satoken.oauth2.granttype.handler.SaOAuth2GrantTypeHandlerInterface;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 自定义 phone_code 授权模式处理器
*
* @author click33
* @since 2024/8/23
*/
@Component
public class PhoneCodeGrantTypeHandler implements SaOAuth2GrantTypeHandlerInterface {
@Override
public String getHandlerGrantType() {
return "phone_code";
}
@Override
public AccessTokenModel getAccessTokenModel(SaRequest req, String clientId, List<String> scopes) {
String phone = req.getParamNotNull("phone");
String code = req.getParamNotNull("code");
String realCode = SaManager.getSaTokenDao().get("phone_code:" + phone);
// 1校验验证码是否正确
if(!code.equals(realCode)) {
throw new SaOAuth2Exception("验证码错误");
}
// 2校验通过删除验证码
SaManager.getSaTokenDao().delete("phone_code:" + phone);
// 3登录
long userId = 10001; // 模拟 userId真实项目应该根据手机号从数据库查询
// 4构建 ra 对象
RequestAuthModel ra = new RequestAuthModel();
ra.clientId = clientId;
ra.loginId = userId;
ra.scopes = scopes;
// 5生成 Access-Token
AccessTokenModel at = SaOAuth2Manager.getDataGenerate().generateAccessToken(ra, true);
return at;
}
}

View File

@ -0,0 +1,26 @@
package com.pj.oauth2.custom;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 自定义手机登录接口
*
* @author click33
* @since 2024/8/23
*/
@RestController
public class PhoneLoginController {
@RequestMapping("/oauth2/sendPhoneCode")
public SaResult sendCode(String phone) {
String code = SaFoxUtil.getRandomNumber(100000, 999999) + "";
SaManager.getSaTokenDao().set("phone_code:" + phone, code, 60 * 5);
System.out.println("手机号:" + phone + ",验证码:" + code + ",已发送成功");
return SaResult.ok("验证码发送成功");
}
}

View File

@ -1,4 +1,4 @@
package com.pj.oauth2;
package com.pj.oauth2.custom;
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.data.model.ClientTokenModel;

View File

@ -5,6 +5,8 @@ server:
sa-token:
# token名称 (同时也是 Cookie 名称)
token-name: satoken-oauth2-server
# 是否打印操作日志
is-log: true
# OAuth2.0 配置
oauth2:
# 是否全局开启授权码模式

View File

@ -63,7 +63,7 @@
- [自定义 grant_type](/oauth2/oauth2-custom-grant_type)
- [OAuth2-与登录会话实现数据互通](/oauth2/oauth2-interworking)
- [OAuth2 代码 API 参考](/oauth2/oauth2-dev)
- [常见问题说明](/oauth2/8)
<!-- - [常见问题说明](/oauth2/8) -->
<!-- - [前后端分离模式整合方案](/oauth2/4) -->
<!-- - [平台中心模式开发](/oauth2/5) -->
- <!-- jwt风格token、使用注解校验权限、state参数详解 -->

View File

@ -0,0 +1,174 @@
# OAuth2-自定义权限处理器
### 1、需求场景
OAuth2 协议的 `/oauth2/token` 接口定义了两种获取 `access_token``grant_type`,分别是:
- `authorization_code`:使用用户授权的授权码获取 access_token。
- `password`:使用用户提交的账号、密码来获取 access_token。
除此之外,你还可以自定义 `grant_type`,来支持更多的场景。
假设有以下需求:通过 手机号+验证码 登录,返回 `access_token`
---
### 2、实现步骤
#### 2.1、新增验证码发送接口
首先在 oauth2-server 端开放一个接口,为指定手机号发送验证码。
``` java
/**
* 自定义手机登录接口
*/
@RestController
public class PhoneLoginController {
@RequestMapping("/oauth2/sendPhoneCode")
public SaResult sendCode(String phone) {
String code = SaFoxUtil.getRandomNumber(100000, 999999) + "";
SaManager.getSaTokenDao().set("phone_code:" + phone, code, 60 * 5);
System.out.println("手机号:" + phone + ",验证码:" + code + ",已发送成功");
return SaResult.ok("验证码发送成功");
}
}
```
真实项目肯定是要对接短信服务商的,此处我们仅做模拟代码,将发送的验证码打印在控制台上。
#### 2.2、自定义 grant_type 处理器
在 oauth2-server 新建 `PhoneCodeGrantTypeHandler` 实现 `SaOAuth2GrantTypeHandlerInterface` 接口:
``` java
/**
* 自定义 phone_code 授权模式处理器
*/
@Component
public class PhoneCodeGrantTypeHandler implements SaOAuth2GrantTypeHandlerInterface {
@Override
public String getHandlerGrantType() {
return "phone_code";
}
@Override
public AccessTokenModel getAccessTokenModel(SaRequest req, String clientId, List<String> scopes) {
String phone = req.getParamNotNull("phone");
String code = req.getParamNotNull("code");
String realCode = SaManager.getSaTokenDao().get("phone_code:" + phone);
// 1、校验验证码是否正确
if(!code.equals(realCode)) {
throw new SaOAuth2Exception("验证码错误");
}
// 2、校验通过删除验证码
SaManager.getSaTokenDao().delete("phone_code:" + phone);
// 3、登录
long userId = 10001; // 模拟 userId真实项目应该根据手机号从数据库查询
// 4、构建 ra 对象
RequestAuthModel ra = new RequestAuthModel();
ra.clientId = clientId;
ra.loginId = userId;
ra.scopes = scopes;
// 5、生成 Access-Token
AccessTokenModel at = SaOAuth2Manager.getDataGenerate().generateAccessToken(ra, true);
return at;
}
}
```
#### 2.3、为应用添加允许的授权类型
`SaOAuth2DataLoader` 实现类中,为 client 的允许授权类型增加自定义的 `phone_code`
``` java
// Sa-Token OAuth2自定义数据加载器
@Component
public class SaOAuth2DataLoaderImpl implements SaOAuth2DataLoader {
@Override
public SaClientModel getClientModel(String clientId) {
if("1001".equals(clientId)) {
return new SaClientModel()
.setClientId("1001")
.setClientSecret("aaaa-bbbb-cccc-dddd-eeee")
.addAllowUrls("*")
.addContractScopes("openid", "userid", "userinfo")
.addAllowGrantTypes(
GrantType.authorization_code,
GrantType.implicit,
GrantType.refresh_token,
GrantType.password,
GrantType.client_credentials,
"phone_code" // 重要代码:自定义授权模式 手机号验证码登录
)
;
}
return null;
}
// 其它代码 ...
}
```
完工,开始测试。
### 3、测试步骤
#### 1、先发送验证码
``` url
http://sa-oauth-server.com:8000/oauth2/sendPhoneCode?phone=13144556677
```
#### 2、请求 token
注意 `grant_type` 要填写我们自定义的 `phone_code`code 的具体值可以在后端的控制台上看到
``` url
http://sa-oauth-server.com:8000/oauth2/token
?grant_type=phone_code
&client_id=1001
&client_secret=aaaa-bbbb-cccc-dddd-eeee
&scope=openid
&phone=13144556677
&code={value}
```
返回结果参考如下:
``` js
{
"code": 200,
"msg": "ok",
"data": null,
"token_type": "bearer",
"access_token": "pfxRz6KVacwvKNu4IHmDsCJs33kvvARs2z1lTch7stog8nRt6rfVLowtAZ0E",
"refresh_token": "qcFD6Wo2qZidofXQtWF5oK5ML6ljHKufQ5SbouBxzGnHhnMjUG4VV0iXZhdE",
"expires_in": 7199,
"refresh_expires_in": 2591999,
"client_id": "1001",
"scope": "openid",
"openid": "ded91dc189a437dd1bac2274be167d50"
}
```

View File

@ -26,6 +26,9 @@ import cn.dev33.satoken.oauth2.data.loader.SaOAuth2DataLoader;
import cn.dev33.satoken.oauth2.data.loader.SaOAuth2DataLoaderDefaultImpl;
import cn.dev33.satoken.oauth2.data.resolver.SaOAuth2DataResolver;
import cn.dev33.satoken.oauth2.data.resolver.SaOAuth2DataResolverDefaultImpl;
import cn.dev33.satoken.oauth2.template.SaOAuth2Template;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
/**
* Sa-Token-OAuth2 模块 总控类
@ -144,4 +147,40 @@ public class SaOAuth2Manager {
SaOAuth2Manager.dao = dao;
}
/**
* OAuth2 模板方法 Bean
*/
private static volatile SaOAuth2Template template;
public static SaOAuth2Template getTemplate() {
if (template == null) {
synchronized (SaOAuth2Manager.class) {
if (template == null) {
setTemplate(new SaOAuth2Template());
}
}
}
return template;
}
public static void setTemplate(SaOAuth2Template template) {
SaOAuth2Manager.template = template;
}
/**
* OAuth2 StpLogic
*/
private static volatile StpLogic stpLogic;
public static StpLogic getStpLogic() {
if (stpLogic == null) {
synchronized (SaOAuth2Manager.class) {
if (stpLogic == null) {
setStpLogic(StpUtil.stpLogic);
}
}
}
return stpLogic;
}
public static void setStpLogic(StpLogic stpLogic) {
SaOAuth2Manager.stpLogic = stpLogic;
}
}

View File

@ -0,0 +1,12 @@
package cn.dev33.satoken.oauth2.consts;
/**
* 所有授权类型
*/
public final class GrantType {
public static String authorization_code = "authorization_code";
public static String refresh_token = "refresh_token";
public static String password = "password";
public static String client_credentials = "client_credentials";
public static String implicit = "implicit";
}

View File

@ -68,17 +68,6 @@ public class SaOAuth2Consts {
public static String token = "token";
}
/**
* 所有授权类型
*/
public static final class GrantType {
public static String authorization_code = "authorization_code";
public static String refresh_token = "refresh_token";
public static String password = "password";
public static String client_credentials = "client_credentials";
public static String implicit = "implicit";
}
/**
* 所有 token 类型
*/

View File

@ -35,21 +35,21 @@ public interface SaOAuth2DataGenerate {
* @param ra 请求参数Model
* @return 授权码Model
*/
public CodeModel generateCode(RequestAuthModel ra);
CodeModel generateCode(RequestAuthModel ra);
/**
* 构建ModelAccess-Token
* @param code 授权码Model
* @return AccessToken Model
*/
public AccessTokenModel generateAccessToken(String code);
AccessTokenModel generateAccessToken(String code);
/**
* 刷新Model根据 Refresh-Token 生成一个新的 Access-Token
* @param refreshToken Refresh-Token值
* @return 新的 Access-Token
*/
public AccessTokenModel refreshAccessToken(String refreshToken);
AccessTokenModel refreshAccessToken(String refreshToken);
/**
* 构建ModelAccess-Token (根据RequestAuthModel构建用于隐藏式 and 密码式)
@ -57,7 +57,7 @@ public interface SaOAuth2DataGenerate {
* @param isCreateRt 是否生成对应的Refresh-Token
* @return Access-Token Model
*/
public AccessTokenModel generateAccessToken(RequestAuthModel ra, boolean isCreateRt);
AccessTokenModel generateAccessToken(RequestAuthModel ra, boolean isCreateRt);
/**
* 构建ModelClient-Token
@ -65,7 +65,7 @@ public interface SaOAuth2DataGenerate {
* @param scopes 授权范围
* @return Client-Token Model
*/
public ClientTokenModel generateClientToken(String clientId, List<String> scopes);
ClientTokenModel generateClientToken(String clientId, List<String> scopes);
/**
* 构建URL下放Code URL (Authorization Code 授权码)
@ -74,7 +74,7 @@ public interface SaOAuth2DataGenerate {
* @param state state参数
* @return 构建完毕的URL
*/
public String buildRedirectUri(String redirectUri, String code, String state);
String buildRedirectUri(String redirectUri, String code, String state);
/**
* 构建URL下放Access-Token URL implicit 隐藏式
@ -83,14 +83,12 @@ public interface SaOAuth2DataGenerate {
* @param state state参数
* @return 构建完毕的URL
*/
public String buildImplicitRedirectUri(String redirectUri, String token, String state);
String buildImplicitRedirectUri(String redirectUri, String token, String state);
/**
* 回收 Access-Token
* @param accessToken Access-Token值
*/
public void revokeAccessToken(String accessToken);
void revokeAccessToken(String accessToken);
}

View File

@ -53,24 +53,10 @@ public class SaClientModel implements Serializable {
*/
public List<String> allowUrls;
/** 此 Client 是否打开模式授权码Authorization Code */
public Boolean enableCode = false;
/** 此 Client 是否打开模式隐藏式Implicit */
public Boolean enableImplicit = false;
/** 此 Client 是否打开模式密码式Password */
public Boolean enablePassword = false;
/** 此 Client 是否打开模式凭证式Client Credentials */
public Boolean enableClient = false;
// /**
// * 是否自动判断此 Client 开放的授权模式
// * <br> 此值为true时四种模式isCodeisImplicitisPasswordisClient是否生效依靠全局设置
// * <br> 此值为false时四种模式isCodeisImplicitisPasswordisClient是否生效依靠局部配置+全局配置
// */
// public Boolean isAutoMode = true;
/**
* 应用允许的所有 grant_type
*/
public List<String> allowGrantTypes = new ArrayList<>();
/** 单独配置此Client是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token [默认取全局配置] */
public Boolean isNewRefresh;
@ -169,86 +155,22 @@ public class SaClientModel implements Serializable {
}
/**
* @return Client 是否打开模式授权码Authorization Code
* @return 应用允许的所有 grant_type
*/
public Boolean getEnableCode() {
return enableCode;
public List<String> getAllowGrantTypes() {
return allowGrantTypes;
}
/**
* @param enableCode Client 是否打开模式授权码Authorization Code
* @return 对象自身
* 应用允许的所有 grant_type
* @param allowGrantTypes /
* @return /
*/
public SaClientModel setEnableCode(Boolean enableCode) {
this.enableCode = enableCode;
public SaClientModel setAllowGrantTypes(List<String> allowGrantTypes) {
this.allowGrantTypes = allowGrantTypes;
return this;
}
/**
* @return Client 是否打开模式隐藏式Implicit
*/
public Boolean getEnableImplicit() {
return enableImplicit;
}
/**
* @param enableImplicit Client 是否打开模式隐藏式Implicit
* @return 对象自身
*/
public SaClientModel setEnableImplicit(Boolean enableImplicit) {
this.enableImplicit = enableImplicit;
return this;
}
/**
* @return Client 是否打开模式密码式Password
*/
public Boolean getEnablePassword() {
return enablePassword;
}
/**
* @param enablePassword Client 是否打开模式密码式Password
* @return 对象自身
*/
public SaClientModel setEnablePassword(Boolean enablePassword) {
this.enablePassword = enablePassword;
return this;
}
/**
* @return Client 是否打开模式凭证式Client Credentials
*/
public Boolean getEnableClient() {
return enableClient;
}
/**
* @param enableClient Client 是否打开模式凭证式Client Credentials
* @return 对象自身
*/
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是否在每次 Refresh-Token 刷新 Access-Token 产生一个新的 Refresh-Token [默认取全局配置]
*/
@ -338,11 +260,7 @@ public class SaClientModel implements Serializable {
", clientSecret='" + clientSecret + '\'' +
", contractScopes=" + contractScopes +
", allowUrls=" + allowUrls +
", isCode=" + enableCode +
", isImplicit=" + enableImplicit +
", isPassword=" + enablePassword +
", isClient=" + enableClient +
// ", isAutoMode=" + isAutoMode +
", allowGrantTypes=" + allowGrantTypes +
", isNewRefresh=" + isNewRefresh +
", accessTokenTimeout=" + accessTokenTimeout +
", refreshTokenTimeout=" + refreshTokenTimeout +
@ -367,7 +285,7 @@ public class SaClientModel implements Serializable {
}
/**
* @param urls 添加应用签约的所有权限
* @param urls 添加应用允许授权的所有URL
* @return 对象自身
*/
public SaClientModel addAllowUrls(String... urls) {
@ -378,5 +296,17 @@ public class SaClientModel implements Serializable {
return this;
}
/**
* @param grantTypes 应用允许的所有 grant_type
* @return 对象自身
*/
public SaClientModel addAllowGrantTypes(String... grantTypes) {
if(this.allowGrantTypes == null) {
this.allowGrantTypes = new ArrayList<>();
}
this.allowGrantTypes.addAll(Arrays.asList(grantTypes));
return this;
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.oauth2.function.strategy;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import java.util.function.Function;
/**
* 函数式接口GrantType 认证
*
* <p> 参数SaRequestgrant_type </p>
* <p> 返回处理结果 </p>
*
* @author click33
* @since 1.39.0
*/
@FunctionalInterface
public interface SaOAuth2GrantTypeAuthFunction extends Function<SaRequest, AccessTokenModel> {
}

View File

@ -0,0 +1,57 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.oauth2.granttype.handler;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts;
import cn.dev33.satoken.oauth2.consts.GrantType;
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.data.model.request.ClientIdAndSecretModel;
import java.util.List;
/**
* authorization_code grant_type 处理器
*
* @author click33
* @since 1.39.0
*/
public class AuthorizationCodeGrantTypeHandler implements SaOAuth2GrantTypeHandlerInterface {
@Override
public String getHandlerGrantType() {
return GrantType.authorization_code;
}
@Override
public AccessTokenModel getAccessTokenModel(SaRequest req, String clientId, List<String> scopes) {
// 获取参数
ClientIdAndSecretModel clientIdAndSecret = SaOAuth2Manager.getDataResolver().readClientIdAndSecret(req);
// String clientId = clientIdAndSecret.clientId;
String clientSecret = clientIdAndSecret.clientSecret;
String code = req.getParamNotNull(SaOAuth2Consts.Param.code);
String redirectUri = req.getParam(SaOAuth2Consts.Param.redirect_uri);
// 校验参数
SaOAuth2Manager.getTemplate().checkGainTokenParam(code, clientId, clientSecret, redirectUri);
// 构建 Access-Token返回
AccessTokenModel accessTokenModel = SaOAuth2Manager.getDataGenerate().generateAccessToken(code);
return accessTokenModel;
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.oauth2.granttype.handler;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.consts.GrantType;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts;
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.data.model.request.RequestAuthModel;
import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
import cn.dev33.satoken.stp.StpUtil;
import java.util.List;
/**
* password grant_type 处理器
*
* @author click33
* @since 1.39.0
*/
public class PasswordGrantTypeHandler implements SaOAuth2GrantTypeHandlerInterface {
@Override
public String getHandlerGrantType() {
return GrantType.password;
}
@Override
public AccessTokenModel getAccessTokenModel(SaRequest req, String clientId, List<String> scopes) {
// 1获取请求参数
String username = req.getParamNotNull(SaOAuth2Consts.Param.username);
String password = req.getParamNotNull(SaOAuth2Consts.Param.password);
// 3调用API 开始登录如果没能成功登录则直接退出
loginByUsernamePassword(username, password);
Object loginId = StpUtil.getLoginIdDefaultNull();
if(loginId == null) {
throw new SaOAuth2Exception("登录失败");
}
// 4构建 ra 对象
RequestAuthModel ra = new RequestAuthModel();
ra.clientId = clientId;
ra.loginId = loginId;
ra.scopes = scopes;
// 5生成 Access-Token
AccessTokenModel at = SaOAuth2Manager.getDataGenerate().generateAccessToken(ra, true);
return at;
}
/**
* 根据 usernamepassword 进行登录如果登录失败请直接抛出异常
* @param username /
* @param password /
*/
public void loginByUsernamePassword(String username, String password) {
SaOAuth2Manager.getConfig().doLoginHandle.apply(username, password);
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.oauth2.granttype.handler;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.consts.GrantType;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts;
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.data.model.RefreshTokenModel;
import cn.dev33.satoken.oauth2.error.SaOAuth2ErrorCode;
import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
import java.util.List;
/**
* refresh_token grant_type 处理器
*
* @author click33
* @since 1.39.0
*/
public class RefreshTokenGrantTypeHandler implements SaOAuth2GrantTypeHandlerInterface {
@Override
public String getHandlerGrantType() {
return GrantType.refresh_token;
}
@Override
public AccessTokenModel getAccessTokenModel(SaRequest req, String clientId, List<String> scopes) {
// 获取参数
String refreshToken = req.getParamNotNull(SaOAuth2Consts.Param.refresh_token);
// 校验Refresh-Token 是否存在
RefreshTokenModel rt = SaOAuth2Manager.getDao().getRefreshToken(refreshToken);
SaOAuth2Exception.throwBy(rt == null, "无效refresh_token: " + refreshToken, SaOAuth2ErrorCode.CODE_30121);
// 校验Refresh-Token 代表的 ClientId 与提供的 ClientId 是否一致
SaOAuth2Exception.throwBy( ! rt.clientId.equals(clientId), "无效client_id: " + clientId, SaOAuth2ErrorCode.CODE_30122);
// 获取新 Access-Token
AccessTokenModel accessTokenModel = SaOAuth2Manager.getDataGenerate().refreshAccessToken(refreshToken);
return accessTokenModel;
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.oauth2.granttype.handler;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import java.util.List;
/**
* 所有 OAuth2 GrantType 处理器的父接口
*
* @author click33
* @since 1.39.0
*/
public interface SaOAuth2GrantTypeHandlerInterface {
/**
* 获取所要处理的 GrantType
*
* @return /
*/
String getHandlerGrantType();
/**
* 获取 AccessTokenModel 对象
*
* @param req /
* @return /
*/
AccessTokenModel getAccessTokenModel(SaRequest req, String clientId, List<String> scopes);
}

View File

@ -20,9 +20,9 @@ import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
import cn.dev33.satoken.oauth2.consts.GrantType;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.Api;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.GrantType;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.Param;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.ResponseType;
import cn.dev33.satoken.oauth2.data.generate.SaOAuth2DataGenerate;
@ -34,10 +34,9 @@ import cn.dev33.satoken.oauth2.data.model.request.ClientIdAndSecretModel;
import cn.dev33.satoken.oauth2.data.model.request.RequestAuthModel;
import cn.dev33.satoken.oauth2.error.SaOAuth2ErrorCode;
import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy;
import cn.dev33.satoken.oauth2.template.SaOAuth2Template;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import java.util.List;
@ -55,11 +54,6 @@ public class SaOAuth2ServerProcessor {
*/
public static SaOAuth2ServerProcessor instance = new SaOAuth2ServerProcessor();
/**
* 底层 SaOAuth2Template 对象
*/
public SaOAuth2Template oauth2Template = new SaOAuth2Template();
/**
* 处理 Server 端请求 路由分发
* @return 处理结果
@ -68,7 +62,6 @@ public class SaOAuth2ServerProcessor {
// 获取变量
SaRequest req = SaHolder.getRequest();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
// ------------------ 路由分发 ------------------
@ -79,7 +72,7 @@ public class SaOAuth2ServerProcessor {
// Code Access-Token || 模式三密码式
if(req.isPath(Api.token)) {
return tokenOrPassword();
return token();
}
// Refresh-Token 刷新 Access-Token
@ -122,18 +115,19 @@ public class SaOAuth2ServerProcessor {
SaResponse res = SaHolder.getResponse();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
SaOAuth2DataGenerate dataGenerate = SaOAuth2Manager.getDataGenerate();
SaOAuth2Template oauth2Template = SaOAuth2Manager.getTemplate();
String responseType = req.getParamNotNull(Param.response_type);
// 1先判断是否开启了指定的授权模式
checkAuthorizeResponseType(responseType, req, cfg);
// 2如果尚未登录, 则先去登录
if( ! getStpLogic().isLogin()) {
if( ! SaOAuth2Manager.getStpLogic().isLogin()) {
return cfg.notLoginView.get();
}
// 3构建请求 Model
RequestAuthModel ra = SaOAuth2Manager.getDataResolver().readRequestAuthModel(req, getStpLogic().getLoginId());
RequestAuthModel ra = SaOAuth2Manager.getDataResolver().readRequestAuthModel(req, SaOAuth2Manager.getStpLogic().getLoginId());
// 4校验重定向域名是否合法
oauth2Template.checkRightUrl(ra.clientId, ra.redirectUri);
@ -167,55 +161,11 @@ public class SaOAuth2ServerProcessor {
}
/**
* 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
* Code Access-Token / 模式三密码式 / 自定义 grant_type
* @return 处理结果
*/
public Object token() {
// 获取变量
SaRequest req = SaHolder.getRequest();
// 获取参数
ClientIdAndSecretModel clientIdAndSecret = SaOAuth2Manager.getDataResolver().readClientIdAndSecret(req);
String clientId = clientIdAndSecret.clientId;
String clientSecret = clientIdAndSecret.clientSecret;
String code = req.getParamNotNull(Param.code);
String redirectUri = req.getParam(Param.redirect_uri);
// 校验参数
oauth2Template.checkGainTokenParam(code, clientId, clientSecret, redirectUri);
// 构建 Access-Token
AccessTokenModel accessTokenModel = SaOAuth2Manager.getDataGenerate().generateAccessToken(code);
// 返回
AccessTokenModel accessTokenModel = SaOAuth2Strategy.instance.grantTypeAuth.apply(SaHolder.getRequest());
return SaOAuth2Manager.getDataResolver().buildTokenReturnValue(accessTokenModel);
}
@ -224,27 +174,10 @@ public class SaOAuth2ServerProcessor {
* @return 处理结果
*/
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);
}
// 获取参数
ClientIdAndSecretModel clientIdAndSecret = SaOAuth2Manager.getDataResolver().readClientIdAndSecret(req);
String clientId = clientIdAndSecret.clientId;
String clientSecret = clientIdAndSecret.clientSecret;
String refreshToken = req.getParamNotNull(Param.refresh_token);
// 校验参数
oauth2Template.checkRefreshTokenParam(clientId, clientSecret, refreshToken);
// 获取新 Access-Token
AccessTokenModel accessTokenModel = SaOAuth2Manager.getDataGenerate().refreshAccessToken(refreshToken);
// 返回
SaOAuth2Exception.throwBy(!grantType.equals(GrantType.refresh_token), "无效 grant_type" + grantType, SaOAuth2ErrorCode.CODE_30126);
AccessTokenModel accessTokenModel = SaOAuth2Strategy.instance.grantTypeAuth.apply(req);
return SaOAuth2Manager.getDataResolver().buildRefreshTokenReturnValue(accessTokenModel);
}
@ -254,6 +187,7 @@ public class SaOAuth2ServerProcessor {
*/
public Object revoke() {
// 获取变量
SaOAuth2Template oauth2Template = SaOAuth2Manager.getTemplate();
SaRequest req = SaHolder.getRequest();
// 获取参数
@ -297,10 +231,11 @@ public class SaOAuth2ServerProcessor {
// 获取变量
SaRequest req = SaHolder.getRequest();
String clientId = req.getParamNotNull(Param.client_id);
Object loginId = getStpLogic().getLoginId();
Object loginId = SaOAuth2Manager.getStpLogic().getLoginId();
String scope = req.getParamNotNull(Param.scope);
List<String> scopes = SaOAuth2Manager.getDataConverter().convertScopeStringToList(scope);
SaOAuth2DataGenerate dataGenerate = SaOAuth2Manager.getDataGenerate();
SaOAuth2Template oauth2Template = SaOAuth2Manager.getTemplate();
// 此请求只允许 POST 方式
if(!req.isMethod(SaHttpMethod.POST)) {
@ -343,49 +278,6 @@ public class SaOAuth2ServerProcessor {
throw new SaOAuth2Exception("无效response_type: " + ra.responseType).setCode(SaOAuth2ErrorCode.CODE_30125);
}
/**
* 模式三密码式
* @return 处理结果
*/
public Object password() {
// 获取变量
SaRequest req = SaHolder.getRequest();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
// 1获取请求参数
String username = req.getParamNotNull(Param.username);
String password = req.getParamNotNull(Param.password);
ClientIdAndSecretModel clientIdAndSecret = SaOAuth2Manager.getDataResolver().readClientIdAndSecret(req);
String clientId = clientIdAndSecret.clientId;
String clientSecret = clientIdAndSecret.clientSecret;
String scope = req.getParam(Param.scope, "");
List<String> scopes = SaOAuth2Manager.getDataConverter().convertScopeStringToList(scope);
// 2校验 ClientScope scope
oauth2Template.checkClientSecretAndScope(clientId, clientSecret, scopes);
// 3防止因前端误传token造成逻辑干扰
// SaHolder.getStorage().set(getStpLogic().stpLogic.splicingKeyJustCreatedSave(), "no-token");
// 3调用API 开始登录如果没能成功登录则直接退出
Object retObj = cfg.doLoginHandle.apply(username, password);
if( ! getStpLogic().isLogin()) {
return retObj;
}
// 4构建 ra对象
RequestAuthModel ra = new RequestAuthModel();
ra.clientId = clientId;
ra.loginId = getStpLogic().getLoginId();
ra.scopes = scopes;
// 5生成 Access-Token
AccessTokenModel at = SaOAuth2Manager.getDataGenerate().generateAccessToken(ra, true);
// 6返回 Access-Token
return SaOAuth2Manager.getDataResolver().buildPasswordReturnValue(at);
}
/**
* 模式四凭证式
* @return 处理结果
@ -394,6 +286,7 @@ public class SaOAuth2ServerProcessor {
// 获取变量
SaRequest req = SaHolder.getRequest();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
SaOAuth2Template oauth2Template = SaOAuth2Manager.getTemplate();
String grantType = req.getParamNotNull(Param.grant_type);
if(!grantType.equals(GrantType.client_credentials)) {
@ -402,7 +295,7 @@ public class SaOAuth2ServerProcessor {
if(!cfg.enableClient) {
throwErrorSystemNotEnableModel();
}
if(!currClientModel().enableClient) {
if(!currClientModel().getAllowGrantTypes().contains(GrantType.client_credentials)) {
throwErrorClientNotEnableModel();
}
@ -434,6 +327,7 @@ public class SaOAuth2ServerProcessor {
* @return /
*/
public SaClientModel currClientModel() {
SaOAuth2Template oauth2Template = SaOAuth2Manager.getTemplate();
ClientIdAndSecretModel clientIdAndSecret = SaOAuth2Manager.getDataResolver().readClientIdAndSecret(SaHolder.getRequest());
return oauth2Template.checkClientModel(clientIdAndSecret.clientId);
}
@ -447,7 +341,7 @@ public class SaOAuth2ServerProcessor {
if(!cfg.enableCode) {
throwErrorSystemNotEnableModel();
}
if(!currClientModel().enableCode) {
if(!currClientModel().getAllowGrantTypes().contains(GrantType.authorization_code)) {
throwErrorClientNotEnableModel();
}
}
@ -456,7 +350,7 @@ public class SaOAuth2ServerProcessor {
if(!cfg.enableImplicit) {
throwErrorSystemNotEnableModel();
}
if(!currClientModel().enableImplicit) {
if(!currClientModel().getAllowGrantTypes().contains(GrantType.implicit)) {
throwErrorClientNotEnableModel();
}
}
@ -466,15 +360,6 @@ public class SaOAuth2ServerProcessor {
}
}
/**
* 获取底层使用的会话对象
*
* @return /
*/
public StpLogic getStpLogic() {
return StpUtil.stpLogic;
}
/**
* 系统未开放此授权模式时抛出异常
*/

View File

@ -16,8 +16,18 @@
package cn.dev33.satoken.oauth2.strategy;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
import cn.dev33.satoken.oauth2.consts.GrantType;
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts;
import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel;
import cn.dev33.satoken.oauth2.data.model.request.ClientIdAndSecretModel;
import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
import cn.dev33.satoken.oauth2.function.strategy.*;
import cn.dev33.satoken.oauth2.granttype.handler.AuthorizationCodeGrantTypeHandler;
import cn.dev33.satoken.oauth2.granttype.handler.PasswordGrantTypeHandler;
import cn.dev33.satoken.oauth2.granttype.handler.RefreshTokenGrantTypeHandler;
import cn.dev33.satoken.oauth2.granttype.handler.SaOAuth2GrantTypeHandlerInterface;
import cn.dev33.satoken.oauth2.scope.CommonScope;
import cn.dev33.satoken.oauth2.scope.handler.OidcScopeHandler;
import cn.dev33.satoken.oauth2.scope.handler.OpenIdScopeHandler;
@ -26,6 +36,7 @@ import cn.dev33.satoken.oauth2.scope.handler.UserIdScopeHandler;
import cn.dev33.satoken.util.SaFoxUtil;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
@ -38,6 +49,7 @@ public final class SaOAuth2Strategy {
private SaOAuth2Strategy() {
registerDefaultScopeHandler();
registerDefaultGrantTypeHandler();
}
/**
@ -78,9 +90,6 @@ public final class SaOAuth2Strategy {
scopeHandlerMap.remove(scope);
}
// ----------------------- 所有策略
/**
* 根据 scope 信息对一个 AccessTokenModel 进行加工处理
*/
@ -117,6 +126,75 @@ public final class SaOAuth2Strategy {
}
};
// grant_type 处理器
/**
* grant_type 处理器集合
*/
public Map<String, SaOAuth2GrantTypeHandlerInterface> grantTypeHandlerMap = new LinkedHashMap<>();
/**
* 注册所有默认的权限处理器
*/
public void registerDefaultGrantTypeHandler() {
grantTypeHandlerMap.put(GrantType.authorization_code, new AuthorizationCodeGrantTypeHandler());
grantTypeHandlerMap.put(GrantType.password, new PasswordGrantTypeHandler());
grantTypeHandlerMap.put(GrantType.refresh_token, new RefreshTokenGrantTypeHandler());
}
/**
* 注册一个权限处理器
*/
public void registerGrantTypeHandler(SaOAuth2GrantTypeHandlerInterface handler) {
grantTypeHandlerMap.put(handler.getHandlerGrantType(), handler);
// TODO 优化日志输出
SaManager.getLog().info("新增GrantType处理器" + handler.getHandlerGrantType());
// SaTokenEventCenter.doRegisterAnnotationHandler(handler);
}
/**
* 移除一个权限处理器
*/
public void removeGrantTypeHandler(String scope) {
scopeHandlerMap.remove(scope);
}
/**
* 根据 scope 信息对一个 AccessTokenModel 进行加工处理
*/
public SaOAuth2GrantTypeAuthFunction grantTypeAuth = (req) -> {
String grantType = req.getParamNotNull(SaOAuth2Consts.Param.grant_type);
SaOAuth2GrantTypeHandlerInterface grantTypeHandler = grantTypeHandlerMap.get(grantType);
if(grantTypeHandler == null) {
throw new RuntimeException("无效 grant_type: " + grantType);
}
// 看看全局是否开启了此 grantType
SaOAuth2Config config = SaOAuth2Manager.getConfig();
if(grantType.equals(GrantType.authorization_code) && !config.getEnableCode() ) {
throw new SaOAuth2Exception("系统未开放的 grant_type: " + grantType);
}
if(grantType.equals(GrantType.password) && !config.getEnablePassword() ) {
throw new SaOAuth2Exception("系统未开放的 grant_type: " + grantType);
}
// 校验 clientSecret scope
ClientIdAndSecretModel clientIdAndSecretModel = SaOAuth2Manager.getDataResolver().readClientIdAndSecret(req);
List<String> scopes = SaOAuth2Manager.getDataConverter().convertScopeStringToList(req.getParam(SaOAuth2Consts.Param.scope));
SaClientModel clientModel = SaOAuth2Manager.getTemplate().checkClientSecretAndScope(clientIdAndSecretModel.getClientId(), clientIdAndSecretModel.getClientSecret(), scopes);
// 检测应用是否开启此 grantType
if(!clientModel.getAllowGrantTypes().contains(grantType)) {
throw new SaOAuth2Exception("应用未开放的 grant_type: " + grantType);
}
// 调用 处理器
return grantTypeHandler.getAccessTokenModel(req, clientIdAndSecretModel.getClientId(), scopes);
};
// ----------------------- 所有策略
/**
* 创建一个 code value
*/

View File

@ -41,7 +41,7 @@ public class SaOAuth2Util {
* @return ClientModel
*/
public static SaClientModel checkClientModel(String clientId) {
return SaOAuth2ServerProcessor.instance.oauth2Template.checkClientModel(clientId);
return SaOAuth2Manager.getTemplate().checkClientModel(clientId);
}
/**
@ -50,7 +50,7 @@ public class SaOAuth2Util {
* @return .
*/
public static AccessTokenModel checkAccessToken(String accessToken) {
return SaOAuth2ServerProcessor.instance.oauth2Template.checkAccessToken(accessToken);
return SaOAuth2Manager.getTemplate().checkAccessToken(accessToken);
}
/**
@ -59,7 +59,7 @@ public class SaOAuth2Util {
* @return .
*/
public static ClientTokenModel checkClientToken(String clientToken) {
return SaOAuth2ServerProcessor.instance.oauth2Template.checkClientToken(clientToken);
return SaOAuth2Manager.getTemplate().checkClientToken(clientToken);
}
/**
@ -68,7 +68,7 @@ public class SaOAuth2Util {
* @return LoginId
*/
public static Object getLoginIdByAccessToken(String accessToken) {
return SaOAuth2ServerProcessor.instance.oauth2Template.getLoginIdByAccessToken(accessToken);
return SaOAuth2Manager.getTemplate().getLoginIdByAccessToken(accessToken);
}
/**
@ -77,7 +77,7 @@ public class SaOAuth2Util {
* @param scopes 需要校验的权限列表
*/
public static void checkScope(String accessToken, String... scopes) {
SaOAuth2ServerProcessor.instance.oauth2Template.checkScope(accessToken, scopes);
SaOAuth2Manager.getTemplate().checkScope(accessToken, scopes);
}
/**
@ -86,7 +86,7 @@ public class SaOAuth2Util {
* @param scopes 需要校验的权限列表
*/
public static void checkClientTokenScope(String clientToken, String... scopes) {
SaOAuth2ServerProcessor.instance.oauth2Template.checkClientTokenScope(clientToken, scopes);
SaOAuth2Manager.getTemplate().checkClientTokenScope(clientToken, scopes);
}
@ -100,7 +100,7 @@ public class SaOAuth2Util {
* @return 是否已经授权
*/
public static boolean isGrant(Object loginId, String clientId, List<String> scopes) {
return SaOAuth2ServerProcessor.instance.oauth2Template.isGrant(loginId, clientId, scopes);
return SaOAuth2Manager.getTemplate().isGrant(loginId, clientId, scopes);
}
/**
@ -109,7 +109,7 @@ public class SaOAuth2Util {
* @param scopes 权限(多个用逗号隔开)
*/
public static void checkContract(String clientId, List<String> scopes) {
SaOAuth2ServerProcessor.instance.oauth2Template.checkContract(clientId, scopes);
SaOAuth2Manager.getTemplate().checkContract(clientId, scopes);
}
/**
@ -118,7 +118,7 @@ public class SaOAuth2Util {
* @param url 指定url
*/
public static void checkRightUrl(String clientId, String url) {
SaOAuth2ServerProcessor.instance.oauth2Template.checkRightUrl(clientId, url);
SaOAuth2Manager.getTemplate().checkRightUrl(clientId, url);
}
/**
@ -128,7 +128,7 @@ public class SaOAuth2Util {
* @return SaClientModel对象
*/
public static SaClientModel checkClientSecret(String clientId, String clientSecret) {
return SaOAuth2ServerProcessor.instance.oauth2Template.checkClientSecret(clientId, clientSecret);
return SaOAuth2Manager.getTemplate().checkClientSecret(clientId, clientSecret);
}
/**
@ -139,7 +139,7 @@ public class SaOAuth2Util {
* @return SaClientModel对象
*/
public static SaClientModel checkClientSecretAndScope(String clientId, String clientSecret, List<String> scopes) {
return SaOAuth2ServerProcessor.instance.oauth2Template.checkClientSecretAndScope(clientId, clientSecret, scopes);
return SaOAuth2Manager.getTemplate().checkClientSecretAndScope(clientId, clientSecret, scopes);
}
/**
@ -151,7 +151,7 @@ public class SaOAuth2Util {
* @return CodeModel对象
*/
public static CodeModel checkGainTokenParam(String code, String clientId, String clientSecret, String redirectUri) {
return SaOAuth2ServerProcessor.instance.oauth2Template.checkGainTokenParam(code, clientId, clientSecret, redirectUri);
return SaOAuth2Manager.getTemplate().checkGainTokenParam(code, clientId, clientSecret, redirectUri);
}
/**
@ -162,7 +162,7 @@ public class SaOAuth2Util {
* @return CodeModel对象
*/
public static RefreshTokenModel checkRefreshTokenParam(String clientId, String clientSecret, String refreshToken) {
return SaOAuth2ServerProcessor.instance.oauth2Template.checkRefreshTokenParam(clientId, clientSecret, refreshToken);
return SaOAuth2Manager.getTemplate().checkRefreshTokenParam(clientId, clientSecret, refreshToken);
}
/**
@ -173,7 +173,7 @@ public class SaOAuth2Util {
* @return SaClientModel对象
*/
public static AccessTokenModel checkAccessTokenParam(String clientId, String clientSecret, String accessToken) {
return SaOAuth2ServerProcessor.instance.oauth2Template.checkAccessTokenParam(clientId, clientSecret, accessToken);
return SaOAuth2Manager.getTemplate().checkAccessTokenParam(clientId, clientSecret, accessToken);
}
// ------------------- save 数据
@ -185,7 +185,7 @@ public class SaOAuth2Util {
* @param scopes 权限列表
*/
public static void saveGrantScope(String clientId, Object loginId, List<String> scopes) {
SaOAuth2ServerProcessor.instance.oauth2Template.saveGrantScope(clientId, loginId, scopes);
SaOAuth2Manager.getTemplate().saveGrantScope(clientId, loginId, scopes);
}

View File

@ -22,6 +22,7 @@ import cn.dev33.satoken.oauth2.data.convert.SaOAuth2DataConverter;
import cn.dev33.satoken.oauth2.data.generate.SaOAuth2DataGenerate;
import cn.dev33.satoken.oauth2.data.loader.SaOAuth2DataLoader;
import cn.dev33.satoken.oauth2.data.resolver.SaOAuth2DataResolver;
import cn.dev33.satoken.oauth2.granttype.handler.SaOAuth2GrantTypeHandlerInterface;
import cn.dev33.satoken.oauth2.processor.SaOAuth2ServerProcessor;
import cn.dev33.satoken.oauth2.scope.handler.SaOAuth2ScopeHandlerInterface;
import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy;
@ -62,7 +63,17 @@ public class SaOAuth2BeanInject {
*/
@Autowired(required = false)
public void setSaOAuth2Template(SaOAuth2Template saOAuth2Template) {
SaOAuth2ServerProcessor.instance.oauth2Template = saOAuth2Template;
SaOAuth2Manager.setTemplate(saOAuth2Template);
}
/**
* 注入 OAuth2 请求处理器
*
* @param serverProcessor 请求处理器
*/
@Autowired(required = false)
public void setSaOAuth2Template(SaOAuth2ServerProcessor serverProcessor) {
SaOAuth2ServerProcessor.instance = serverProcessor;
}
/**
@ -127,4 +138,16 @@ public class SaOAuth2BeanInject {
}
}
/**
* 注入自定义 grant_type 处理器
*
* @param handlerList 自定义 grant_type 处理器集合
*/
@Autowired(required = false)
public void setSaOAuth2GrantTypeHandlerInterface(List<SaOAuth2GrantTypeHandlerInterface> handlerList) {
for (SaOAuth2GrantTypeHandlerInterface handler : handlerList) {
SaOAuth2Strategy.instance.registerGrantTypeHandler(handler);
}
}
}