使OAuth2模块部分属性支持每个Client单独配置

This commit is contained in:
click33 2022-02-07 19:36:31 +08:00
parent 9e47461a0a
commit 0d4830eb7d
4 changed files with 143 additions and 23 deletions

View File

@ -42,7 +42,7 @@ public class SaOAuth2Config implements Serializable {
/** Client-Token 保存的时间(单位:秒) 默认两个小时 */
public long clientTokenTimeout = 60 * 60 * 2;
/** Past-Client-Token 保存的时间(单位:秒) 默认為 null */
/** Past-Client-Token 保存的时间(单位:秒) 默认为 null代表取 clientTokenTimeout 值 */
public Long pastClientTokenTimeout = null;

View File

@ -88,7 +88,6 @@ public class SaOAuth2Handle {
return password(req, res, cfg);
}
throw new SaOAuth2Exception("暂未开放的授权模式");
}
// 模式四凭证式

View File

@ -181,9 +181,9 @@ public class SaOAuth2Template {
// 获取 Refresh-Token 信息
RefreshTokenModel rt = getRefreshToken(refreshToken);
SaOAuth2Exception.throwBy(rt == null, "无效refresh_token: " + refreshToken);
// 如果配置了[每次刷新产生新的Refresh-Token]
if(SaOAuth2Manager.getConfig().getIsNewRefresh()) {
if(checkClientModel(rt.clientId).getIsNewRefresh()) {
// 删除旧 Refresh-Token
deleteRefreshToken(rt.refreshToken);
@ -224,7 +224,7 @@ public class SaOAuth2Template {
String newAtValue = randomAccessToken(ra.clientId, ra.loginId, ra.scope);
AccessTokenModel at = new AccessTokenModel(newAtValue, ra.clientId, ra.loginId, ra.scope);
at.openid = getOpenid(ra.clientId, ra.loginId);
at.expiresTime = System.currentTimeMillis() + (SaOAuth2Manager.getConfig().getAccessTokenTimeout() * 1000);
at.expiresTime = System.currentTimeMillis() + (checkClientModel(ra.clientId).getAccessTokenTimeout() * 1000);
// 3生成&保存 Refresh-Token
if(isCreateRt) {
@ -247,18 +247,25 @@ public class SaOAuth2Template {
* @return Client-Token Model
*/
public ClientTokenModel generateClientToken(String clientId, String scope) {
// 1删掉 Past-Token
// 1删掉 Past-Token
deleteClientToken(getPastTokenValue(clientId));
// 2将Client-Token 标记 Past-Token
String ctValue = getClientTokenValue(clientId);
savePastTokenIndex(getClientToken(ctValue));
// 2将旧Client-Token 标记为新 Past-Token
ClientTokenModel oldCt = getClientToken(getClientTokenValue(clientId));
savePastTokenIndex(oldCt);
// 2.5如果配置了 PastClientToken ttl 则需要更新一下
SaClientModel cm = checkClientModel(clientId);
if(oldCt != null && cm.getPastClientTokenTimeout() != null) {
oldCt.expiresTime = System.currentTimeMillis() + (cm.getPastClientTokenTimeout() * 1000);
saveClientToken(oldCt);
}
// 3生成新Token
// 3生成新Client-Token
ClientTokenModel ct = new ClientTokenModel(randomClientToken(clientId, scope), clientId, scope);
ct.expiresTime = System.currentTimeMillis() + (SaOAuth2Manager.getConfig().getClientTokenTimeout() * 1000);
ct.expiresTime = System.currentTimeMillis() + (cm.getClientTokenTimeout() * 1000);
// 3保存新Token
// 3保存新Client-Token
saveClientToken(ct);
saveClientTokenIndex(ct);
@ -454,8 +461,8 @@ public class SaOAuth2Template {
at.loginId = cm.loginId;
at.scope = cm.scope;
at.openid = getOpenid(cm.clientId, cm.loginId);
at.expiresTime = System.currentTimeMillis() + (SaOAuth2Manager.getConfig().getAccessTokenTimeout() * 1000);
// at.refreshExpiresTime = System.currentTimeMillis() + (SaOAuth2Manager.getConfig().getRefreshTokenTimeout() * 1000);
at.expiresTime = System.currentTimeMillis() + (checkClientModel(cm.clientId).getAccessTokenTimeout() * 1000);
// at.refreshExpiresTime = System.currentTimeMillis() + (checkClientModel(cm.clientId).getRefreshTokenTimeout() * 1000);
return at;
}
/**
@ -470,7 +477,7 @@ public class SaOAuth2Template {
rt.loginId = at.loginId;
rt.scope = at.scope;
rt.openid = at.openid;
rt.expiresTime = System.currentTimeMillis() + (SaOAuth2Manager.getConfig().getRefreshTokenTimeout() * 1000);
rt.expiresTime = System.currentTimeMillis() + (checkClientModel(at.clientId).getRefreshTokenTimeout() * 1000);
// 改变at属性
at.refreshToken = rt.refreshToken;
at.refreshExpiresTime = rt.expiresTime;
@ -489,7 +496,7 @@ public class SaOAuth2Template {
at.loginId = rt.loginId;
at.scope = rt.scope;
at.openid = rt.openid;
at.expiresTime = System.currentTimeMillis() + (SaOAuth2Manager.getConfig().getAccessTokenTimeout() * 1000);
at.expiresTime = System.currentTimeMillis() + (checkClientModel(rt.clientId).getAccessTokenTimeout() * 1000);
at.refreshExpiresTime = rt.expiresTime;
return at;
}
@ -501,7 +508,7 @@ public class SaOAuth2Template {
public RefreshTokenModel convertRefreshTokenToRefreshToken(RefreshTokenModel rt) {
RefreshTokenModel newRt = new RefreshTokenModel();
newRt.refreshToken = randomRefreshToken(rt.clientId, rt.loginId, rt.scope);
newRt.expiresTime = System.currentTimeMillis() + (SaOAuth2Manager.getConfig().getRefreshTokenTimeout() * 1000);
newRt.expiresTime = System.currentTimeMillis() + (checkClientModel(rt.clientId).getRefreshTokenTimeout() * 1000);
newRt.clientId = rt.clientId;
newRt.scope = rt.scope;
newRt.loginId = rt.loginId;
@ -599,8 +606,9 @@ public class SaOAuth2Template {
return;
}
Long ttl = ct.getExpiresIn();
if (null != SaOAuth2Manager.getConfig().getPastClientTokenTimeout()) {
ttl = SaOAuth2Manager.getConfig().getPastClientTokenTimeout();
SaClientModel cm = checkClientModel(ct.clientId);
if (null != cm.getPastClientTokenTimeout()) {
ttl = cm.getPastClientTokenTimeout();
}
SaManager.getSaTokenDao().set(splicingPastTokenIndexKey(ct.clientId), ct.clientToken, ttl);
}
@ -612,7 +620,7 @@ public class SaOAuth2Template {
*/
public void saveGrantScope(String clientId, Object loginId, String scope) {
if(SaFoxUtil.isEmpty(scope) == false) {
long ttl = SaOAuth2Manager.getConfig().getAccessTokenTimeout();
long ttl = checkClientModel(clientId).getAccessTokenTimeout();
SaManager.getSaTokenDao().set(splicingGrantScopeKey(clientId, loginId), scope, ttl);
}
}

View File

@ -2,6 +2,9 @@ package cn.dev33.satoken.oauth2.model;
import java.io.Serializable;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
/**
* Client应用信息 Model
* @author kong
@ -43,11 +46,36 @@ public class SaClientModel implements Serializable {
/** 此 Client 是否打开模式凭证式Client Credentials */
public Boolean isClient = false;
/** 是否自动判断开放的授权模式此值为true时单独设置isCode、isImplicit、isPassword、isClient不再有效而是跟随全局设置 */
/**
* 是否自动判断开放的授权模式
* <br> 此值为true时四种模式isCodeisImplicitisPasswordisClient是否生效依靠全局设置
* <br> 此值为false时四种模式isCodeisImplicitisPasswordisClient是否生效依靠局部配置+全局配置
*/
public Boolean isAutoMode = false;
/** 单独配置此Client是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token [默认取全局配置] */
public Boolean isNewRefresh;
/** 单独配置此ClientAccess-Token 保存的时间(单位秒) [默认取全局配置] */
public long accessTokenTimeout;
/** 单独配置此ClientRefresh-Token 保存的时间(单位秒) [默认取全局配置] */
public long refreshTokenTimeout;
/** 单独配置此ClientClient-Token 保存的时间(单位秒) [默认取全局配置] */
public long clientTokenTimeout;
/** 单独配置此ClientPast-Client-Token 保存的时间(单位:秒) [默认取全局配置] */
public Long pastClientTokenTimeout;
public SaClientModel() {
SaOAuth2Config config = SaOAuth2Manager.getConfig();
this.isNewRefresh = config.getIsNewRefresh();
this.accessTokenTimeout = config.getAccessTokenTimeout();
this.refreshTokenTimeout = config.getRefreshTokenTimeout();
this.clientTokenTimeout = config.getClientTokenTimeout();
this.pastClientTokenTimeout = config.getPastClientTokenTimeout();
}
public SaClientModel(String clientId, String clientSecret, String contractScope, String allowUrl) {
super();
@ -202,12 +230,97 @@ public class SaClientModel implements Serializable {
return this;
}
/**
* @return 此Client是否在每次 Refresh-Token 刷新 Access-Token 产生一个新的 Refresh-Token [默认取全局配置]
*/
public Boolean getIsNewRefresh() {
return isNewRefresh;
}
/**
* @param isNewRefresh 单独配置此Client是否在每次 Refresh-Token 刷新 Access-Token 产生一个新的 Refresh-Token [默认取全局配置]
* @return 对象自身
*/
public SaClientModel setIsNewRefresh(Boolean isNewRefresh) {
this.isNewRefresh = isNewRefresh;
return this;
}
/**
* @return 此ClientAccess-Token 保存的时间(单位秒) [默认取全局配置]
*/
public long getAccessTokenTimeout() {
return accessTokenTimeout;
}
/**
* @param accessTokenTimeout 单独配置此ClientAccess-Token 保存的时间(单位秒) [默认取全局配置]
* @return 对象自身
*/
public SaClientModel setAccessTokenTimeout(long accessTokenTimeout) {
this.accessTokenTimeout = accessTokenTimeout;
return this;
}
/**
* @return 此ClientRefresh-Token 保存的时间(单位秒) [默认取全局配置]
*/
public long getRefreshTokenTimeout() {
return refreshTokenTimeout;
}
/**
* @param refreshTokenTimeout 单独配置此ClientRefresh-Token 保存的时间(单位秒) [默认取全局配置]
* @return 对象自身
*/
public SaClientModel setRefreshTokenTimeout(long refreshTokenTimeout) {
this.refreshTokenTimeout = refreshTokenTimeout;
return this;
}
/**
* @return 此ClientClient-Token 保存的时间(单位秒) [默认取全局配置]
*/
public long getClientTokenTimeout() {
return clientTokenTimeout;
}
/**
* @param clientTokenTimeout 单独配置此ClientClient-Token 保存的时间(单位秒) [默认取全局配置]
* @return 对象自身
*/
public SaClientModel setClientTokenTimeout(long clientTokenTimeout) {
this.clientTokenTimeout = clientTokenTimeout;
return this;
}
/**
* @return 此ClientPast-Client-Token 保存的时间(单位) [默认取全局配置]
*/
public Long getPastClientTokenTimeout() {
return pastClientTokenTimeout;
}
/**
* @param pastClientTokenTimeout 单独配置此ClientPast-Client-Token 保存的时间(单位) [默认取全局配置]
* @return 对象自身
*/
public SaClientModel setPastClientTokenTimeout(Long pastClientTokenTimeout) {
this.pastClientTokenTimeout = pastClientTokenTimeout;
return this;
}
//
@Override
public String toString() {
return "SaClientModel [clientId=" + clientId + ", clientSecret=" + clientSecret + ", contractScope="
+ contractScope + ", allowUrl=" + allowUrl + ", isCode=" + isCode + ", isImplicit=" + isImplicit
+ ", isPassword=" + isPassword + ", isClient=" + isClient + ", isAutoMode=" + isAutoMode + "]";
+ ", isPassword=" + isPassword + ", isClient=" + isClient + ", isAutoMode=" + isAutoMode
+ ", isNewRefresh=" + isNewRefresh + ", accessTokenTimeout=" + accessTokenTimeout
+ ", refreshTokenTimeout=" + refreshTokenTimeout + ", clientTokenTimeout=" + clientTokenTimeout
+ ", pastClientTokenTimeout=" + pastClientTokenTimeout + "]";
}
}