From 0d4830eb7d502809ebfb4c6fd877d1a81464da55 Mon Sep 17 00:00:00 2001 From: click33 <2393584716@qq.com> Date: Mon, 7 Feb 2022 19:36:31 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BD=BFOAuth2=E6=A8=A1=E5=9D=97=E9=83=A8?= =?UTF-8?q?=E5=88=86=E5=B1=9E=E6=80=A7=E6=94=AF=E6=8C=81=E6=AF=8F=E4=B8=AA?= =?UTF-8?q?Client=E5=8D=95=E7=8B=AC=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../satoken/oauth2/config/SaOAuth2Config.java | 2 +- .../satoken/oauth2/logic/SaOAuth2Handle.java | 1 - .../oauth2/logic/SaOAuth2Template.java | 44 ++++--- .../satoken/oauth2/model/SaClientModel.java | 119 +++++++++++++++++- 4 files changed, 143 insertions(+), 23 deletions(-) diff --git a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/config/SaOAuth2Config.java b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/config/SaOAuth2Config.java index 6f505bc8..62d3be66 100644 --- a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/config/SaOAuth2Config.java +++ b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/config/SaOAuth2Config.java @@ -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; diff --git a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Handle.java b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Handle.java index 7aefc0fd..e1a9684a 100644 --- a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Handle.java +++ b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Handle.java @@ -88,7 +88,6 @@ public class SaOAuth2Handle { return password(req, res, cfg); } throw new SaOAuth2Exception("暂未开放的授权模式"); - } // 模式四:凭证式 diff --git a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Template.java b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Template.java index c3ec9900..c5b9a316 100644 --- a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Template.java +++ b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Template.java @@ -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); } } diff --git a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/model/SaClientModel.java b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/model/SaClientModel.java index 8c6fd31c..ea0ff687 100644 --- a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/model/SaClientModel.java +++ b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/model/SaClientModel.java @@ -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)不再有效,而是跟随全局设置 */ + /** + * 是否自动判断开放的授权模式 + *
此值为true时:四种模式(isCode、isImplicit、isPassword、isClient)是否生效,依靠全局设置 + *
此值为false时:四种模式(isCode、isImplicit、isPassword、isClient)是否生效,依靠局部配置+全局配置 + */ public Boolean isAutoMode = false; + /** 单独配置此Client:是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token [默认取全局配置] */ + public Boolean isNewRefresh; + + /** 单独配置此Client:Access-Token 保存的时间(单位秒) [默认取全局配置] */ + public long accessTokenTimeout; + + /** 单独配置此Client:Refresh-Token 保存的时间(单位秒) [默认取全局配置] */ + public long refreshTokenTimeout; + + /** 单独配置此Client:Client-Token 保存的时间(单位秒) [默认取全局配置] */ + public long clientTokenTimeout; + + /** 单独配置此Client:Past-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 此Client:Access-Token 保存的时间(单位秒) [默认取全局配置] + */ + public long getAccessTokenTimeout() { + return accessTokenTimeout; + } + + /** + * @param accessTokenTimeout 单独配置此Client:Access-Token 保存的时间(单位秒) [默认取全局配置] + * @return 对象自身 + */ + public SaClientModel setAccessTokenTimeout(long accessTokenTimeout) { + this.accessTokenTimeout = accessTokenTimeout; + return this; + } + + /** + * @return 此Client:Refresh-Token 保存的时间(单位秒) [默认取全局配置] + */ + public long getRefreshTokenTimeout() { + return refreshTokenTimeout; + } + + /** + * @param refreshTokenTimeout 单独配置此Client:Refresh-Token 保存的时间(单位秒) [默认取全局配置] + * @return 对象自身 + */ + public SaClientModel setRefreshTokenTimeout(long refreshTokenTimeout) { + this.refreshTokenTimeout = refreshTokenTimeout; + return this; + } + + /** + * @return 此Client:Client-Token 保存的时间(单位秒) [默认取全局配置] + */ + public long getClientTokenTimeout() { + return clientTokenTimeout; + } + + /** + * @param clientTokenTimeout 单独配置此Client:Client-Token 保存的时间(单位秒) [默认取全局配置] + * @return 对象自身 + */ + public SaClientModel setClientTokenTimeout(long clientTokenTimeout) { + this.clientTokenTimeout = clientTokenTimeout; + return this; + } + + /** + * @return 此Client:Past-Client-Token 保存的时间(单位:秒) [默认取全局配置] + */ + public Long getPastClientTokenTimeout() { + return pastClientTokenTimeout; + } + + /** + * @param pastClientTokenTimeout 单独配置此Client:Past-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 + "]"; } + }