refactor(oauth2): 优化调整 sa-token-oauth2 模块代码结构及注释
This commit is contained in:
@@ -22,6 +22,7 @@ import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.session.raw.SaRawSessionDelegator;
|
||||
import cn.dev33.satoken.strategy.SaStrategy;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
import cn.dev33.satoken.util.SaTtlMethods;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -35,7 +36,7 @@ import java.util.*;
|
||||
* @author click33
|
||||
* @since 1.42.0
|
||||
*/
|
||||
public class SaTempTemplate {
|
||||
public class SaTempTemplate implements SaTtlMethods {
|
||||
|
||||
/**
|
||||
*默认命名空间
|
||||
@@ -256,14 +257,14 @@ public class SaTempTemplate {
|
||||
if(session == null) {
|
||||
session = rawSessionDelegator.getSessionById(value, false);
|
||||
if(session == null) {
|
||||
return newTempTokenMap();
|
||||
return newTokenIndexMap();
|
||||
}
|
||||
}
|
||||
|
||||
// 重新整理索引列表
|
||||
Map<String, Long> tempTokenNewList = newTempTokenMap();
|
||||
Map<String, Long> tempTokenNewList = newTokenIndexMap();
|
||||
ArrayList<Long> tempTokenTtlList = new ArrayList<>();
|
||||
Map<String, Long> tempTokenMap = session.get(TEMP_TOKEN_MAP, this::newTempTokenMap);
|
||||
Map<String, Long> tempTokenMap = session.get(TEMP_TOKEN_MAP, this::newTokenIndexMap);
|
||||
for (Map.Entry<String, Long> entry : tempTokenMap.entrySet()) {
|
||||
long ttl = expireTimeToTtl(entry.getValue());
|
||||
if(ttl != SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||
@@ -306,7 +307,7 @@ public class SaTempTemplate {
|
||||
* @param timeout /
|
||||
*/
|
||||
protected void addTempTokenIndex(SaSession session, String token, long timeout) {
|
||||
Map<String, Long> tempTokenMap = session.get(TEMP_TOKEN_MAP, this::newTempTokenMap);
|
||||
Map<String, Long> tempTokenMap = session.get(TEMP_TOKEN_MAP, this::newTokenIndexMap);
|
||||
if(! tempTokenMap.containsKey(token)) {
|
||||
tempTokenMap.put(token, ttlToExpireTime(timeout));
|
||||
session.set(TEMP_TOKEN_MAP, tempTokenMap);
|
||||
@@ -319,21 +320,13 @@ public class SaTempTemplate {
|
||||
* @param token /
|
||||
*/
|
||||
protected void deleteTempTokenIndex(SaSession session, String token) {
|
||||
Map<String, Long> tempTokenMap = session.get(TEMP_TOKEN_MAP, this::newTempTokenMap);
|
||||
Map<String, Long> tempTokenMap = session.get(TEMP_TOKEN_MAP, this::newTokenIndexMap);
|
||||
if(tempTokenMap.containsKey(token)) {
|
||||
tempTokenMap.remove(token);
|
||||
session.set(TEMP_TOKEN_MAP, tempTokenMap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个新的 TempTokenMap 集合
|
||||
* @return /
|
||||
*/
|
||||
protected Map<String, Long> newTempTokenMap() {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
|
||||
// -------- 元操作
|
||||
|
||||
@@ -364,55 +357,6 @@ public class SaTempTemplate {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 过期时间转 ttl (秒) 获取最大 ttl 值
|
||||
* @param tempTokenTtlList /
|
||||
* @return /
|
||||
*/
|
||||
protected long getMaxTtl(ArrayList<Long> tempTokenTtlList) {
|
||||
long maxTtl = 0;
|
||||
for (long ttl : tempTokenTtlList) {
|
||||
if(ttl == SaTokenDao.NEVER_EXPIRE) {
|
||||
maxTtl = SaTokenDao.NEVER_EXPIRE;
|
||||
break;
|
||||
}
|
||||
if(ttl > maxTtl) {
|
||||
maxTtl = ttl;
|
||||
}
|
||||
}
|
||||
return maxTtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过期时间转 ttl (秒)
|
||||
* @param expireTime /
|
||||
* @return /
|
||||
*/
|
||||
protected long expireTimeToTtl(long expireTime) {
|
||||
if(expireTime == SaTokenDao.NEVER_EXPIRE) {
|
||||
return SaTokenDao.NEVER_EXPIRE;
|
||||
}
|
||||
if(expireTime == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
}
|
||||
return (expireTime - System.currentTimeMillis()) / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* ttl (秒) 转 过期时间
|
||||
* @param ttl /
|
||||
* @return /
|
||||
*/
|
||||
protected long ttlToExpireTime(long ttl) {
|
||||
if(ttl == SaTokenDao.NEVER_EXPIRE) {
|
||||
return SaTokenDao.NEVER_EXPIRE;
|
||||
}
|
||||
if(ttl == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
}
|
||||
return ttl * 1000 + System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取:在存储临时 token 数据时,应该使用的 key
|
||||
* @param token token值
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* TTL 操作工具方法
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.43.0
|
||||
*/
|
||||
public interface SaTtlMethods {
|
||||
|
||||
/**
|
||||
* 获取一个新的 Token 集合
|
||||
* @return /
|
||||
*/
|
||||
default List<String> newTokenValueList() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个新的 TokenIndexMap 集合
|
||||
* @return /
|
||||
*/
|
||||
default Map<String, Long> newTokenIndexMap() {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最大 ttl 值
|
||||
* @param ttlList /
|
||||
* @return /
|
||||
*/
|
||||
default long getMaxTtl(ArrayList<Long> ttlList) {
|
||||
long maxTtl = 0;
|
||||
for (long ttl : ttlList) {
|
||||
if(ttl == SaTokenDao.NEVER_EXPIRE) {
|
||||
maxTtl = SaTokenDao.NEVER_EXPIRE;
|
||||
break;
|
||||
}
|
||||
if(ttl > maxTtl) {
|
||||
maxTtl = ttl;
|
||||
}
|
||||
}
|
||||
return maxTtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最大 ttl 值:过期时间 (13位时间戳) 转 ttl (秒)
|
||||
* @param expireTimeList /
|
||||
* @return /
|
||||
*/
|
||||
default long getMaxTtlByExpireTime(Collection<Long> expireTimeList) {
|
||||
long maxTtl = 0;
|
||||
for (long expireTime : expireTimeList) {
|
||||
long ttl = expireTimeToTtl(expireTime);
|
||||
if(ttl == SaTokenDao.NEVER_EXPIRE) {
|
||||
maxTtl = SaTokenDao.NEVER_EXPIRE;
|
||||
break;
|
||||
}
|
||||
if(ttl > maxTtl) {
|
||||
maxTtl = ttl;
|
||||
}
|
||||
}
|
||||
return maxTtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过期时间 (13位时间戳) 转 (13位时间戳) ttl (秒)
|
||||
* @param expireTime /
|
||||
* @return /
|
||||
*/
|
||||
default long expireTimeToTtl(long expireTime) {
|
||||
if(expireTime == SaTokenDao.NEVER_EXPIRE) {
|
||||
return SaTokenDao.NEVER_EXPIRE;
|
||||
}
|
||||
if(expireTime == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
}
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if(expireTime < currentTime) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
}
|
||||
return (expireTime - currentTime) / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* ttl (秒) 转 过期时间 (13位时间戳)
|
||||
* @param ttl /
|
||||
* @return /
|
||||
*/
|
||||
default long ttlToExpireTime(long ttl) {
|
||||
if(ttl == SaTokenDao.NEVER_EXPIRE) {
|
||||
return SaTokenDao.NEVER_EXPIRE;
|
||||
}
|
||||
if(ttl < 0) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
}
|
||||
return ttl * 1000 + System.currentTimeMillis();
|
||||
}
|
||||
|
||||
}
|
||||
+8
-4
@@ -13,6 +13,7 @@ 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.processor.SaOAuth2ServerProcessor;
|
||||
import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy;
|
||||
import cn.dev33.satoken.oauth2.template.SaOAuth2Template;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@@ -55,13 +56,16 @@ public class SaOAuth2ServerH5Controller {
|
||||
// 3、构建请求 Model
|
||||
RequestAuthModel ra = SaOAuth2Manager.getDataResolver().readRequestAuthModel(req, loginId);
|
||||
|
||||
// 4、校验:重定向域名是否合法
|
||||
// 4、开发者自定义的授权前置检查
|
||||
SaOAuth2Strategy.instance.userAuthorizeClientCheck.run(ra.loginId, ra.clientId);
|
||||
|
||||
// 5、校验:重定向域名是否合法
|
||||
oauth2Template.checkRedirectUri(ra.clientId, ra.redirectUri);
|
||||
|
||||
// 5、校验:此次申请的Scope,该Client是否已经签约
|
||||
// 6、校验:此次申请的Scope,该Client是否已经签约
|
||||
oauth2Template.checkContractScope(ra.clientId, ra.scopes);
|
||||
|
||||
// 6、判断:如果此次申请的Scope,该用户尚未授权,则转到授权页面
|
||||
// 7、判断:如果此次申请的Scope,该用户尚未授权,则转到授权页面
|
||||
boolean isNeedCarefulConfirm = oauth2Template.isNeedCarefulConfirm(ra.loginId, ra.clientId, ra.scopes);
|
||||
if(isNeedCarefulConfirm) {
|
||||
SaClientModel cm = oauth2Template.checkClientModel(ra.clientId);
|
||||
@@ -71,7 +75,7 @@ public class SaOAuth2ServerH5Controller {
|
||||
}
|
||||
}
|
||||
|
||||
// 7、判断授权类型,重定向到不同地址
|
||||
// 8、判断授权类型,重定向到不同地址
|
||||
// 如果是 授权码式,则:开始重定向授权,下放code
|
||||
if(SaOAuth2Consts.ResponseType.code.equals(ra.responseType)) {
|
||||
CodeModel codeModel = dataGenerate.generateCode(ra);
|
||||
|
||||
+25
@@ -1,11 +1,13 @@
|
||||
package com.pj.test;
|
||||
|
||||
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
|
||||
import cn.dev33.satoken.oauth2.template.SaOAuth2Util;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 测试 OAuth2 相关 token 增删查
|
||||
@@ -24,6 +26,13 @@ public class Test2Controller {
|
||||
return SaResult.data(accessTokenValueList);
|
||||
}
|
||||
|
||||
// 测试:查询全部 Access-Token, 带过期时间 --- http://localhost:8000/test/getAccessTokenIndexMap?clientId=1001&loginId=10001
|
||||
@RequestMapping("/getAccessTokenIndexMap")
|
||||
public SaResult getAccessTokenIndexMap(String clientId, long loginId) {
|
||||
Map<String, Long> accessTokenIndexMap = SaOAuth2Manager.getDao().getAccessTokenIndexMap_FromAdjustAfter(clientId, loginId);
|
||||
return SaResult.data(accessTokenIndexMap);
|
||||
}
|
||||
|
||||
// 测试:回收指定 Access-Token --- http://localhost:8000/test/revokeAccessToken?access_token=xxxxxxxxxx
|
||||
@RequestMapping("/revokeAccessToken")
|
||||
public SaResult revokeAccessToken(String access_token) {
|
||||
@@ -38,6 +47,7 @@ public class Test2Controller {
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
|
||||
// 测试:查询全部 Refresh-Token --- http://localhost:8000/test/getRefreshTokenValueList?clientId=1001&loginId=10001
|
||||
@RequestMapping("/getRefreshTokenValueList")
|
||||
public SaResult getRefreshTokenValueList(String clientId, long loginId) {
|
||||
@@ -45,6 +55,13 @@ public class Test2Controller {
|
||||
return SaResult.data(refreshTokenValueList);
|
||||
}
|
||||
|
||||
// 测试:查询全部 Refresh-Token, 带过期时间 --- http://localhost:8000/test/getRefreshTokenIndexMap?clientId=1001&loginId=10001
|
||||
@RequestMapping("/getRefreshTokenIndexMap")
|
||||
public SaResult getRefreshTokenIndexMap(String clientId, long loginId) {
|
||||
Map<String, Long> refreshTokenIndexMap = SaOAuth2Manager.getDao().getRefreshTokenIndexMap_FromAdjustAfter(clientId, loginId);
|
||||
return SaResult.data(refreshTokenIndexMap);
|
||||
}
|
||||
|
||||
// 测试:回收指定 Refresh-Token --- http://localhost:8000/test/revokeRefreshToken?refresh_token=xxxxxxxxxx
|
||||
@RequestMapping("/revokeRefreshToken")
|
||||
public SaResult revokeRefreshToken(String refresh_token) {
|
||||
@@ -59,6 +76,7 @@ public class Test2Controller {
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
|
||||
// 测试:查询全部 Client-Token --- http://localhost:8000/test/getClientTokenValueList?clientId=1001
|
||||
@RequestMapping("/getClientTokenValueList")
|
||||
public SaResult getClientTokenValueList(String clientId) {
|
||||
@@ -66,6 +84,13 @@ public class Test2Controller {
|
||||
return SaResult.data(clientTokenValueList);
|
||||
}
|
||||
|
||||
// 测试:查询全部 Client-Token, 带过期时间 --- http://localhost:8000/test/getClientTokenIndexMap?clientId=1001&loginId=10001
|
||||
@RequestMapping("/getClientTokenIndexMap")
|
||||
public SaResult getClientTokenIndexMap(String clientId, long loginId) {
|
||||
Map<String, Long> rlientTokenIndexMap = SaOAuth2Manager.getDao().getClientTokenIndexMap_FromAdjustAfter(clientId, loginId);
|
||||
return SaResult.data(rlientTokenIndexMap);
|
||||
}
|
||||
|
||||
// 测试:回收指定 Client-Token --- http://localhost:8000/test/revokeClientToken?client_token=xxxxxxxxxxx
|
||||
@RequestMapping("/revokeClientToken")
|
||||
public SaResult revokeClientToken(String client_token) {
|
||||
|
||||
+25
-2
@@ -33,19 +33,42 @@ public class SaOAuth2OidcConfig implements Serializable {
|
||||
/** idToken 有效期(单位秒) 默认十分钟 */
|
||||
public long idTokenTimeout = 60 * 10;
|
||||
|
||||
|
||||
/**
|
||||
* 获取 iss 值,如不配置则自动计算
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public String getIss() {
|
||||
return iss;
|
||||
return this.iss;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 iss 值,如不配置则自动计算
|
||||
*
|
||||
* @param iss /
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2OidcConfig setIss(String iss) {
|
||||
this.iss = iss;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 idToken 有效期(单位秒) 默认十分钟
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public long getIdTokenTimeout() {
|
||||
return idTokenTimeout;
|
||||
return this.idTokenTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 idToken 有效期(单位秒) 默认十分钟
|
||||
*
|
||||
* @param idTokenTimeout /
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2OidcConfig setIdTokenTimeout(long idTokenTimeout) {
|
||||
this.idTokenTimeout = idTokenTimeout;
|
||||
return this;
|
||||
|
||||
+92
-86
@@ -44,24 +44,18 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
/** 是否打开模式:凭证式(Client Credentials) */
|
||||
public Boolean enableClientCredentials = true;
|
||||
|
||||
/** 是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token */
|
||||
public Boolean isNewRefresh = false;
|
||||
|
||||
/** Code授权码 保存的时间(单位:秒) 默认五分钟 */
|
||||
public long codeTimeout = 60 * 5;
|
||||
|
||||
/** Access-Token 保存的时间(单位:秒) 默认两个小时 */
|
||||
/** 全局默认配置所有应用:Access-Token 保存的时间(单位:秒) 默认两个小时 */
|
||||
public long accessTokenTimeout = 60 * 60 * 2;
|
||||
|
||||
/** Refresh-Token 保存的时间(单位:秒) 默认30 天 */
|
||||
/** 全局默认配置所有应用:Refresh-Token 保存的时间(单位:秒) 默认30 天 */
|
||||
public long refreshTokenTimeout = 60 * 60 * 24 * 30;
|
||||
|
||||
/** Client-Token 保存的时间(单位:秒) 默认两个小时 */
|
||||
/** 全局默认配置所有应用:Client-Token 保存的时间(单位:秒) 默认两个小时 */
|
||||
public long clientTokenTimeout = 60 * 60 * 2;
|
||||
|
||||
/** Lower-Client-Token 保存的时间(单位:秒) 默认为 -1,代表延续 Client-Token 有效期 */
|
||||
public long lowerClientTokenTimeout = -1;
|
||||
|
||||
/** 全局默认配置所有应用:单个应用单个用户最多同时存在的 Access-Token 数量 */
|
||||
public int maxAccessTokenCount = 12;
|
||||
|
||||
@@ -71,6 +65,9 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
/** 全局默认配置所有应用:单个应用最多同时存在的 Client-Token 数量 */
|
||||
public int maxClientTokenCount = 12;
|
||||
|
||||
/** 全局默认配置所有应用:是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token */
|
||||
public Boolean isNewRefresh = false;
|
||||
|
||||
/** 默认 openid 生成算法中使用的摘要前缀 */
|
||||
public String openidDigestPrefix = SaOAuth2Consts.OPENID_DEFAULT_DIGEST_PREFIX;
|
||||
|
||||
@@ -83,7 +80,7 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
/** 指定低级权限,多个用逗号隔开 */
|
||||
public String lowerScope;
|
||||
|
||||
/** 模式4是否返回 AccessToken 字段 */
|
||||
/** 模式4是否返回 AccessToken 字段,以使其更符合 OAuth2 RFC 规范 */
|
||||
public Boolean mode4ReturnAccessToken = false;
|
||||
|
||||
/** 是否在返回值中隐藏默认的状态字段 (code、msg、data) */
|
||||
@@ -115,15 +112,17 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
// get set
|
||||
|
||||
/**
|
||||
* @return enableCode
|
||||
* 是否打开模式:授权码(Authorization Code)
|
||||
* @return enableAuthorizationCode
|
||||
*/
|
||||
public Boolean getEnableAuthorizationCode() {
|
||||
return enableAuthorizationCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param enableAuthorizationCode 要设置的 enableAuthorizationCode
|
||||
* @return /
|
||||
* 设置是否打开模式:授权码(Authorization Code)
|
||||
* @param enableAuthorizationCode 是否开启
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setEnableAuthorizationCode(Boolean enableAuthorizationCode) {
|
||||
this.enableAuthorizationCode = enableAuthorizationCode;
|
||||
@@ -131,6 +130,7 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否打开模式:隐藏式(Implicit)
|
||||
* @return enableImplicit
|
||||
*/
|
||||
public Boolean getEnableImplicit() {
|
||||
@@ -138,8 +138,9 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param enableImplicit 要设置的 enableImplicit
|
||||
* @return /
|
||||
* 设置是否打开模式:隐藏式(Implicit)
|
||||
* @param enableImplicit 是否开启
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setEnableImplicit(Boolean enableImplicit) {
|
||||
this.enableImplicit = enableImplicit;
|
||||
@@ -147,6 +148,7 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否打开模式:密码式(Password)
|
||||
* @return enablePassword
|
||||
*/
|
||||
public Boolean getEnablePassword() {
|
||||
@@ -154,7 +156,9 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param enablePassword 要设置的 enablePassword
|
||||
* 设置是否打开模式:密码式(Password)
|
||||
* @param enablePassword 是否开启
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setEnablePassword(Boolean enablePassword) {
|
||||
this.enablePassword = enablePassword;
|
||||
@@ -162,6 +166,7 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否打开模式:凭证式(Client Credentials)
|
||||
* @return enableClientCredentials
|
||||
*/
|
||||
public Boolean getEnableClientCredentials() {
|
||||
@@ -169,8 +174,9 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param enableClientCredentials 要设置的 enableClientCredentials
|
||||
* @return /
|
||||
* 设置是否打开模式:凭证式(Client Credentials)
|
||||
* @param enableClientCredentials 是否开启
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setEnableClientCredentials(Boolean enableClientCredentials) {
|
||||
this.enableClientCredentials = enableClientCredentials;
|
||||
@@ -178,6 +184,7 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局默认配置所有应用:是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token
|
||||
* @return isNewRefresh
|
||||
*/
|
||||
public Boolean getIsNewRefresh() {
|
||||
@@ -185,8 +192,9 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isNewRefresh 要设置的 isNewRefresh
|
||||
* @return /
|
||||
* 全局默认配置所有应用:设置是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token
|
||||
* @param isNewRefresh 是否开启
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setIsNewRefresh(Boolean isNewRefresh) {
|
||||
this.isNewRefresh = isNewRefresh;
|
||||
@@ -194,6 +202,7 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Code授权码 保存的时间(单位:秒) 默认五分钟
|
||||
* @return codeTimeout
|
||||
*/
|
||||
public long getCodeTimeout() {
|
||||
@@ -201,7 +210,8 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param codeTimeout 要设置的 codeTimeout
|
||||
* 设置Code授权码保存的时间(单位:秒)
|
||||
* @param codeTimeout 保存时间(秒)
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setCodeTimeout(long codeTimeout) {
|
||||
@@ -210,6 +220,7 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局默认配置所有应用:Access-Token 保存的时间(单位:秒) 默认两个小时
|
||||
* @return accessTokenTimeout
|
||||
*/
|
||||
public long getAccessTokenTimeout() {
|
||||
@@ -217,7 +228,8 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param accessTokenTimeout 要设置的 accessTokenTimeout
|
||||
* 全局默认配置所有应用:设置Access-Token保存的时间(单位:秒)
|
||||
* @param accessTokenTimeout 保存时间(秒)
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setAccessTokenTimeout(long accessTokenTimeout) {
|
||||
@@ -226,6 +238,7 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局默认配置所有应用:Refresh-Token 保存的时间(单位:秒) 默认30天
|
||||
* @return refreshTokenTimeout
|
||||
*/
|
||||
public long getRefreshTokenTimeout() {
|
||||
@@ -233,7 +246,8 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param refreshTokenTimeout 要设置的 refreshTokenTimeout
|
||||
* 全局默认配置所有应用:设置Refresh-Token保存的时间(单位:秒)
|
||||
* @param refreshTokenTimeout 保存时间(秒)
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setRefreshTokenTimeout(long refreshTokenTimeout) {
|
||||
@@ -242,6 +256,7 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局默认配置所有应用:Client-Token 保存的时间(单位:秒) 默认两个小时
|
||||
* @return clientTokenTimeout
|
||||
*/
|
||||
public long getClientTokenTimeout() {
|
||||
@@ -249,7 +264,8 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clientTokenTimeout 要设置的 clientTokenTimeout
|
||||
* 全局默认配置所有应用:设置Client-Token保存的时间(单位:秒)
|
||||
* @param clientTokenTimeout 保存时间(秒)
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setClientTokenTimeout(long clientTokenTimeout) {
|
||||
@@ -258,22 +274,7 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return lowerClientTokenTimeout
|
||||
*/
|
||||
public long getLowerClientTokenTimeout() {
|
||||
return lowerClientTokenTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lowerClientTokenTimeout 要设置的 lowerClientTokenTimeout
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setLowerClientTokenTimeout(long lowerClientTokenTimeout) {
|
||||
this.lowerClientTokenTimeout = lowerClientTokenTimeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局默认配置所有应用:单个应用单个用户最多同时存在的 Access-Token 数量
|
||||
* @return maxAccessTokenCount
|
||||
*/
|
||||
public int getMaxAccessTokenCount() {
|
||||
@@ -281,7 +282,8 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param maxAccessTokenCount 要设置的 maxAccessTokenCount
|
||||
* 设置单个应用单个用户最多同时存在的 Access-Token 数量
|
||||
* @param maxAccessTokenCount 最大数量
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setMaxAccessTokenCount(int maxAccessTokenCount) {
|
||||
@@ -291,15 +293,15 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* 全局默认配置所有应用:单个应用单个用户最多同时存在的 Refresh-Token 数量
|
||||
* @return /
|
||||
* @return maxRefreshTokenCount
|
||||
*/
|
||||
public int getMaxRefreshTokenCount() {
|
||||
return maxRefreshTokenCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局默认配置所有应用:单个应用单个用户最多同时存在的 Refresh-Token 数量
|
||||
* @param maxRefreshTokenCount /
|
||||
* 设置单个应用单个用户最多同时存在的 Refresh-Token 数量
|
||||
* @param maxRefreshTokenCount 最大数量
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setMaxRefreshTokenCount(int maxRefreshTokenCount) {
|
||||
@@ -308,16 +310,16 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局默认配置所有应用:单个应用单个用户最多同时存在的 Client-Token 数量
|
||||
* @return /
|
||||
* 全局默认配置所有应用:单个应用最多同时存在的 Client-Token 数量
|
||||
* @return maxClientTokenCount
|
||||
*/
|
||||
public int getMaxClientTokenCount() {
|
||||
return maxClientTokenCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局默认配置所有应用:单个应用单个用户最多同时存在的 Client-Token 数量
|
||||
* @param maxClientTokenCount /
|
||||
* 设置单个应用最多同时存在的 Client-Token 数量
|
||||
* @param maxClientTokenCount 最大数量
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setMaxClientTokenCount(int maxClientTokenCount) {
|
||||
@@ -326,6 +328,7 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认 openid 生成算法中使用的摘要前缀
|
||||
* @return openidDigestPrefix
|
||||
*/
|
||||
public String getOpenidDigestPrefix() {
|
||||
@@ -333,7 +336,8 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param openidDigestPrefix 要设置的 openidDigestPrefix
|
||||
* 设置默认 openid 生成算法中使用的摘要前缀
|
||||
* @param openidDigestPrefix 摘要前缀
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setOpenidDigestPrefix(String openidDigestPrefix) {
|
||||
@@ -342,6 +346,7 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认 unionid 生成算法中使用的摘要前缀
|
||||
* @return unionidDigestPrefix
|
||||
*/
|
||||
public String getUnionidDigestPrefix() {
|
||||
@@ -349,7 +354,8 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param unionidDigestPrefix 要设置的 unionidDigestPrefix
|
||||
* 设置默认 unionid 生成算法中使用的摘要前缀
|
||||
* @param unionidDigestPrefix 摘要前缀
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setUnionidDigestPrefix(String unionidDigestPrefix) {
|
||||
@@ -358,19 +364,17 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 指定高级权限,多个用逗号隔开
|
||||
*
|
||||
* @return higherScope 指定高级权限,多个用逗号隔开
|
||||
* 指定高级权限,多个用逗号隔开
|
||||
* @return higherScope
|
||||
*/
|
||||
public String getHigherScope() {
|
||||
return this.higherScope;
|
||||
return higherScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 指定高级权限,多个用逗号隔开
|
||||
*
|
||||
* @param higherScope 指定高级权限,多个用逗号隔开
|
||||
* @return /
|
||||
* 设置高级权限,多个用逗号隔开
|
||||
* @param higherScope 权限字符串
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setHigherScope(String higherScope) {
|
||||
this.higherScope = higherScope;
|
||||
@@ -378,19 +382,17 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 指定低级权限,多个用逗号隔开
|
||||
*
|
||||
* @return lowerScope 指定低级权限,多个用逗号隔开
|
||||
* 指定低级权限,多个用逗号隔开
|
||||
* @return lowerScope
|
||||
*/
|
||||
public String getLowerScope() {
|
||||
return this.lowerScope;
|
||||
return lowerScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 指定低级权限,多个用逗号隔开
|
||||
*
|
||||
* @param lowerScope 指定低级权限,多个用逗号隔开
|
||||
* @return /
|
||||
* 设置低级权限,多个用逗号隔开
|
||||
* @param lowerScope 权限字符串
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setLowerScope(String lowerScope) {
|
||||
this.lowerScope = lowerScope;
|
||||
@@ -398,6 +400,7 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 模式4是否返回 AccessToken 字段,以使其更符合 OAuth2 RFC 规范
|
||||
* @return mode4ReturnAccessToken
|
||||
*/
|
||||
public Boolean getMode4ReturnAccessToken() {
|
||||
@@ -405,7 +408,9 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mode4ReturnAccessToken 要设置的 mode4ReturnAccessToken
|
||||
* 设置模式4是否返回 AccessToken 字段,以使其更符合 OAuth2 RFC 规范
|
||||
* @param mode4ReturnAccessToken 是否返回
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setMode4ReturnAccessToken(Boolean mode4ReturnAccessToken) {
|
||||
this.mode4ReturnAccessToken = mode4ReturnAccessToken;
|
||||
@@ -413,6 +418,7 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否在返回值中隐藏默认的状态字段 (code、msg、data)
|
||||
* @return hideStatusField
|
||||
*/
|
||||
public Boolean getHideStatusField() {
|
||||
@@ -420,7 +426,9 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hideStatusField 要设置的 hideStatusField
|
||||
* 设置是否在返回值中隐藏默认的状态字段 (code、msg、data)
|
||||
* @param hideStatusField 是否隐藏
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setHideStatusField(Boolean hideStatusField) {
|
||||
this.hideStatusField = hideStatusField;
|
||||
@@ -429,18 +437,16 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* 获取oidc相关配置
|
||||
*
|
||||
* @return oidc 相关配置
|
||||
* @return oidc配置对象
|
||||
*/
|
||||
public SaOAuth2OidcConfig getOidc() {
|
||||
return this.oidc;
|
||||
return oidc;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置oidc相关配置
|
||||
*
|
||||
* @param oidc /
|
||||
* @return /
|
||||
* @param oidc oidc配置对象
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setOidc(SaOAuth2OidcConfig oidc) {
|
||||
this.oidc = oidc;
|
||||
@@ -449,15 +455,16 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* 获取client列表
|
||||
* @return /
|
||||
* @return client列表
|
||||
*/
|
||||
public Map<String, SaClientModel> getClients() {
|
||||
return clients;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入 client 列表
|
||||
* @return /
|
||||
* 设置client列表
|
||||
* @param clients client列表
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setClients(Map<String, SaClientModel> clients) {
|
||||
this.clients = clients;
|
||||
@@ -476,20 +483,19 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
", accessTokenTimeout=" + accessTokenTimeout +
|
||||
", refreshTokenTimeout=" + refreshTokenTimeout +
|
||||
", clientTokenTimeout=" + clientTokenTimeout +
|
||||
", lowerClientTokenTimeout=" + lowerClientTokenTimeout +
|
||||
", maxAccessTokenCount=" + maxAccessTokenCount +
|
||||
", maxRefreshTokenCount=" + maxRefreshTokenCount +
|
||||
", maxClientTokenCount=" + maxClientTokenCount +
|
||||
", openidDigestPrefix='" + openidDigestPrefix +
|
||||
", unionidDigestPrefix='" + unionidDigestPrefix +
|
||||
", higherScope='" + higherScope +
|
||||
", lowerScope='" + lowerScope +
|
||||
", mode4ReturnAccessToken='" + mode4ReturnAccessToken +
|
||||
", hideStatusField='" + hideStatusField +
|
||||
", oidc='" + oidc +
|
||||
", openidDigestPrefix=" + openidDigestPrefix +
|
||||
", unionidDigestPrefix=" + unionidDigestPrefix +
|
||||
", higherScope=" + higherScope +
|
||||
", lowerScope=" + lowerScope +
|
||||
", mode4ReturnAccessToken=" + mode4ReturnAccessToken +
|
||||
", hideStatusField=" + hideStatusField +
|
||||
", oidc=" + oidc +
|
||||
", clients=" + clients +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+160
-173
@@ -27,23 +27,26 @@ import cn.dev33.satoken.oauth2.data.model.RefreshTokenModel;
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.session.raw.SaRawSessionDelegator;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
import cn.dev33.satoken.util.SaTtlMethods;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.dev33.satoken.oauth2.template.SaOAuth2Util.checkClientModel;
|
||||
|
||||
/**
|
||||
* Sa-Token OAuth2 数据持久层
|
||||
* Sa-Token OAuth2 数据持久层 (在 SaTokenDao 之上再封装一层,方便 OAuth2 模块整体的数据读写操作)
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.39.0
|
||||
*/
|
||||
public class SaOAuth2Dao {
|
||||
public class SaOAuth2Dao implements SaTtlMethods {
|
||||
|
||||
// ------------------- 索引操作公共代码
|
||||
|
||||
/**
|
||||
* Raw Session 读写委托
|
||||
* Raw Session 读写委托 (存储 Access-Token、Refresh-Token、Client-Token 索引)
|
||||
*/
|
||||
public SaRawSessionDelegator oauth2RSD = new SaRawSessionDelegator("oauth2");
|
||||
|
||||
@@ -63,10 +66,11 @@ public class SaOAuth2Dao {
|
||||
public static final String CLIENT_TOKEN_MAP = "__HD_CLIENT_TOKEN_MAP";
|
||||
|
||||
/**
|
||||
* 获取 Access-Token 索引 RawSession
|
||||
* 获取:保存 Access-Token 索引时使用的 RawSession
|
||||
*
|
||||
* @param clientId 应用 id
|
||||
* @param loginId 账号 id
|
||||
* @param isCreate 如果尚未创建,是否理解创建
|
||||
* @param isCreate 如果尚未创建,是否立即创建
|
||||
* @return /
|
||||
*/
|
||||
protected SaSession getRawSessionByAccessToken(String clientId, Object loginId, boolean isCreate) {
|
||||
@@ -75,10 +79,11 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 refresh_token 索引 RawSession
|
||||
* 获取:保存 Refresh-Token 索引时使用的 RawSession
|
||||
*
|
||||
* @param clientId 应用 id
|
||||
* @param loginId 账号 id
|
||||
* @param isCreate 如果尚未创建,是否理解创建
|
||||
* @param isCreate 如果尚未创建,是否立即创建
|
||||
* @return /
|
||||
*/
|
||||
protected SaSession getRawSessionByRefreshToken(String clientId, Object loginId, boolean isCreate) {
|
||||
@@ -87,9 +92,10 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 client_token 索引 RawSession
|
||||
* 获取:保存 Client-Token 索引时使用的 RawSession
|
||||
*
|
||||
* @param clientId 应用 id
|
||||
* @param isCreate 如果尚未创建,是否理解创建
|
||||
* @param isCreate 如果尚未创建,是否立即创建
|
||||
* @return /
|
||||
*/
|
||||
protected SaSession getRawSessionByClientToken(String clientId, boolean isCreate) {
|
||||
@@ -98,7 +104,7 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 RawSession 上添加 token 索引
|
||||
* 在 RawSession 上添加 token 索引,并完整调整索引列表
|
||||
*
|
||||
* @param session 待操作的 RawSession
|
||||
* @param tokenIndexMapSaveKey 在 session 上保存 token 索引列表使用的 key
|
||||
@@ -107,19 +113,19 @@ public class SaOAuth2Dao {
|
||||
* @param maxTokenCount 允许的最多 token 数量,超出的将被删除 (-1=不限制)
|
||||
* @param removeFun 执行删除 token 的函数
|
||||
*/
|
||||
protected void addTokenIndex(SaSession session, String tokenIndexMapSaveKey, String token, long timeout, int maxTokenCount, SaParamFunction<String> removeFun) {
|
||||
protected void addTokenIndex_AndAdjust(SaSession session, String tokenIndexMapSaveKey, String token, long timeout, int maxTokenCount, SaParamFunction<String> removeFun) {
|
||||
Map<String, Long> tokenIndexMap = session.get(tokenIndexMapSaveKey, this::newTokenIndexMap);
|
||||
if(! tokenIndexMap.containsKey(token)) {
|
||||
// 添加
|
||||
tokenIndexMap.put(token, ttlToExpireTime(timeout));
|
||||
// 剔除过期的
|
||||
tokenIndexMap = removeExpiredIndex(tokenIndexMap);
|
||||
tokenIndexMap = _removeExpiredIndex(tokenIndexMap);
|
||||
// 删掉溢出的
|
||||
tokenIndexMap = removeOverflowIndex(tokenIndexMap, maxTokenCount, removeFun);
|
||||
tokenIndexMap = _removeOverflowIndex(tokenIndexMap, maxTokenCount, removeFun);
|
||||
// 保存
|
||||
session.set(tokenIndexMapSaveKey, tokenIndexMap);
|
||||
// 更新 TTL
|
||||
long maxTtl = getMaxTtl(tokenIndexMap.values());
|
||||
long maxTtl = getMaxTtlByExpireTime(tokenIndexMap.values());
|
||||
if(maxTtl != 0) {
|
||||
session.updateTimeout(maxTtl);
|
||||
}
|
||||
@@ -127,12 +133,13 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 RawSession 上删除 token 索引
|
||||
* 在 RawSession 上删除 token 索引,并尝试注销 RawSession
|
||||
*
|
||||
* @param session 待操作的 RawSession
|
||||
* @param tokenIndexMapSaveKey 在 session 上保存 token 索引列表使用的 key
|
||||
* @param token 待删除的 token
|
||||
*/
|
||||
protected void deleteTokenIndex(SaSession session, String tokenIndexMapSaveKey, String token) {
|
||||
protected void deleteTokenIndex_AndTryLogout(SaSession session, String tokenIndexMapSaveKey, String token) {
|
||||
Map<String, Long> tokenIndexMap = session.get(tokenIndexMapSaveKey, this::newTokenIndexMap);
|
||||
tokenIndexMap.remove(token);
|
||||
// 如果删除后还有记录,就再次保存
|
||||
@@ -150,7 +157,7 @@ public class SaOAuth2Dao {
|
||||
* @param tokenIndexMap token 索引列表
|
||||
* @return 调整后的索引列表
|
||||
*/
|
||||
protected Map<String, Long> removeExpiredIndex(Map<String, Long> tokenIndexMap) {
|
||||
protected Map<String, Long> _removeExpiredIndex(Map<String, Long> tokenIndexMap) {
|
||||
Map<String, Long> newTokenList = newTokenIndexMap();
|
||||
for (Map.Entry<String, Long> entry : tokenIndexMap.entrySet()) {
|
||||
long ttl = expireTimeToTtl(entry.getValue());
|
||||
@@ -169,7 +176,7 @@ public class SaOAuth2Dao {
|
||||
* @param removeFun 执行删除 token 的函数
|
||||
* @return 调整后的索引列表
|
||||
*/
|
||||
protected Map<String, Long> removeOverflowIndex(Map<String, Long> tokenIndexMap, int maxTokenCount, SaParamFunction<String> removeFun) {
|
||||
protected Map<String, Long> _removeOverflowIndex(Map<String, Long> tokenIndexMap, int maxTokenCount, SaParamFunction<String> removeFun) {
|
||||
|
||||
// 如果当前数量未超过限制,直接返回
|
||||
if (tokenIndexMap.size() <= maxTokenCount || maxTokenCount == SaTokenDao.NEVER_EXPIRE) {
|
||||
@@ -203,25 +210,25 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Token 列表
|
||||
* 从 RawSession 获取 Token 索引列表(获取之前会完整调整索引列表,保证获取的都是有效 token)
|
||||
*
|
||||
* @param session 待操作的 RawSession
|
||||
* @param tokenIndexMapSaveKey 在 session 上保存 token 索引列表使用的 key
|
||||
* @return /
|
||||
*/
|
||||
protected List<String> getTokenValueList(SaSession session, String tokenIndexMapSaveKey) {
|
||||
protected Map<String, Long> getTokenIndexMap_FromAdjustAfter(SaSession session, String tokenIndexMapSaveKey) {
|
||||
if(session == null) {
|
||||
return new ArrayList<>();
|
||||
return newTokenIndexMap();
|
||||
}
|
||||
|
||||
// 根据 ttl 值过滤一遍
|
||||
Map<String, Long> tokenIndexMap = session.get(tokenIndexMapSaveKey, this::newTokenIndexMap);
|
||||
Map<String, Long> newTokenIndexMap = removeExpiredIndex(tokenIndexMap);
|
||||
Map<String, Long> newTokenIndexMap = _removeExpiredIndex(tokenIndexMap);
|
||||
|
||||
// 如果调整后集合长度归零了,说明 token 已全部过期,直接注销此 RawSession
|
||||
if(newTokenIndexMap.isEmpty()) {
|
||||
session.logout();
|
||||
return new ArrayList<>();
|
||||
return newTokenIndexMap();
|
||||
}
|
||||
|
||||
// 没有归零,但是长度变小了,说明有过期的 token,需要重写写入一遍
|
||||
@@ -230,15 +237,26 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
// 转 List 返回
|
||||
return new ArrayList<>(newTokenIndexMap.keySet());
|
||||
return newTokenIndexMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 RawSession 获取 Token 列表(获取之前会完整调整索引列表,保证获取的都是有效 token)
|
||||
*
|
||||
* @param session 待操作的 RawSession
|
||||
* @param tokenIndexMapSaveKey 在 session 上保存 token 索引列表使用的 key
|
||||
* @return /
|
||||
*/
|
||||
protected List<String> getTokenValueList_FromAdjustAfter(SaSession session, String tokenIndexMapSaveKey) {
|
||||
return new ArrayList<>(getTokenIndexMap_FromAdjustAfter(session, tokenIndexMapSaveKey).keySet());
|
||||
}
|
||||
|
||||
|
||||
// ------------------- code 操作
|
||||
|
||||
/**
|
||||
* 持久化:Code-Model
|
||||
* @param c .
|
||||
* 保存:CodeModel
|
||||
* @param c /
|
||||
*/
|
||||
public void saveCode(CodeModel c) {
|
||||
if(c == null) {
|
||||
@@ -248,8 +266,8 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除:Code
|
||||
* @param code 值
|
||||
* 删除:CodeModel
|
||||
* @param code /
|
||||
*/
|
||||
public void deleteCode(String code) {
|
||||
if(code != null) {
|
||||
@@ -259,8 +277,8 @@ public class SaOAuth2Dao {
|
||||
|
||||
/**
|
||||
* 获取:CodeModel
|
||||
* @param code .
|
||||
* @return .
|
||||
* @param code /
|
||||
* @return /
|
||||
*/
|
||||
public CodeModel getCode(String code) {
|
||||
if(code == null) {
|
||||
@@ -273,8 +291,8 @@ public class SaOAuth2Dao {
|
||||
// ------------------- code 索引
|
||||
|
||||
/**
|
||||
* 持久化:Code-索引
|
||||
* @param c .
|
||||
* 保存:Code 索引
|
||||
* @param c /
|
||||
*/
|
||||
public void saveCodeIndex(CodeModel c) {
|
||||
if(c == null) {
|
||||
@@ -296,18 +314,18 @@ public class SaOAuth2Dao {
|
||||
* 获取:Code Value
|
||||
* @param clientId 应用id
|
||||
* @param loginId 账号id
|
||||
* @return .
|
||||
* @return /
|
||||
*/
|
||||
public String getCodeValue(String clientId, Object loginId) {
|
||||
return getSaTokenDao().get(splicingCodeIndexKey(clientId, loginId));
|
||||
}
|
||||
|
||||
|
||||
// ------------------- access_token Model
|
||||
// ------------------- Access-Token Model
|
||||
|
||||
/**
|
||||
* 持久化:AccessToken-Model
|
||||
* @param at .
|
||||
* 保存:AccessTokenModel
|
||||
* @param at /
|
||||
*/
|
||||
public void saveAccessToken(AccessTokenModel at) {
|
||||
if(at == null) {
|
||||
@@ -317,7 +335,7 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除:Access-Token
|
||||
* 删除:AccessTokenModel
|
||||
* @param accessToken 值
|
||||
*/
|
||||
public void deleteAccessToken(String accessToken) {
|
||||
@@ -327,9 +345,9 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取:Access-Token Model
|
||||
* @param accessToken .
|
||||
* @return .
|
||||
* 获取:AccessTokenModel
|
||||
* @param accessToken /
|
||||
* @return /
|
||||
*/
|
||||
public AccessTokenModel getAccessToken(String accessToken) {
|
||||
if(accessToken == null) {
|
||||
@@ -339,20 +357,20 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
|
||||
// ------------------- access_token 索引
|
||||
// ------------------- Access-Token 索引
|
||||
|
||||
/**
|
||||
* 持久化:Access-Token 索引
|
||||
* 保存:Access-Token 索引,并完整调整索引列表
|
||||
*
|
||||
* @param at /
|
||||
* @param maxAccessTokenCount 允许的最多 Access-Token 数量,超出的将被删除 (-1=不限制)
|
||||
*/
|
||||
public void saveAccessTokenIndex(AccessTokenModel at, int maxAccessTokenCount) {
|
||||
public void saveAccessTokenIndex_AndAdjust(AccessTokenModel at, int maxAccessTokenCount) {
|
||||
if(at == null) {
|
||||
return;
|
||||
}
|
||||
SaSession session = getRawSessionByAccessToken(at.clientId, at.loginId, true);
|
||||
addTokenIndex(session, ACCESS_TOKEN_MAP, at.accessToken, at.getExpiresIn(), maxAccessTokenCount, this::deleteAccessToken);
|
||||
addTokenIndex_AndAdjust(session, ACCESS_TOKEN_MAP, at.accessToken, at.getExpiresIn(), maxAccessTokenCount, this::deleteAccessToken);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -362,12 +380,12 @@ public class SaOAuth2Dao {
|
||||
* @param loginId 账号id
|
||||
* @param accessToken 值
|
||||
*/
|
||||
public void deleteAccessTokenIndexBySingleData(String clientId, Object loginId, String accessToken) {
|
||||
public void deleteAccessTokenIndex_BySingleData(String clientId, Object loginId, String accessToken) {
|
||||
SaSession session = getRawSessionByAccessToken(clientId, loginId, false);
|
||||
if(session == null) {
|
||||
return;
|
||||
}
|
||||
deleteTokenIndex(session, ACCESS_TOKEN_MAP, accessToken);
|
||||
deleteTokenIndex_AndTryLogout(session, ACCESS_TOKEN_MAP, accessToken);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -380,22 +398,34 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Access-Token 列表:此应用下 对 某个用户 签发的所有 Access-token
|
||||
* 获取 Access-Token 索引列表(获取之前会完整调整索引列表,保证获取的都是有效 AccessToken 索引)
|
||||
*
|
||||
* @param clientId 应用id
|
||||
* @param loginId 账号id
|
||||
* @return /
|
||||
*/
|
||||
public List<String> getAccessTokenValueList(String clientId, Object loginId) {
|
||||
public Map<String, Long> getAccessTokenIndexMap_FromAdjustAfter(String clientId, Object loginId) {
|
||||
SaSession session = getRawSessionByAccessToken(clientId, loginId, false);
|
||||
return getTokenValueList(session, ACCESS_TOKEN_MAP);
|
||||
return getTokenIndexMap_FromAdjustAfter(session, ACCESS_TOKEN_MAP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Access-Token 列表(获取之前会完整调整索引列表,保证获取的都是有效 AccessToken)
|
||||
*
|
||||
* @param clientId 应用id
|
||||
* @param loginId 账号id
|
||||
* @return /
|
||||
*/
|
||||
public List<String> getAccessTokenValueList_FromAdjustAfter(String clientId, Object loginId) {
|
||||
SaSession session = getRawSessionByAccessToken(clientId, loginId, false);
|
||||
return getTokenValueList_FromAdjustAfter(session, ACCESS_TOKEN_MAP);
|
||||
}
|
||||
|
||||
|
||||
// ------------------- refresh_token Model
|
||||
// ------------------- Refresh-Token Model
|
||||
|
||||
/**
|
||||
* 持久化:RefreshToken-Model
|
||||
* 保存:RefreshTokenModel
|
||||
* @param rt .
|
||||
*/
|
||||
public void saveRefreshToken(RefreshTokenModel rt) {
|
||||
@@ -406,7 +436,7 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除:Refresh-Token
|
||||
* 删除:RefreshTokenModel
|
||||
* @param refreshToken 值
|
||||
*/
|
||||
public void deleteRefreshToken(String refreshToken) {
|
||||
@@ -416,9 +446,9 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取:Refresh-Token Model
|
||||
* @param refreshToken .
|
||||
* @return .
|
||||
* 获取:RefreshTokenModel
|
||||
* @param refreshToken /
|
||||
* @return /
|
||||
*/
|
||||
public RefreshTokenModel getRefreshToken(String refreshToken) {
|
||||
if(refreshToken == null) {
|
||||
@@ -428,20 +458,20 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
|
||||
// ------------------- refresh_token 索引
|
||||
// ------------------- Refresh-Token 索引
|
||||
|
||||
/**
|
||||
* 持久化:Refresh-Token 索引
|
||||
* 保存:Refresh-Token 索引
|
||||
*
|
||||
* @param rt /
|
||||
* @param maxRefreshTokenCount 允许的最多 Refresh-Token 数量,超出的将被删除 (-1=不限制)
|
||||
*/
|
||||
public void saveRefreshTokenIndex(RefreshTokenModel rt, int maxRefreshTokenCount) {
|
||||
public void saveRefreshTokenIndex_AndAdjust(RefreshTokenModel rt, int maxRefreshTokenCount) {
|
||||
if(rt == null) {
|
||||
return;
|
||||
}
|
||||
SaSession session = getRawSessionByRefreshToken(rt.clientId, rt.loginId, true);
|
||||
addTokenIndex(session, REFRESH_TOKEN_MAP, rt.refreshToken, rt.getExpiresIn(), maxRefreshTokenCount, this::deleteRefreshToken);
|
||||
addTokenIndex_AndAdjust(session, REFRESH_TOKEN_MAP, rt.refreshToken, rt.getExpiresIn(), maxRefreshTokenCount, this::deleteRefreshToken);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -451,12 +481,12 @@ public class SaOAuth2Dao {
|
||||
* @param loginId 账号id
|
||||
* @param refreshToken 值
|
||||
*/
|
||||
public void deleteRefreshTokenIndexBySingleData(String clientId, Object loginId, String refreshToken) {
|
||||
public void deleteRefreshTokenIndex_BySingleData(String clientId, Object loginId, String refreshToken) {
|
||||
SaSession session = getRawSessionByRefreshToken(clientId, loginId, false);
|
||||
if(session == null) {
|
||||
return;
|
||||
}
|
||||
deleteTokenIndex(session, REFRESH_TOKEN_MAP, refreshToken);
|
||||
deleteTokenIndex_AndTryLogout(session, REFRESH_TOKEN_MAP, refreshToken);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -469,22 +499,34 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Refresh-Token 列表:此应用下 对 某个用户 签发的所有 Refresh-token
|
||||
* 获取 Refresh-Token 索引列表(获取之前会完整调整索引列表,保证获取的都是有效 RefreshToken 索引)
|
||||
*
|
||||
* @param clientId 应用id
|
||||
* @param loginId 账号id
|
||||
* @return /
|
||||
*/
|
||||
public List<String> getRefreshTokenValueList(String clientId, Object loginId) {
|
||||
public Map<String, Long> getRefreshTokenIndexMap_FromAdjustAfter(String clientId, Object loginId) {
|
||||
SaSession session = getRawSessionByRefreshToken(clientId, loginId, false);
|
||||
return getTokenValueList(session, REFRESH_TOKEN_MAP);
|
||||
return getTokenIndexMap_FromAdjustAfter(session, REFRESH_TOKEN_MAP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Refresh-Token 列表(获取之前会完整调整索引列表,保证获取的都是有效 RefreshToken)
|
||||
*
|
||||
* @param clientId 应用id
|
||||
* @param loginId 账号id
|
||||
* @return /
|
||||
*/
|
||||
public List<String> getRefreshTokenValueList_FromAdjustAfter(String clientId, Object loginId) {
|
||||
SaSession session = getRawSessionByRefreshToken(clientId, loginId, false);
|
||||
return getTokenValueList_FromAdjustAfter(session, REFRESH_TOKEN_MAP);
|
||||
}
|
||||
|
||||
|
||||
// ------------------- client_token Model
|
||||
// ------------------- Client-Token Model
|
||||
|
||||
/**
|
||||
* 持久化:ClientToken-Model
|
||||
* 保存:ClientTokenModel
|
||||
* @param ct .
|
||||
*/
|
||||
public void saveClientToken(ClientTokenModel ct) {
|
||||
@@ -495,7 +537,7 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除:Client-Token
|
||||
* 删除:ClientTokenModel
|
||||
* @param clientToken 值
|
||||
*/
|
||||
public void deleteClientToken(String clientToken) {
|
||||
@@ -505,9 +547,9 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取:Client-Token Model
|
||||
* @param clientToken .
|
||||
* @return .
|
||||
* 获取:ClientTokenModel
|
||||
* @param clientToken /
|
||||
* @return /
|
||||
*/
|
||||
public ClientTokenModel getClientToken(String clientToken) {
|
||||
if(clientToken == null) {
|
||||
@@ -517,20 +559,20 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
|
||||
// ------------------- client_token 索引
|
||||
// ------------------- Client-Token 索引
|
||||
|
||||
/**
|
||||
* 持久化:Client-Token 索引
|
||||
* 保存:Client-Token 索引
|
||||
*
|
||||
* @param ct /
|
||||
* @param maxClientTokenCount 允许的最多 Client-Token 数量,超出的将被删除 (-1=不限制)
|
||||
*/
|
||||
public void saveClientTokenIndex(ClientTokenModel ct, int maxClientTokenCount) {
|
||||
public void saveClientTokenIndex_AndAdjust(ClientTokenModel ct, int maxClientTokenCount) {
|
||||
if(ct == null) {
|
||||
return;
|
||||
}
|
||||
SaSession session = getRawSessionByClientToken(ct.clientId, true);
|
||||
addTokenIndex(session, CLIENT_TOKEN_MAP, ct.clientToken, ct.getExpiresIn(), maxClientTokenCount, this::deleteClientToken);
|
||||
addTokenIndex_AndAdjust(session, CLIENT_TOKEN_MAP, ct.clientToken, ct.getExpiresIn(), maxClientTokenCount, this::deleteClientToken);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -538,12 +580,12 @@ public class SaOAuth2Dao {
|
||||
* @param clientId 应用 id
|
||||
* @param clientToken 值
|
||||
*/
|
||||
public void deleteClientTokenIndexBySingleData(String clientId, String clientToken) {
|
||||
public void deleteClientTokenIndex_BySingleData(String clientId, String clientToken) {
|
||||
SaSession session = getRawSessionByClientToken(clientId, false);
|
||||
if(session == null) {
|
||||
return;
|
||||
}
|
||||
deleteTokenIndex(session, CLIENT_TOKEN_MAP, clientToken);
|
||||
deleteTokenIndex_AndTryLogout(session, CLIENT_TOKEN_MAP, clientToken);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -556,21 +598,33 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Client-Token 列表:此应用下 对 某个用户 签发的所有 Client-token
|
||||
* 获取 Client-Token 索引列表(获取之前会完整调整索引列表,保证获取的都是有效 ClientToken 索引)
|
||||
*
|
||||
* @param clientId 应用id
|
||||
* @param loginId 账号id
|
||||
* @return /
|
||||
*/
|
||||
public Map<String, Long> getClientTokenIndexMap_FromAdjustAfter(String clientId, Object loginId) {
|
||||
SaSession session = getRawSessionByClientToken(clientId, false);
|
||||
return getTokenIndexMap_FromAdjustAfter(session, CLIENT_TOKEN_MAP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Client-Token 列表(获取之前会完整调整索引列表,保证获取的都是有效 ClientToken)
|
||||
*
|
||||
* @param clientId 应用id
|
||||
* @return /
|
||||
*/
|
||||
public List<String> getClientTokenValueList(String clientId) {
|
||||
public List<String> getClientTokenValueList_FromAdjustAfter(String clientId) {
|
||||
SaSession session = getRawSessionByClientToken(clientId, false);
|
||||
return getTokenValueList(session, CLIENT_TOKEN_MAP);
|
||||
return getTokenValueList_FromAdjustAfter(session, CLIENT_TOKEN_MAP);
|
||||
}
|
||||
|
||||
|
||||
// ------------------- GrantScope
|
||||
|
||||
/**
|
||||
* 持久化:用户授权记录
|
||||
* 保存:用户授权记录
|
||||
* @param clientId 应用id
|
||||
* @param loginId 账号id
|
||||
* @param scopes 权限列表
|
||||
@@ -607,7 +661,7 @@ public class SaOAuth2Dao {
|
||||
// ------------------- State
|
||||
|
||||
/**
|
||||
* 持久化:state
|
||||
* 保存:state
|
||||
* @param state /
|
||||
*/
|
||||
public void saveState(String state) {
|
||||
@@ -641,8 +695,8 @@ public class SaOAuth2Dao {
|
||||
// ------------------- 其它
|
||||
|
||||
/**
|
||||
* 持久化:nonce-索引
|
||||
* @param c .
|
||||
* 保存:nonce-索引
|
||||
* @param c /
|
||||
*/
|
||||
public void saveCodeNonceIndex(CodeModel c) {
|
||||
if(c == null || SaFoxUtil.isEmpty(c.nonce)) {
|
||||
@@ -667,7 +721,7 @@ public class SaOAuth2Dao {
|
||||
// ------------------- 拼接key
|
||||
|
||||
/**
|
||||
* 拼接key:Code持久化
|
||||
* 拼接 key:Code 保存
|
||||
* @param code 授权码
|
||||
* @return key
|
||||
*/
|
||||
@@ -686,7 +740,7 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接key:Access-Token持久化
|
||||
* 拼接 key:Access-Token 保存
|
||||
* @param accessToken accessToken
|
||||
* @return key
|
||||
*/
|
||||
@@ -704,6 +758,15 @@ public class SaOAuth2Dao {
|
||||
return "access-token:" + clientId + ":" + loginId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接 key:Refresh-Token 保存
|
||||
* @param refreshToken refreshToken
|
||||
* @return key
|
||||
*/
|
||||
public String splicingRefreshTokenSaveKey(String refreshToken) {
|
||||
return getSaTokenConfig().getTokenName() + ":oauth2:refresh-token:" + refreshToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接 key:Refresh-Token RSD Value
|
||||
* @param clientId 应用id
|
||||
@@ -714,6 +777,15 @@ public class SaOAuth2Dao {
|
||||
return "refresh-token:" + clientId + ":" + loginId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接 key:Client-Token 保存
|
||||
* @param clientToken clientToken
|
||||
* @return key
|
||||
*/
|
||||
public String splicingClientTokenSaveKey(String clientToken) {
|
||||
return getSaTokenConfig().getTokenName() + ":oauth2:client-token:" + clientToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接 key:Client-Token RSD Value
|
||||
* @param clientId 应用id
|
||||
@@ -723,24 +795,6 @@ public class SaOAuth2Dao {
|
||||
return "client-token:" + clientId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接key:Refresh-Token持久化
|
||||
* @param refreshToken refreshToken
|
||||
* @return key
|
||||
*/
|
||||
public String splicingRefreshTokenSaveKey(String refreshToken) {
|
||||
return getSaTokenConfig().getTokenName() + ":oauth2:refresh-token:" + refreshToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接key:Client-Token持久化
|
||||
* @param clientToken clientToken
|
||||
* @return key
|
||||
*/
|
||||
public String splicingClientTokenSaveKey(String clientToken) {
|
||||
return getSaTokenConfig().getTokenName() + ":oauth2:client-token:" + clientToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接 key:用户授权记录
|
||||
* @param clientId 应用id
|
||||
@@ -752,7 +806,7 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接key:state 参数持久化
|
||||
* 拼接 key:state 参数保存
|
||||
* @param state /
|
||||
* @return key
|
||||
*/
|
||||
@@ -761,7 +815,7 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接key:code-nonce 索引 参数持久化
|
||||
* 拼接 key:code-nonce 索引 参数保存
|
||||
* @param code 授权码
|
||||
* @return key
|
||||
*/
|
||||
@@ -770,73 +824,6 @@ public class SaOAuth2Dao {
|
||||
}
|
||||
|
||||
|
||||
// -------- 工具方法
|
||||
|
||||
/**
|
||||
* 获取一个新的 TokenMap 集合
|
||||
* @return /
|
||||
*/
|
||||
protected Map<String, Long> newTokenIndexMap() {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 过期时间转 ttl (秒) 获取最大 ttl 值
|
||||
* @param expireTimeList /
|
||||
* @return /
|
||||
*/
|
||||
protected long getMaxTtl(Collection<Long> expireTimeList) {
|
||||
long maxTtl = 0;
|
||||
for (long expireTime : expireTimeList) {
|
||||
long ttl = expireTimeToTtl(expireTime);
|
||||
if(ttl == SaTokenDao.NEVER_EXPIRE) {
|
||||
maxTtl = SaTokenDao.NEVER_EXPIRE;
|
||||
break;
|
||||
}
|
||||
if(ttl > maxTtl) {
|
||||
maxTtl = ttl;
|
||||
}
|
||||
}
|
||||
return maxTtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过期时间转 ttl (秒)
|
||||
* @param expireTime /
|
||||
* @return /
|
||||
*/
|
||||
protected long expireTimeToTtl(long expireTime) {
|
||||
if(expireTime == SaTokenDao.NEVER_EXPIRE) {
|
||||
return SaTokenDao.NEVER_EXPIRE;
|
||||
}
|
||||
if(expireTime == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
}
|
||||
// TODO temp-token 模块与 apikey 模块是否也应该修改为这个逻辑 ?
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if(expireTime < currentTime) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
}
|
||||
return (expireTime - currentTime) / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* ttl (秒) 转 过期时间
|
||||
* @param ttl /
|
||||
* @return /
|
||||
*/
|
||||
protected long ttlToExpireTime(long ttl) {
|
||||
if(ttl == SaTokenDao.NEVER_EXPIRE) {
|
||||
return SaTokenDao.NEVER_EXPIRE;
|
||||
}
|
||||
if(ttl == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
}
|
||||
return ttl * 1000 + System.currentTimeMillis();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -------- bean 对象代理
|
||||
|
||||
/**
|
||||
|
||||
+38
-8
@@ -16,8 +16,11 @@
|
||||
package cn.dev33.satoken.oauth2.data.convert;
|
||||
|
||||
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.ClientTokenModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.CodeModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.RefreshTokenModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.request.RequestAuthModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -51,31 +54,58 @@ public interface SaOAuth2DataConverter {
|
||||
List<String> convertRedirectUriStringToList(String redirectUris);
|
||||
|
||||
/**
|
||||
* 将 Code 转换为 Access-Token
|
||||
* 根据 RequestAuthModel 构建一个 CodeModel
|
||||
* @param ra RequestAuthModel
|
||||
* @return CodeModel 对象
|
||||
*/
|
||||
CodeModel convertRequestAuthToCode(RequestAuthModel ra);
|
||||
|
||||
/**
|
||||
* 根据 RequestAuthModel 构建一个 AccessTokenModel
|
||||
* @param ra RequestAuthModel
|
||||
* @param accessTokenTimeout Access-Token 有效期 (单位:秒)
|
||||
* @return AccessTokenModel 对象
|
||||
*/
|
||||
AccessTokenModel convertRequestAuthToAccessToken(RequestAuthModel ra, long accessTokenTimeout);
|
||||
|
||||
/**
|
||||
* 根据 Code 构建一个 Access-Token
|
||||
* @param cm CodeModel对象
|
||||
* @param accessTokenTimeout Access-Token 有效期 (单位:秒)
|
||||
* @return AccessToken对象
|
||||
*/
|
||||
AccessTokenModel convertCodeToAccessToken(CodeModel cm);
|
||||
AccessTokenModel convertCodeToAccessToken(CodeModel cm, long accessTokenTimeout);
|
||||
|
||||
/**
|
||||
* 将 Access-Token 转换为 Refresh-Token
|
||||
* 根据 Access-Token 构建一个 Refresh-Token
|
||||
* @param at /
|
||||
* @param refreshTokenTimeout Refresh-Token 有效期 (单位:秒)
|
||||
* @return /
|
||||
*/
|
||||
RefreshTokenModel convertAccessTokenToRefreshToken(AccessTokenModel at);
|
||||
RefreshTokenModel convertAccessTokenToRefreshToken(AccessTokenModel at, long refreshTokenTimeout);
|
||||
|
||||
/**
|
||||
* 将 Refresh-Token 转换为 Access-Token
|
||||
* 根据 Refresh-Token 构建一个 Access-Token
|
||||
* @param rt /
|
||||
* @param accessTokenTimeout Access-Token 有效期 (单位:秒)
|
||||
* @return /
|
||||
*/
|
||||
AccessTokenModel convertRefreshTokenToAccessToken(RefreshTokenModel rt);
|
||||
AccessTokenModel convertRefreshTokenToAccessToken(RefreshTokenModel rt, long accessTokenTimeout);
|
||||
|
||||
/**
|
||||
* 根据 Refresh-Token 创建一个新的 Refresh-Token
|
||||
* 根据 Refresh-Token 构建一个新的 Refresh-Token
|
||||
* @param rt /
|
||||
* @param refreshTokenTimeout Refresh-Token 有效期 (单位:秒)
|
||||
* @return /
|
||||
*/
|
||||
RefreshTokenModel convertRefreshTokenToRefreshToken(RefreshTokenModel rt);
|
||||
RefreshTokenModel convertRefreshTokenToRefreshToken(RefreshTokenModel rt, long refreshTokenTimeout);
|
||||
|
||||
/**
|
||||
* 根据 SaClientModel 构建一个 ClientTokenModel
|
||||
* @param clientModel /
|
||||
* @param scopes 权限列表
|
||||
* @return /
|
||||
*/
|
||||
ClientTokenModel convertSaClientToClientToken(SaClientModel clientModel, List<String> scopes);
|
||||
|
||||
}
|
||||
|
||||
+73
-27
@@ -15,15 +15,17 @@
|
||||
*/
|
||||
package cn.dev33.satoken.oauth2.data.convert;
|
||||
|
||||
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.ClientTokenModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.CodeModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.RefreshTokenModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.request.RequestAuthModel;
|
||||
import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
import cn.dev33.satoken.util.SaTtlMethods;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -35,7 +37,7 @@ import java.util.List;
|
||||
* @author click33
|
||||
* @since 1.39.0
|
||||
*/
|
||||
public class SaOAuth2DataConverterDefaultImpl implements SaOAuth2DataConverter {
|
||||
public class SaOAuth2DataConverterDefaultImpl implements SaOAuth2DataConverter, SaTtlMethods {
|
||||
|
||||
/**
|
||||
* 转换 scope 数据格式:String -> List
|
||||
@@ -72,10 +74,47 @@ public class SaOAuth2DataConverterDefaultImpl implements SaOAuth2DataConverter {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 Code 转换为 Access-Token
|
||||
* 根据 RequestAuthModel 构建一个 CodeModel
|
||||
* @param ra RequestAuthModel
|
||||
* @return CodeModel 对象
|
||||
*/
|
||||
@Override
|
||||
public AccessTokenModel convertCodeToAccessToken(CodeModel cm) {
|
||||
public CodeModel convertRequestAuthToCode(RequestAuthModel ra){
|
||||
String codeValue = SaOAuth2Strategy.instance.createCodeValue.execute(ra.clientId, ra.loginId, ra.scopes);
|
||||
CodeModel cm = new CodeModel();
|
||||
cm.code = codeValue;
|
||||
cm.clientId = ra.clientId;
|
||||
cm.scopes = ra.scopes;
|
||||
cm.loginId = ra.loginId;
|
||||
cm.redirectUri = ra.redirectUri;
|
||||
cm.nonce = ra.getNonce();
|
||||
return cm;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 RequestAuthModel 构建一个 AccessTokenModel
|
||||
* @param ra RequestAuthModel
|
||||
* @return AccessTokenModel 对象
|
||||
*/
|
||||
@Override
|
||||
public AccessTokenModel convertRequestAuthToAccessToken(RequestAuthModel ra, long accessTokenTimeout) {
|
||||
String newAtValue = SaOAuth2Strategy.instance.createAccessToken.execute(ra.clientId, ra.loginId, ra.scopes);
|
||||
AccessTokenModel at = new AccessTokenModel();
|
||||
at.accessToken = newAtValue;
|
||||
at.clientId = ra.clientId;
|
||||
at.loginId = ra.loginId;
|
||||
at.scopes = ra.scopes;
|
||||
at.tokenType = SaOAuth2Consts.TokenType.bearer;
|
||||
at.expiresTime = ttlToExpireTime(accessTokenTimeout);
|
||||
at.extraData = new LinkedHashMap<>();
|
||||
return at;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 Code 构建一个 Access-Token
|
||||
*/
|
||||
@Override
|
||||
public AccessTokenModel convertCodeToAccessToken(CodeModel cm, long accessTokenTimeout) {
|
||||
AccessTokenModel at = new AccessTokenModel();
|
||||
at.accessToken = SaOAuth2Strategy.instance.createAccessToken.execute(cm.clientId, cm.loginId, cm.scopes);
|
||||
at.clientId = cm.clientId;
|
||||
@@ -83,40 +122,31 @@ public class SaOAuth2DataConverterDefaultImpl implements SaOAuth2DataConverter {
|
||||
at.scopes = cm.scopes;
|
||||
at.tokenType = SaOAuth2Consts.TokenType.bearer;
|
||||
at.grantType = GrantType.authorization_code;
|
||||
SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(cm.clientId);
|
||||
at.expiresTime = System.currentTimeMillis() + (clientModel.getAccessTokenTimeout() * 1000);
|
||||
at.expiresTime = ttlToExpireTime(accessTokenTimeout);
|
||||
at.extraData = new LinkedHashMap<>();
|
||||
return at;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 Access-Token 转换为 Refresh-Token
|
||||
* @param at .
|
||||
* @return .
|
||||
* 根据 Access-Token 构建一个 Refresh-Token
|
||||
*/
|
||||
@Override
|
||||
public RefreshTokenModel convertAccessTokenToRefreshToken(AccessTokenModel at) {
|
||||
public RefreshTokenModel convertAccessTokenToRefreshToken(AccessTokenModel at, long refreshTokenTimeout) {
|
||||
RefreshTokenModel rt = new RefreshTokenModel();
|
||||
rt.refreshToken = SaOAuth2Strategy.instance.createRefreshToken.execute(at.clientId, at.loginId, at.scopes);
|
||||
rt.clientId = at.clientId;
|
||||
rt.loginId = at.loginId;
|
||||
rt.scopes = at.scopes;
|
||||
SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(at.clientId);
|
||||
rt.expiresTime = System.currentTimeMillis() + (clientModel.getRefreshTokenTimeout() * 1000);
|
||||
rt.expiresTime = ttlToExpireTime(refreshTokenTimeout);
|
||||
rt.extraData = new LinkedHashMap<>(at.extraData);
|
||||
// 改变 at 属性
|
||||
// at.refreshToken = rt.refreshToken;
|
||||
// at.refreshExpiresTime = rt.expiresTime;
|
||||
return rt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 Refresh-Token 转换为 Access-Token
|
||||
* @param rt .
|
||||
* @return .
|
||||
* 根据 Refresh-Token 构建一个 Access-Token
|
||||
*/
|
||||
@Override
|
||||
public AccessTokenModel convertRefreshTokenToAccessToken(RefreshTokenModel rt) {
|
||||
public AccessTokenModel convertRefreshTokenToAccessToken(RefreshTokenModel rt, long accessTokenTimeout) {
|
||||
AccessTokenModel at = new AccessTokenModel();
|
||||
at.accessToken = SaOAuth2Strategy.instance.createAccessToken.execute(rt.clientId, rt.loginId, rt.scopes);
|
||||
at.refreshToken = rt.refreshToken;
|
||||
@@ -126,23 +156,19 @@ public class SaOAuth2DataConverterDefaultImpl implements SaOAuth2DataConverter {
|
||||
at.tokenType = SaOAuth2Consts.TokenType.bearer;
|
||||
at.grantType = GrantType.refresh_token;
|
||||
at.extraData = new LinkedHashMap<>(rt.extraData);
|
||||
SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(rt.clientId);
|
||||
at.expiresTime = System.currentTimeMillis() + (clientModel.getAccessTokenTimeout() * 1000);
|
||||
at.expiresTime = ttlToExpireTime(accessTokenTimeout);
|
||||
at.refreshExpiresTime = rt.expiresTime;
|
||||
return at;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 Refresh-Token 创建一个新的 Refresh-Token
|
||||
* @param rt .
|
||||
* @return .
|
||||
* 根据 Refresh-Token 构建一个新的 Refresh-Token
|
||||
*/
|
||||
@Override
|
||||
public RefreshTokenModel convertRefreshTokenToRefreshToken(RefreshTokenModel rt) {
|
||||
public RefreshTokenModel convertRefreshTokenToRefreshToken(RefreshTokenModel rt, long refreshTokenTimeout) {
|
||||
RefreshTokenModel newRt = new RefreshTokenModel();
|
||||
newRt.refreshToken = SaOAuth2Strategy.instance.createRefreshToken.execute(rt.clientId, rt.loginId, rt.scopes);
|
||||
SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(rt.clientId);
|
||||
newRt.expiresTime = System.currentTimeMillis() + (clientModel.getRefreshTokenTimeout() * 1000);
|
||||
newRt.expiresTime = ttlToExpireTime(refreshTokenTimeout);
|
||||
newRt.clientId = rt.clientId;
|
||||
newRt.scopes = rt.scopes;
|
||||
newRt.loginId = rt.loginId;
|
||||
@@ -150,5 +176,25 @@ public class SaOAuth2DataConverterDefaultImpl implements SaOAuth2DataConverter {
|
||||
return newRt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 SaClientModel 构建一个 ClientTokenModel
|
||||
* @param clientModel /
|
||||
* @param scopes 权限列表
|
||||
* @return /
|
||||
*/
|
||||
@Override
|
||||
public ClientTokenModel convertSaClientToClientToken(SaClientModel clientModel, List<String> scopes) {
|
||||
String clientTokenValue = SaOAuth2Strategy.instance.createClientToken.execute(clientModel.getClientId(), scopes);
|
||||
ClientTokenModel ct = new ClientTokenModel(clientTokenValue, clientModel.getClientId(), scopes);
|
||||
ct.clientToken = clientTokenValue;
|
||||
ct.clientId = clientModel.getClientId();
|
||||
ct.scopes = scopes;
|
||||
ct.tokenType = SaOAuth2Consts.TokenType.bearer;
|
||||
ct.expiresTime = ttlToExpireTime(clientModel.getClientTokenTimeout());
|
||||
ct.grantType = GrantType.client_credentials;
|
||||
ct.extraData = new LinkedHashMap<>();
|
||||
return ct;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+40
-75
@@ -16,7 +16,6 @@
|
||||
package cn.dev33.satoken.oauth2.data.generate;
|
||||
|
||||
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.dao.SaOAuth2Dao;
|
||||
import cn.dev33.satoken.oauth2.data.convert.SaOAuth2DataConverter;
|
||||
@@ -32,8 +31,8 @@ import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
|
||||
import cn.dev33.satoken.oauth2.exception.SaOAuth2RefreshTokenException;
|
||||
import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
import cn.dev33.satoken.util.SaTtlMethods;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -43,7 +42,7 @@ import java.util.function.Consumer;
|
||||
* @author click33
|
||||
* @since 1.39.0
|
||||
*/
|
||||
public class SaOAuth2DataGenerateDefaultImpl implements SaOAuth2DataGenerate {
|
||||
public class SaOAuth2DataGenerateDefaultImpl implements SaOAuth2DataGenerate, SaTtlMethods {
|
||||
|
||||
/**
|
||||
* 构建 Model:Code授权码
|
||||
@@ -59,14 +58,13 @@ public class SaOAuth2DataGenerateDefaultImpl implements SaOAuth2DataGenerate {
|
||||
dao.deleteCode(dao.getCodeValue(ra.clientId, ra.loginId));
|
||||
|
||||
// 生成新 Code
|
||||
String codeValue = SaOAuth2Strategy.instance.createCodeValue.execute(ra.clientId, ra.loginId, ra.scopes);
|
||||
CodeModel cm = new CodeModel(codeValue, ra.clientId, ra.scopes, ra.loginId, ra.redirectUri, ra.getNonce());
|
||||
CodeModel cm = SaOAuth2Manager.getDataConverter().convertRequestAuthToCode(ra);
|
||||
|
||||
// 保存新 Code
|
||||
dao.saveCode(cm);
|
||||
dao.saveCodeIndex(cm);
|
||||
|
||||
// 保存code-nonce
|
||||
// 保存 code -> nonce
|
||||
dao.saveCodeNonceIndex(cm);
|
||||
|
||||
// 返回
|
||||
@@ -91,25 +89,27 @@ public class SaOAuth2DataGenerateDefaultImpl implements SaOAuth2DataGenerate {
|
||||
// 2、开发者自定义的授权前置检查
|
||||
SaOAuth2Strategy.instance.userAuthorizeClientCheck.run(cm.loginId, cm.clientId);
|
||||
|
||||
// 3、生成token
|
||||
AccessTokenModel at = dataConverter.convertCodeToAccessToken(cm);
|
||||
// 3、生成新 Access-Token
|
||||
SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(cm.clientId);
|
||||
AccessTokenModel at = dataConverter.convertCodeToAccessToken(cm, clientModel.getAccessTokenTimeout());
|
||||
SaOAuth2Strategy.instance.workAccessTokenByScope.accept(at);
|
||||
RefreshTokenModel rt = dataConverter.convertAccessTokenToRefreshToken(at);
|
||||
|
||||
// 4、生成新 Refresh-Token
|
||||
RefreshTokenModel rt = dataConverter.convertAccessTokenToRefreshToken(at, clientModel.getRefreshTokenTimeout());
|
||||
at.refreshToken = rt.refreshToken;
|
||||
at.refreshExpiresTime = rt.expiresTime;
|
||||
|
||||
// 4、保存token
|
||||
SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(cm.clientId);
|
||||
// 5、保存 Access-Token、Refresh-Token
|
||||
dao.saveAccessToken(at);
|
||||
dao.saveAccessTokenIndex(at, clientModel.getMaxAccessTokenCount());
|
||||
dao.saveAccessTokenIndex_AndAdjust(at, clientModel.getMaxAccessTokenCount());
|
||||
dao.saveRefreshToken(rt);
|
||||
dao.saveRefreshTokenIndex(rt, clientModel.getMaxRefreshTokenCount());
|
||||
dao.saveRefreshTokenIndex_AndAdjust(rt, clientModel.getMaxRefreshTokenCount());
|
||||
|
||||
// 5、删除此Code
|
||||
// 6、删除 Code (一个 code 只可以使用一次)
|
||||
dao.deleteCode(code);
|
||||
dao.deleteCodeIndex(cm.clientId, cm.loginId);
|
||||
|
||||
// 6、返回 Access-Token
|
||||
// 7、返回 Access-Token
|
||||
return at;
|
||||
}
|
||||
|
||||
@@ -123,37 +123,30 @@ public class SaOAuth2DataGenerateDefaultImpl implements SaOAuth2DataGenerate {
|
||||
|
||||
SaOAuth2Dao dao = SaOAuth2Manager.getDao();
|
||||
|
||||
// 获取 Refresh-Token 信息
|
||||
// 1、获取 Refresh-Token 信息
|
||||
RefreshTokenModel rt = dao.getRefreshToken(refreshToken);
|
||||
SaOAuth2RefreshTokenException.throwBy(rt == null, "无效 refresh_token: " + refreshToken, refreshToken, SaOAuth2ErrorCode.CODE_30111);
|
||||
|
||||
// 开发者自定义的授权前置检查
|
||||
// 2、开发者自定义的授权前置检查
|
||||
SaOAuth2Strategy.instance.userAuthorizeClientCheck.run(rt.loginId, rt.clientId);
|
||||
|
||||
// 如果配置了 [每次刷新产生新的Refresh-Token]
|
||||
// 3、如果配置了 isNewRefresh=true,则生成一个新的 Refresh-Token
|
||||
SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(rt.clientId);
|
||||
if(clientModel.getIsNewRefresh()) {
|
||||
// 删除旧 Refresh-Token
|
||||
// dao.deleteRefreshToken(rt.refreshToken);
|
||||
|
||||
// 创建并保存新的 Refresh-Token
|
||||
rt = SaOAuth2Manager.getDataConverter().convertRefreshTokenToRefreshToken(rt);
|
||||
rt = SaOAuth2Manager.getDataConverter().convertRefreshTokenToRefreshToken(rt, clientModel.getRefreshTokenTimeout());
|
||||
dao.saveRefreshToken(rt);
|
||||
dao.saveRefreshTokenIndex(rt, clientModel.getMaxRefreshTokenCount());
|
||||
dao.saveRefreshTokenIndex_AndAdjust(rt, clientModel.getMaxRefreshTokenCount());
|
||||
}
|
||||
|
||||
// 删除旧 Access-Token
|
||||
// dao.deleteAccessToken(dao.getAccessTokenList(rt.clientId, rt.loginId));
|
||||
|
||||
// 生成新 Access-Token
|
||||
AccessTokenModel at = SaOAuth2Manager.getDataConverter().convertRefreshTokenToAccessToken(rt);
|
||||
// 4、生成新 Access-Token
|
||||
AccessTokenModel at = SaOAuth2Manager.getDataConverter().convertRefreshTokenToAccessToken(rt, clientModel.getAccessTokenTimeout());
|
||||
SaOAuth2Strategy.instance.refreshAccessTokenWorkByScope.accept(at);
|
||||
|
||||
// 保存新 Access-Token
|
||||
// 5、保存新 Access-Token
|
||||
dao.saveAccessToken(at);
|
||||
dao.saveAccessTokenIndex(at, clientModel.getMaxAccessTokenCount());
|
||||
dao.saveAccessTokenIndex_AndAdjust(at, clientModel.getMaxAccessTokenCount());
|
||||
|
||||
// 返回新 Access-Token
|
||||
// 6、返回新 Access-Token
|
||||
return at;
|
||||
}
|
||||
|
||||
@@ -169,46 +162,34 @@ public class SaOAuth2DataGenerateDefaultImpl implements SaOAuth2DataGenerate {
|
||||
public AccessTokenModel generateAccessToken(RequestAuthModel ra, boolean isCreateRt, Consumer<AccessTokenModel> appendWork) {
|
||||
|
||||
SaOAuth2Dao dao = SaOAuth2Manager.getDao();
|
||||
|
||||
// 1、删除 旧Token
|
||||
// dao.deleteAccessToken(dao.getAccessTokenList(ra.clientId, ra.loginId));
|
||||
// if(isCreateRt) {
|
||||
// dao.deleteRefreshToken(dao.getRefreshTokenValue(ra.clientId, ra.loginId));
|
||||
// }
|
||||
SaOAuth2DataConverter dataConverter = SaOAuth2Manager.getDataConverter();
|
||||
|
||||
// 1、开发者自定义的授权前置检查
|
||||
SaOAuth2Strategy.instance.userAuthorizeClientCheck.run(ra.loginId, ra.clientId);
|
||||
|
||||
// 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);
|
||||
at.tokenType = SaOAuth2Consts.TokenType.bearer;
|
||||
// 2、生成 Access-Token
|
||||
SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(ra.clientId);
|
||||
AccessTokenModel at = dataConverter.convertRequestAuthToAccessToken(ra, clientModel.getAccessTokenTimeout());
|
||||
if(appendWork != null) {
|
||||
appendWork.accept(at);
|
||||
}
|
||||
|
||||
// 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);
|
||||
RefreshTokenModel rt = dataConverter.convertAccessTokenToRefreshToken(at, clientModel.getRefreshTokenTimeout());
|
||||
at.refreshToken = rt.refreshToken;
|
||||
at.refreshExpiresTime = rt.expiresTime;
|
||||
|
||||
dao.saveRefreshToken(rt);
|
||||
dao.saveRefreshTokenIndex(rt, clientModel.getMaxRefreshTokenCount());
|
||||
dao.saveRefreshTokenIndex_AndAdjust(rt, clientModel.getMaxRefreshTokenCount());
|
||||
}
|
||||
|
||||
// 5、保存 新Access-Token
|
||||
// 4、保存 Access-Token
|
||||
dao.saveAccessToken(at);
|
||||
dao.saveAccessTokenIndex(at, clientModel.getMaxAccessTokenCount());
|
||||
dao.saveAccessTokenIndex_AndAdjust(at, clientModel.getMaxAccessTokenCount());
|
||||
|
||||
// 6、返回 新Access-Token
|
||||
// 5、返回 Access-Token
|
||||
return at;
|
||||
}
|
||||
|
||||
@@ -223,32 +204,16 @@ public class SaOAuth2DataGenerateDefaultImpl implements SaOAuth2DataGenerate {
|
||||
|
||||
SaOAuth2Dao dao = SaOAuth2Manager.getDao();
|
||||
|
||||
// 1、删掉旧 Lower-Client-Token
|
||||
// dao.deleteClientToken(dao.getLowerClientTokenValue(clientId));
|
||||
// 1、如果配置了 Lower-Client-Token 的 ttl ,则需要更新一下
|
||||
SaClientModel clientModel = SaOAuth2Manager.getDataLoader().getClientModelNotNull(clientId);
|
||||
|
||||
// 2、将旧Client-Token 标记为新 Lower-Client-Token
|
||||
// ClientTokenModel oldCt = dao.getClientToken(dao.getClientTokenValue(clientId));
|
||||
// dao.saveLowerClientTokenIndex(oldCt);
|
||||
|
||||
// 2.5、如果配置了 Lower-Client-Token 的 ttl ,则需要更新一下
|
||||
SaClientModel cm = SaOAuth2Manager.getDataLoader().getClientModelNotNull(clientId);
|
||||
// if(oldCt != null && cm.getLowerClientTokenTimeout() != -1) {
|
||||
// oldCt.expiresTime = System.currentTimeMillis() + (cm.getLowerClientTokenTimeout() * 1000);
|
||||
// dao.saveClientToken(oldCt);
|
||||
// }
|
||||
|
||||
// 3、生成新 Client-Token
|
||||
String clientTokenValue = SaOAuth2Strategy.instance.createClientToken.execute(clientId, scopes);
|
||||
ClientTokenModel ct = new ClientTokenModel(clientTokenValue, clientId, scopes);
|
||||
ct.tokenType = SaOAuth2Consts.TokenType.bearer;
|
||||
ct.expiresTime = System.currentTimeMillis() + (cm.getClientTokenTimeout() * 1000);
|
||||
ct.grantType = GrantType.client_credentials;
|
||||
ct.extraData = new LinkedHashMap<>();
|
||||
// 2、生成 Client-Token
|
||||
ClientTokenModel ct = SaOAuth2Manager.getDataConverter().convertSaClientToClientToken(clientModel, scopes);
|
||||
SaOAuth2Strategy.instance.workClientTokenByScope.accept(ct);
|
||||
|
||||
// 3、保存新Client-Token
|
||||
// 3、保存 Client-Token
|
||||
dao.saveClientToken(ct);
|
||||
dao.saveClientTokenIndex(ct, cm.getMaxClientTokenCount());
|
||||
dao.saveClientTokenIndex_AndAdjust(ct, clientModel.getMaxClientTokenCount());
|
||||
|
||||
// 4、返回
|
||||
return ct;
|
||||
|
||||
+22
-19
@@ -104,6 +104,28 @@ public class AccessTokenModel implements Serializable {
|
||||
this.scopes = scopes;
|
||||
}
|
||||
|
||||
// 额外追加方法
|
||||
|
||||
/**
|
||||
* 获取:此 Access-Token 的剩余有效期(秒)
|
||||
* @return /
|
||||
*/
|
||||
public long getExpiresIn() {
|
||||
long s = (expiresTime - System.currentTimeMillis()) / 1000;
|
||||
return s < 1 ? -2 : s;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取:此 Refresh-Token 的剩余有效期(秒)
|
||||
* @return /
|
||||
*/
|
||||
public long getRefreshExpiresIn() {
|
||||
long s = (refreshExpiresTime - System.currentTimeMillis()) / 1000;
|
||||
return s < 1 ? -2 : s;
|
||||
}
|
||||
|
||||
|
||||
// get set
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
@@ -221,24 +243,5 @@ public class AccessTokenModel implements Serializable {
|
||||
'}';
|
||||
}
|
||||
|
||||
// 追加只读属性
|
||||
|
||||
/**
|
||||
* 获取:此 Access-Token 的剩余有效期(秒)
|
||||
* @return /
|
||||
*/
|
||||
public long getExpiresIn() {
|
||||
long s = (expiresTime - System.currentTimeMillis()) / 1000;
|
||||
return s < 1 ? -2 : s;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取:此 Refresh-Token 的剩余有效期(秒)
|
||||
* @return /
|
||||
*/
|
||||
public long getRefreshExpiresIn() {
|
||||
long s = (refreshExpiresTime - System.currentTimeMillis()) / 1000;
|
||||
return s < 1 ? -2 : s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
-9
@@ -86,6 +86,20 @@ public class ClientTokenModel implements Serializable {
|
||||
this.scopes = scopes;
|
||||
}
|
||||
|
||||
// 额外追加方法
|
||||
|
||||
/**
|
||||
* 获取:此 Client-Token 的剩余有效期(秒)
|
||||
* @return /
|
||||
*/
|
||||
public long getExpiresIn() {
|
||||
long s = (expiresTime - System.currentTimeMillis()) / 1000;
|
||||
return s < 1 ? -2 : s;
|
||||
}
|
||||
|
||||
|
||||
// get set
|
||||
|
||||
public String getClientToken() {
|
||||
return clientToken;
|
||||
}
|
||||
@@ -172,13 +186,4 @@ public class ClientTokenModel implements Serializable {
|
||||
'}';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取:此 Client-Token 的剩余有效期(秒)
|
||||
* @return /
|
||||
*/
|
||||
public long getExpiresIn() {
|
||||
long s = (expiresTime - System.currentTimeMillis()) / 1000;
|
||||
return s < 1 ? -2 : s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
@@ -69,6 +69,7 @@ public class CodeModel implements Serializable {
|
||||
public CodeModel() {
|
||||
this.createTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建一个
|
||||
* @param code 授权码
|
||||
@@ -76,6 +77,7 @@ public class CodeModel implements Serializable {
|
||||
* @param scopes 请求授权范围
|
||||
* @param loginId 对应的账号id
|
||||
* @param redirectUri 重定向地址
|
||||
* @param nonce 随机数
|
||||
*/
|
||||
public CodeModel(String code, String clientId, List<String> scopes, Object loginId, String redirectUri, String nonce) {
|
||||
this();
|
||||
|
||||
+14
-9
@@ -69,6 +69,20 @@ public class RefreshTokenModel implements Serializable {
|
||||
}
|
||||
|
||||
|
||||
// 额外追加方法
|
||||
|
||||
/**
|
||||
* 获取:此 Refresh-Token 的剩余有效期(秒)
|
||||
* @return /
|
||||
*/
|
||||
public long getExpiresIn() {
|
||||
long s = (expiresTime - System.currentTimeMillis()) / 1000;
|
||||
return s < 1 ? -2 : s;
|
||||
}
|
||||
|
||||
|
||||
// get set
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
@@ -145,13 +159,4 @@ public class RefreshTokenModel implements Serializable {
|
||||
"]";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取:此 Refresh-Token 的剩余有效期(秒)
|
||||
* @return /
|
||||
*/
|
||||
public long getExpiresIn() {
|
||||
long s = (expiresTime - System.currentTimeMillis()) / 1000;
|
||||
return s < 1 ? -2 : s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-11
@@ -15,8 +15,7 @@
|
||||
*/
|
||||
package cn.dev33.satoken.oauth2.data.model.loader;
|
||||
|
||||
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
|
||||
import cn.dev33.satoken.oauth2.config.SaOAuth2ServerConfig;
|
||||
import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
@@ -92,15 +91,7 @@ public class SaClientModel implements Serializable {
|
||||
|
||||
|
||||
public SaClientModel() {
|
||||
SaOAuth2ServerConfig config = SaOAuth2Manager.getServerConfig();
|
||||
this.isNewRefresh = config.getIsNewRefresh();
|
||||
this.accessTokenTimeout = config.getAccessTokenTimeout();
|
||||
this.refreshTokenTimeout = config.getRefreshTokenTimeout();
|
||||
this.clientTokenTimeout = config.getClientTokenTimeout();
|
||||
this.lowerClientTokenTimeout = config.getLowerClientTokenTimeout();
|
||||
this.maxAccessTokenCount = config.getMaxAccessTokenCount();
|
||||
this.maxRefreshTokenCount = config.getMaxRefreshTokenCount();
|
||||
this.maxClientTokenCount = config.getMaxClientTokenCount();
|
||||
SaOAuth2Strategy.instance.setSaClientModelDefaultFields.run(this);
|
||||
}
|
||||
public SaClientModel(String clientId, String clientSecret, List<String> contractScopes, List<String> allowRedirectUris) {
|
||||
this();
|
||||
|
||||
+1
@@ -84,4 +84,5 @@ public class ClientIdAndSecretModel implements Serializable {
|
||||
", clientSecret='" + clientSecret + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
-4
@@ -15,13 +15,13 @@
|
||||
*/
|
||||
package cn.dev33.satoken.oauth2.data.model.request;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import cn.dev33.satoken.oauth2.error.SaOAuth2ErrorCode;
|
||||
import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 请求授权参数的 Model
|
||||
*
|
||||
@@ -181,7 +181,7 @@ public class RequestAuthModel implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查此Model参数是否有效
|
||||
* 数据自检
|
||||
* @return 对象自身
|
||||
*/
|
||||
public RequestAuthModel checkModel() {
|
||||
@@ -200,5 +200,17 @@ public class RequestAuthModel implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RequestAuthModel{" +
|
||||
"clientId='" + clientId + '\'' +
|
||||
", scopes=" + scopes +
|
||||
", loginId=" + loginId +
|
||||
", redirectUri='" + redirectUri + '\'' +
|
||||
", responseType='" + responseType + '\'' +
|
||||
", state='" + state + '\'' +
|
||||
", nonce='" + nonce + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-1
@@ -66,7 +66,6 @@ public interface SaOAuth2DataResolver {
|
||||
*/
|
||||
RequestAuthModel readRequestAuthModel(SaRequest req, Object loginId);
|
||||
|
||||
|
||||
/**
|
||||
* 构建返回值: 获取 token
|
||||
* @param at token信息
|
||||
|
||||
+3
-3
@@ -77,7 +77,7 @@ public class SaOAuth2DataResolverDefaultImpl implements SaOAuth2DataResolver {
|
||||
*/
|
||||
@Override
|
||||
public String readAccessToken(SaRequest request) {
|
||||
// 优先从请求参数中获取
|
||||
// 优先从请求参数中获取,可以读取到的话直接返回
|
||||
String accessToken = request.getParam(Param.access_token);
|
||||
if(SaFoxUtil.isNotEmpty(accessToken)) {
|
||||
return accessToken;
|
||||
@@ -104,7 +104,7 @@ public class SaOAuth2DataResolverDefaultImpl implements SaOAuth2DataResolver {
|
||||
*/
|
||||
@Override
|
||||
public String readClientToken(SaRequest request) {
|
||||
// 优先从请求参数中获取
|
||||
// 优先从请求参数中获取,可以读取到的话直接返回
|
||||
String clientToken = request.getParam(Param.client_token);
|
||||
if(SaFoxUtil.isNotEmpty(clientToken)) {
|
||||
return clientToken;
|
||||
@@ -172,7 +172,7 @@ public class SaOAuth2DataResolverDefaultImpl implements SaOAuth2DataResolver {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("token_type", ct.tokenType);
|
||||
map.put("client_token", ct.clientToken);
|
||||
if(SaOAuth2Manager.getServerConfig().mode4ReturnAccessToken) {
|
||||
if(SaOAuth2Manager.getServerConfig().getMode4ReturnAccessToken()) {
|
||||
map.put("access_token", ct.clientToken);
|
||||
}
|
||||
map.put("expires_in", ct.getExpiresIn());
|
||||
|
||||
+2
-5
@@ -17,8 +17,8 @@ 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.consts.SaOAuth2Consts;
|
||||
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.request.ClientIdAndSecretModel;
|
||||
|
||||
@@ -39,9 +39,7 @@ public class AuthorizationCodeGrantTypeHandler implements SaOAuth2GrantTypeHandl
|
||||
|
||||
@Override
|
||||
public AccessTokenModel getAccessToken(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);
|
||||
@@ -50,8 +48,7 @@ public class AuthorizationCodeGrantTypeHandler implements SaOAuth2GrantTypeHandl
|
||||
SaOAuth2Manager.getTemplate().checkGainTokenParam(code, clientId, clientSecret, redirectUri);
|
||||
|
||||
// 构建 Access-Token、返回
|
||||
AccessTokenModel accessTokenModel = SaOAuth2Manager.getDataGenerate().generateAccessToken(code);
|
||||
return accessTokenModel;
|
||||
return SaOAuth2Manager.getDataGenerate().generateAccessToken(code);
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -49,20 +49,20 @@ public class PasswordGrantTypeHandler implements SaOAuth2GrantTypeHandlerInterfa
|
||||
String username = req.getParamNotNull(SaOAuth2Consts.Param.username);
|
||||
String password = req.getParamNotNull(SaOAuth2Consts.Param.password);
|
||||
|
||||
// 3、调用API 开始登录,如果没能成功登录,则直接退出
|
||||
// 2、调用API 开始登录,如果没能成功登录,则直接退出
|
||||
PasswordAuthResult passwordAuthResult = loginByUsernamePassword(username, password);
|
||||
Object loginId = passwordAuthResult.getLoginId();
|
||||
if(loginId == null) {
|
||||
throw new SaOAuth2Exception("登录失败").setCode(SaOAuth2ErrorCode.CODE_30161);
|
||||
}
|
||||
|
||||
// 4、构建 ra 对象
|
||||
// 3、构建 ra 对象
|
||||
RequestAuthModel ra = new RequestAuthModel();
|
||||
ra.clientId = clientId;
|
||||
ra.loginId = loginId;
|
||||
ra.scopes = scopes;
|
||||
|
||||
// 5、生成 Access-Token
|
||||
// 4、生成 Access-Token
|
||||
AccessTokenModel at = SaOAuth2Manager.getDataGenerate().generateAccessToken(ra, true, atm -> atm.grantType = GrantType.password);
|
||||
return at;
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 所有 OAuth2 GrantType 处理器的父接口
|
||||
* 所有 OAuth2 GrantType 处理器的父接口,如果要自定义 GrantType 处理器,必须实现此接口
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.39.0
|
||||
|
||||
+6
-4
@@ -182,8 +182,12 @@ public class SaOAuth2ServerProcessor {
|
||||
*/
|
||||
public Object refresh() {
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
|
||||
// 校验 grant_type 必须为 refresh_token
|
||||
String grantType = req.getParamNotNull(Param.grant_type);
|
||||
SaOAuth2Exception.throwBy(!grantType.equals(GrantType.refresh_token), "无效 grant_type:" + grantType, SaOAuth2ErrorCode.CODE_30126);
|
||||
|
||||
// 刷新 Access-Token
|
||||
AccessTokenModel accessTokenModel = SaOAuth2Strategy.instance.grantTypeAuth.apply(req);
|
||||
return SaOAuth2Manager.getDataResolver().buildRefreshTokenReturnValue(accessTokenModel);
|
||||
}
|
||||
@@ -223,9 +227,7 @@ public class SaOAuth2ServerProcessor {
|
||||
* @return 处理结果
|
||||
*/
|
||||
public Object doLogin() {
|
||||
// 获取变量
|
||||
SaRequest req = SaHolder.getRequest();
|
||||
|
||||
return SaOAuth2Strategy.instance.doLoginHandle.apply(req.getParam(Param.name), req.getParam(Param.pwd));
|
||||
}
|
||||
|
||||
@@ -262,10 +264,10 @@ public class SaOAuth2ServerProcessor {
|
||||
|
||||
// -------- 情况2:需要返回最终的 redirect_uri 地址
|
||||
|
||||
// s3、构建请求 Model
|
||||
// 构建请求 Model
|
||||
RequestAuthModel ra = SaOAuth2Manager.getDataResolver().readRequestAuthModel(req, loginId);
|
||||
|
||||
// 7、判断授权类型,构建不同的重定向地址
|
||||
// 判断授权类型,构建不同的重定向地址
|
||||
// 如果是 授权码式,则:开始重定向授权,下放code
|
||||
if(ResponseType.code.equals(ra.responseType)) {
|
||||
CodeModel codeModel = dataGenerate.generateCode(ra);
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
package cn.dev33.satoken.oauth2.scope;
|
||||
|
||||
/**
|
||||
* OAuth2 常见权限定义
|
||||
* OAuth2 常见 Scope 定义
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.39.0
|
||||
|
||||
+1
-1
@@ -136,7 +136,7 @@ public class OidcScopeHandler implements SaOAuth2ScopeHandlerInterface {
|
||||
* @return /
|
||||
*/
|
||||
public IdTokenModel workExtraData(IdTokenModel idToken) {
|
||||
//
|
||||
// 留给开发者扩展
|
||||
return idToken;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.ClientTokenModel;
|
||||
|
||||
/**
|
||||
* 所有 OAuth2 权限处理器的父接口
|
||||
* 所有 OAuth2 权限处理器的父接口,如果要自定义 Scope 处理器,必须实现此接口
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.39.0
|
||||
|
||||
+24
-7
@@ -16,6 +16,7 @@
|
||||
package cn.dev33.satoken.oauth2.strategy;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.fun.SaParamFunction;
|
||||
import cn.dev33.satoken.fun.SaTwoParamFunction;
|
||||
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
|
||||
import cn.dev33.satoken.oauth2.config.SaOAuth2ServerConfig;
|
||||
@@ -64,12 +65,12 @@ public final class SaOAuth2Strategy {
|
||||
// ------------------ 权限处理器 ------------------
|
||||
|
||||
/**
|
||||
* 权限处理器集合
|
||||
* Scope 权限处理器集合
|
||||
*/
|
||||
public Map<String, SaOAuth2ScopeHandlerInterface> scopeHandlerMap = new LinkedHashMap<>();
|
||||
|
||||
/**
|
||||
* 注册所有默认的权限处理器
|
||||
* 注册所有默认的 Scope 权限处理器
|
||||
*/
|
||||
public void registerDefaultScopeHandler() {
|
||||
scopeHandlerMap.put(CommonScope.OPENID, new OpenIdScopeHandler());
|
||||
@@ -156,7 +157,7 @@ public final class SaOAuth2Strategy {
|
||||
public Map<String, SaOAuth2GrantTypeHandlerInterface> grantTypeHandlerMap = new LinkedHashMap<>();
|
||||
|
||||
/**
|
||||
* 注册所有默认的权限处理器
|
||||
* 注册所有默认的 grant_type 处理器
|
||||
*/
|
||||
public void registerDefaultGrantTypeHandler() {
|
||||
grantTypeHandlerMap.put(GrantType.authorization_code, new AuthorizationCodeGrantTypeHandler());
|
||||
@@ -165,7 +166,7 @@ public final class SaOAuth2Strategy {
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册一个权限处理器
|
||||
* 注册一个 grant_type 处理器
|
||||
*/
|
||||
public void registerGrantTypeHandler(SaOAuth2GrantTypeHandlerInterface handler) {
|
||||
grantTypeHandlerMap.put(handler.getHandlerGrantType(), handler);
|
||||
@@ -173,7 +174,7 @@ public final class SaOAuth2Strategy {
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除一个权限处理器
|
||||
* 移除一个 grant_type 处理器
|
||||
*/
|
||||
public void removeGrantTypeHandler(String scope) {
|
||||
scopeHandlerMap.remove(scope);
|
||||
@@ -183,13 +184,14 @@ public final class SaOAuth2Strategy {
|
||||
* 根据 grantType 构造一个 AccessTokenModel
|
||||
*/
|
||||
public SaOAuth2GrantTypeAuthFunction grantTypeAuth = (req) -> {
|
||||
// 先校验提供的 grant_type 是否有效
|
||||
String grantType = req.getParamNotNull(SaOAuth2Consts.Param.grant_type);
|
||||
SaOAuth2GrantTypeHandlerInterface grantTypeHandler = grantTypeHandlerMap.get(grantType);
|
||||
if(grantTypeHandler == null) {
|
||||
throw new SaOAuth2Exception("无效 grant_type: " + grantType).setCode(SaOAuth2ErrorCode.CODE_30126);
|
||||
}
|
||||
|
||||
// 看看全局是否开启了此 grantType
|
||||
// 针对 authorization_code 与 password 两种特殊 grant_type,需要判断全局是否开启
|
||||
SaOAuth2ServerConfig config = SaOAuth2Manager.getServerConfig();
|
||||
if(grantType.equals(GrantType.authorization_code) && !config.getEnableAuthorizationCode() ) {
|
||||
throw new SaOAuth2Exception("系统未开放的 grant_type: " + grantType).setCode(SaOAuth2ErrorCode.CODE_30126);
|
||||
@@ -208,7 +210,7 @@ public final class SaOAuth2Strategy {
|
||||
throw new SaOAuth2Exception("应用未开放的 grant_type: " + grantType).setCode(SaOAuth2ErrorCode.CODE_30141);
|
||||
}
|
||||
|
||||
// 调用 处理器
|
||||
// 调用 处理器构建 Access-Token
|
||||
return grantTypeHandler.getAccessToken(req, clientIdAndSecretModel.getClientId(), scopes);
|
||||
};
|
||||
|
||||
@@ -269,5 +271,20 @@ public final class SaOAuth2Strategy {
|
||||
};
|
||||
|
||||
|
||||
// ------------------ 其它 ------------------
|
||||
|
||||
/**
|
||||
* 在创建 SaClientModel 时,设置其默认字段
|
||||
*/
|
||||
public SaParamFunction<SaClientModel> setSaClientModelDefaultFields = (clientModel) -> {
|
||||
SaOAuth2ServerConfig config = SaOAuth2Manager.getServerConfig();
|
||||
clientModel.accessTokenTimeout = config.getAccessTokenTimeout();
|
||||
clientModel.refreshTokenTimeout = config.getRefreshTokenTimeout();
|
||||
clientModel.clientTokenTimeout = config.getClientTokenTimeout();
|
||||
clientModel.maxAccessTokenCount = config.getMaxAccessTokenCount();
|
||||
clientModel.maxRefreshTokenCount = config.getMaxRefreshTokenCount();
|
||||
clientModel.maxClientTokenCount = config.getMaxClientTokenCount();
|
||||
clientModel.isNewRefresh = config.getIsNewRefresh();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+17
-8
@@ -37,7 +37,7 @@ import java.util.List;
|
||||
*/
|
||||
public class SaOAuth2Template {
|
||||
|
||||
// ----------------- ClientModel 相关 -----------------
|
||||
// ----------------- SaClientModel 相关 -----------------
|
||||
|
||||
/**
|
||||
* 获取 ClientModel,根据 clientId
|
||||
@@ -65,7 +65,7 @@ public class SaOAuth2Template {
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验:clientId 与 clientSecret 是否正确
|
||||
* 校验:clientId 与 clientSecret 是否正确,正确返回 SaClientModel,不正确抛出异常
|
||||
* @param clientId 应用id
|
||||
* @param clientSecret 秘钥
|
||||
* @return SaClientModel对象
|
||||
@@ -287,6 +287,15 @@ public class SaOAuth2Template {
|
||||
return !isGrantScope(loginId, clientId, scopes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除:指定 loginId 针对指定 Client 的授权信息
|
||||
* @param loginId 账号id
|
||||
* @param clientId 应用id
|
||||
*/
|
||||
public void deleteGrantScope(Object loginId, String clientId) {
|
||||
SaOAuth2Manager.getDao().deleteGrantScope(clientId, loginId);
|
||||
}
|
||||
|
||||
|
||||
// --------- 请求数据校验相关
|
||||
|
||||
@@ -435,7 +444,7 @@ public class SaOAuth2Template {
|
||||
* @return /
|
||||
*/
|
||||
public List<String> getAccessTokenValueList(String clientId, Object loginId) {
|
||||
return SaOAuth2Manager.getDao().getAccessTokenValueList(clientId, loginId);
|
||||
return SaOAuth2Manager.getDao().getAccessTokenValueList_FromAdjustAfter(clientId, loginId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -503,7 +512,7 @@ public class SaOAuth2Template {
|
||||
// 删 at、索引
|
||||
SaOAuth2Dao dao = SaOAuth2Manager.getDao();
|
||||
dao.deleteAccessToken(accessToken);
|
||||
dao.deleteAccessTokenIndexBySingleData(at.clientId, at.loginId, accessToken);
|
||||
dao.deleteAccessTokenIndex_BySingleData(at.clientId, at.loginId, accessToken);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -560,7 +569,7 @@ public class SaOAuth2Template {
|
||||
* @return /
|
||||
*/
|
||||
public List<String> getRefreshTokenValueList(String clientId, Object loginId) {
|
||||
return SaOAuth2Manager.getDao().getRefreshTokenValueList(clientId, loginId);
|
||||
return SaOAuth2Manager.getDao().getRefreshTokenValueList_FromAdjustAfter(clientId, loginId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -577,7 +586,7 @@ public class SaOAuth2Template {
|
||||
// 删 rt、索引
|
||||
SaOAuth2Dao dao = SaOAuth2Manager.getDao();
|
||||
dao.deleteRefreshToken(refreshToken);
|
||||
dao.deleteRefreshTokenIndexBySingleData(rt.clientId, rt.loginId, refreshToken);
|
||||
dao.deleteRefreshTokenIndex_BySingleData(rt.clientId, rt.loginId, refreshToken);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -643,7 +652,7 @@ public class SaOAuth2Template {
|
||||
* @return /
|
||||
*/
|
||||
public List<String> getClientTokenValueList(String clientId) {
|
||||
return SaOAuth2Manager.getDao().getClientTokenValueList(clientId);
|
||||
return SaOAuth2Manager.getDao().getClientTokenValueList_FromAdjustAfter(clientId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -693,7 +702,7 @@ public class SaOAuth2Template {
|
||||
// 删 ct、删索引
|
||||
SaOAuth2Dao dao = SaOAuth2Manager.getDao();
|
||||
dao.deleteClientToken(clientToken);
|
||||
dao.deleteClientTokenIndexBySingleData(ct.clientId, clientToken);
|
||||
dao.deleteClientTokenIndex_BySingleData(ct.clientId, clientToken);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+9
@@ -128,6 +128,15 @@ public class SaOAuth2Util {
|
||||
return SaOAuth2Manager.getTemplate().isGrantScope(loginId, clientId, scopes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除:指定 loginId 针对指定 Client 的授权信息
|
||||
* @param loginId 账号id
|
||||
* @param clientId 应用id
|
||||
*/
|
||||
public static void deleteGrantScope(Object loginId, String clientId) {
|
||||
SaOAuth2Manager.getTemplate().deleteGrantScope(loginId, clientId);
|
||||
}
|
||||
|
||||
|
||||
// ----------------- Code 相关 -----------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user