diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/SaLoginModel.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/SaLoginModel.java index f3989153..144c157d 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/stp/SaLoginModel.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/SaLoginModel.java @@ -5,6 +5,8 @@ import cn.dev33.satoken.config.SaTokenConfig; import cn.dev33.satoken.dao.SaTokenDao; import cn.dev33.satoken.util.SaTokenConsts; +import java.util.Map; + /** * 调用 `StpUtil.login()` 时的 [配置参数 Model ] * @author kong @@ -27,6 +29,11 @@ public class SaLoginModel { */ public Long timeout; + /** + * jwt扩展信息 + */ + public Map expandInfoMap; + /** * @return 参考 {@link #device} @@ -76,6 +83,21 @@ public class SaLoginModel { return this; } + /** + * @return 参考 {@link #expandInfoMap} + */ + public Map getExpandInfoMap() { + return expandInfoMap; + } + + /** + * @param expandInfoMap 参考 {@link #expandInfoMap} + * @return 对象自身 + */ + public SaLoginModel setExpandInfoMap(Map expandInfoMap) { + this.expandInfoMap = expandInfoMap; + return this; + } /** * @return Cookie时长 diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java index 33312b0c..362ccf43 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java @@ -1,9 +1,6 @@ package cn.dev33.satoken.stp; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.function.Consumer; import cn.dev33.satoken.SaManager; @@ -94,6 +91,18 @@ public class StpLogic { return SaStrategy.me.createToken.apply(loginId, loginType); } + /** + * 创建一个TokenValue + * @param loginId loginId + * @param device 设备标识 + * @param expandInfoMap 扩展信息 + * @param timeout 过期时间 + * @return 生成的tokenValue + */ + public String createTokenValue(Object loginId, String device, Map expandInfoMap, long timeout) { + return SaStrategy.me.createToken.apply(loginId, loginType); + } + /** * 在当前会话写入当前TokenValue * @param tokenValue token值 @@ -260,6 +269,15 @@ public class StpLogic { login(id, new SaLoginModel().setDevice(device)); } + /** + * 会话登录,并指定扩展信息 for Jwt + * @param id 账号id,建议的类型:(long | int | String) + * @param expandInfoMap 扩展数据 + */ + public void login(Object id, Map expandInfoMap) { + login(id, new SaLoginModel().setExpandInfoMap(expandInfoMap)); + } + /** * 会话登录,并指定是否 [记住我] * @param id 账号id,建议的类型:(long | int | String) @@ -301,7 +319,7 @@ public class StpLogic { } // 如果至此,仍未成功创建tokenValue, 则开始生成一个 if(tokenValue == null) { - tokenValue = createTokenValue(id, loginModel.getDeviceOrDefault(), loginModel.getTimeout()); + tokenValue = createTokenValue(id, loginModel.getDeviceOrDefault(), loginModel.getExpandInfoMap(), loginModel.getTimeout()); } // ------ 3. 获取 User-Session , 续期 @@ -659,6 +677,18 @@ public class StpLogic { } return getLoginIdNotHandle(tokenValue); } + + /** + * 获取指定Token对应的扩展信息,如果未登录,则返回 null + * @param tokenValue token + * @return 账号id + */ + public Object getExpandInfoByToken(String tokenValue) { + if(tokenValue == null) { + return null; + } + return getExpandInfoNotHandle(tokenValue); + } /** * 获取指定Token对应的账号id (不做任何特殊处理) @@ -668,6 +698,17 @@ public class StpLogic { public String getLoginIdNotHandle(String tokenValue) { return getSaTokenDao().get(splicingKeyTokenValue(tokenValue)); } + + /** + * 获取指定Token对应的扩展信息 (不做任何特殊处理) + * @param tokenValue token值 + * @return 账号id + */ + public Object getExpandInfoNotHandle(String tokenValue) { + return getSaTokenDao().get(splicingKeyTokenValue(tokenValue)); + } + + // ---- 其它操作 /** diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java index 2f46bc22..8c76e64b 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java @@ -1,6 +1,7 @@ package cn.dev33.satoken.stp; import java.util.List; +import java.util.Map; import cn.dev33.satoken.SaManager; import cn.dev33.satoken.fun.SaFunction; @@ -114,6 +115,15 @@ public class StpUtil { stpLogic.login(id, device); } + /** + * 会话登录,并指定登录设备 + * @param id 账号id,建议的类型:(long | int | String) + * @param expandInfoMap 扩展信息 + */ + public static void login(Object id, Map expandInfoMap) { + stpLogic.login(id, expandInfoMap); + } + /** * 会话登录,并指定是否 [记住我] * @param id 账号id,建议的类型:(long | int | String) @@ -286,6 +296,15 @@ public class StpUtil { public static Object getLoginIdByToken(String tokenValue) { return stpLogic.getLoginIdByToken(tokenValue); } + + /** + * 获取指定Token对应的扩展数据,如果未登录,则返回 null + * @param tokenValue token + * @return 账号id + */ + public static Object getExpandInfoByToken(String tokenValue) { + return stpLogic.getExpandInfoByToken(tokenValue); + } // =================== User-Session 相关 =================== diff --git a/sa-token-doc/doc/more/sa-token-donate.md b/sa-token-doc/doc/more/sa-token-donate.md index 93a3282b..bf8fbe99 100644 --- a/sa-token-doc/doc/more/sa-token-donate.md +++ b/sa-token-doc/doc/more/sa-token-donate.md @@ -19,6 +19,11 @@ Sa-Token 采用 Apache-2.0 开源协议,**承诺框架本身与官网文档永 | 赞助人 | 赞助金额 | 留言 | 时间 | | :-------- | :-------- | :-------- | :-------- | +| 周周周杨 | ¥ 10 | 感谢您的开源项目! | 2021-12-18 | +| MrXionGe | ¥ 10 | SA加油~~ | 2021-12-17 | +| duyiliu | ¥ 10 | 化繁为简,是门艺术。 | 2021-12-16 | +| liu | ¥ 50 | 感谢您的开源项目! | 2021-12-15 | +| fuhouyin | ¥ 10 | 感谢您的开源项目! | 2021-12-01 | | 图灵谷 | ¥ 20 | 感谢您的开源项目! | 2021-11-30 | | luyuan | ¥ 20 | 感谢您的开源项目! | 2021-11-29 | | xiaoyan | ¥ 200 | 感谢您的开源项目! | 2021-11-26 | @@ -45,7 +50,7 @@ Sa-Token 采用 Apache-2.0 开源协议,**承诺框架本身与官网文档永 | njx33 | ¥ 10 | 感谢您的开源项目! | 2020-12-17 | | zhangjiaxiaozhuo | ¥ 10 | 感谢您的开源项目! | 2020-12-15 | | 知知 | ¥ 10 | 感谢您的开源项目! | 2020-12-15 | -| 省长 | ¥ 10 | java中最好用的权限认证框架! | 2020-12-15 | +| 省长 | ¥ 10 | java中最好用的权限认证框架! | 2020-12-15 | 感谢每一位小伙伴的热心支持! diff --git a/sa-token-doc/index.html b/sa-token-doc/index.html index c5db4c17..63142e17 100644 --- a/sa-token-doc/index.html +++ b/sa-token-doc/index.html @@ -263,6 +263,9 @@ + + +
diff --git a/sa-token-plugin/sa-token-context-dubbo/src/main/java/cn/dev33/satoken/context/dubbo/filter/SaTokenDubboConsumerFilter.java b/sa-token-plugin/sa-token-context-dubbo/src/main/java/cn/dev33/satoken/context/dubbo/filter/SaTokenDubboConsumerFilter.java index 451c9f3a..e183eb96 100644 --- a/sa-token-plugin/sa-token-context-dubbo/src/main/java/cn/dev33/satoken/context/dubbo/filter/SaTokenDubboConsumerFilter.java +++ b/sa-token-plugin/sa-token-context-dubbo/src/main/java/cn/dev33/satoken/context/dubbo/filter/SaTokenDubboConsumerFilter.java @@ -1,5 +1,6 @@ package cn.dev33.satoken.context.dubbo.filter; +import cn.dev33.satoken.exception.SaTokenException; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.rpc.Filter; @@ -32,8 +33,15 @@ public class SaTokenDubboConsumerFilter implements Filter { RpcContext.getContext().setAttachment(SaIdUtil.ID_TOKEN, SaIdUtil.getToken()); } - // 1. 调用前,向下传递会话Token - RpcContext.getContext().setAttachment(SaTokenConsts.JUST_CREATED, StpUtil.getTokenValueNotCut()); + // 1. 调用前,向下传递会话Token + String tokenValueNotCut = null; + try { + tokenValueNotCut = StpUtil.getTokenValueNotCut(); + } catch (SaTokenException exception){ + + } finally { + RpcContext.getContext().setAttachment(SaTokenConsts.JUST_CREATED, tokenValueNotCut); + } // 2. 开始调用 Result invoke = invoker.invoke(invocation); diff --git a/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/SaJwtUtil.java b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/SaJwtUtil.java index bed4996f..7f19b001 100644 --- a/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/SaJwtUtil.java +++ b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/SaJwtUtil.java @@ -4,10 +4,13 @@ import cn.dev33.satoken.dao.SaTokenDao; import cn.dev33.satoken.exception.NotLoginException; import cn.dev33.satoken.exception.SaTokenException; import cn.dev33.satoken.util.SaFoxUtil; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.json.JSONObject; import cn.hutool.jwt.JWT; import cn.hutool.jwt.JWTException; +import java.util.Map; + /** * jwt操作工具类封装 * @author kong @@ -33,7 +36,12 @@ public class SaJwtUtil { /** * key:有效截止期 (时间戳) */ - public static final String EFF = "eff"; + public static final String EFF = "eff"; + + /** + * key: 扩展数据 + */ + public static final String EXPAND = "expand"; /** * 当有效期被设为此值时,代表永不过期 @@ -97,6 +105,44 @@ public class SaJwtUtil { return token; } + /** + * 创建 jwt (全参数方式) + * @param loginType 账号类型 + * @param loginId 账号id + * @param device 设备标识 + * @param expandInfoMap 扩展数据 + * @param timeout token有效期 (单位 秒) + * @param keyt 秘钥 + * @return jwt-token + */ + public static String createToken(String loginType, Object loginId, String device, + Map expandInfoMap, long timeout, String keyt) { + + // 秘钥不可以为空 + SaTokenException.throwByNull(keyt, "请配置jwt秘钥"); + + // 计算有效期 + long effTime = timeout; + if(timeout != NEVER_EXPIRE) { + effTime = timeout * 1000 + System.currentTimeMillis(); + } + + JWT jwt = JWT.create() + .setPayload(LOGIN_TYPE, loginType) + .setPayload(LOGIN_ID, loginId) + .setPayload(DEVICE, device) + .setPayload(EFF, effTime); + + // 设定扩展数据 + if (CollectionUtil.isNotEmpty(expandInfoMap)) { + jwt.setPayload(EXPAND, expandInfoMap); + } + + // 返回 + return jwt.setKey(keyt.getBytes()).sign(); + } + + /** * jwt 解析(校验签名和密码) * @param token Jwt-Token值 @@ -188,6 +234,33 @@ public class SaJwtUtil { } } + /** + * getExpandMap + * + * @since 2021/11/23 5:05 下午 + * @param token token值 + * @param keyt 秘钥 + * @return 值 + */ + public static Object getExpandInfo(String token, String keyt) { + return getPayloads(token, keyt).get(EXPAND); + } + + /** + * 获取 jwt 代表的账号id (未登录时返回null) + * @param token Token值 + * @param keyt 秘钥 + * @return 值 + */ + public static Object getExpandInfoOrNull(String token, String keyt) { + try { + return getPayloads(token, keyt).get(EXPAND); + } catch (NotLoginException e) { + return null; + } + } + + /** * 获取 jwt 剩余有效期 * @param token JwtToken值 diff --git a/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForMix.java b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForMix.java index c6db47b0..9c7e5e78 100644 --- a/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForMix.java +++ b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForMix.java @@ -1,6 +1,7 @@ package cn.dev33.satoken.jwt; import java.util.List; +import java.util.Map; import cn.dev33.satoken.context.SaHolder; import cn.dev33.satoken.dao.SaTokenDao; @@ -54,6 +55,11 @@ public class StpLogicJwtForMix extends StpLogic { return SaJwtUtil.createToken(loginType, loginId, device, timeout, jwtSecretKey()); } + @Override + public String createTokenValue(Object loginId, String device, Map expandInfoMap, long timeout) { + return SaJwtUtil.createToken(loginType, loginId, device, expandInfoMap, timeout, jwtSecretKey()); + } + /** * 获取当前会话的Token信息 * @return token信息 @@ -95,6 +101,21 @@ public class StpLogicJwtForMix extends StpLogic { } } + @Override + public Object getExpandInfoNotHandle(String tokenValue) { + // 先验证 loginType,如果不符,则视为无效token,返回null + String loginType = SaJwtUtil.getPayloadsNotCheck(tokenValue, jwtSecretKey()).getStr(SaJwtUtil.LOGIN_TYPE); + if(getLoginType().equals(loginType) == false) { + return null; + } + // 获取 expandInfo + try { + return SaJwtUtil.getExpandInfo(tokenValue, jwtSecretKey()); + } catch (NotLoginException e) { + return null; + } + } + /** * 会话注销 */ diff --git a/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForStateless.java b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForStateless.java index cbfb2760..d8d89eff 100644 --- a/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForStateless.java +++ b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForStateless.java @@ -11,6 +11,8 @@ import cn.dev33.satoken.stp.SaTokenInfo; import cn.dev33.satoken.stp.StpLogic; import cn.dev33.satoken.stp.StpUtil; +import java.util.Map; + /** * Sa-Token 整合 jwt -- stateless 无状态 * @author kong @@ -55,6 +57,11 @@ public class StpLogicJwtForStateless extends StpLogic { return SaJwtUtil.createToken(loginType, loginId, device, timeout, jwtSecretKey()); } + @Override + public String createTokenValue(Object loginId, String device, Map expandInfoMap, long timeout) { + return SaJwtUtil.createToken(loginType, loginId, device, expandInfoMap, timeout, jwtSecretKey()); + } + /** * 获取当前会话的Token信息 * @return token信息 @@ -89,7 +96,7 @@ public class StpLogicJwtForStateless extends StpLogic { loginModel.build(getConfig()); // ------ 2、生成一个token - String tokenValue = createTokenValue(id, loginModel.getDeviceOrDefault(), loginModel.getTimeout()); + String tokenValue = createTokenValue(id, loginModel.getDeviceOrDefault(), loginModel.getExpandInfoMap(), loginModel.getTimeout()); // 3、在当前会话写入tokenValue setTokenValue(tokenValue, loginModel.getCookieTimeout()); @@ -117,6 +124,21 @@ public class StpLogicJwtForStateless extends StpLogic { } } + @Override + public Object getExpandInfoNotHandle(String tokenValue) { + // 先验证 loginType,如果不符,则视为无效token,返回null + String loginType = SaJwtUtil.getPayloadsNotCheck(tokenValue, jwtSecretKey()).getStr(SaJwtUtil.LOGIN_TYPE); + if(getLoginType().equals(loginType) == false) { + return null; + } + // 获取 expandInfoMap + try { + return SaJwtUtil.getExpandInfo(tokenValue, jwtSecretKey()); + } catch (NotLoginException e) { + return null; + } + } + /** * 会话注销 */ 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 06ecd72a..15017790 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 @@ -1,11 +1,11 @@ package cn.dev33.satoken.oauth2.config; +import cn.dev33.satoken.util.SaResult; + import java.io.Serializable; import java.util.function.BiFunction; import java.util.function.Supplier; -import cn.dev33.satoken.util.SaResult; - /** * Sa-Token-OAuth2 配置类 Model * @author kong @@ -16,15 +16,19 @@ public class SaOAuth2Config implements Serializable { private static final long serialVersionUID = -6541180061782004705L; /** 是否打开模式:授权码(Authorization Code) */ + @Deprecated public Boolean isCode = true; /** 是否打开模式:隐藏式(Implicit) */ + @Deprecated public Boolean isImplicit = false; /** 是否打开模式:密码式(Password) */ + @Deprecated public Boolean isPassword = false; /** 是否打开模式:凭证式(Client Credentials) */ + @Deprecated public Boolean isClient = false; /** 是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token */ diff --git a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Consts.java b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Consts.java index afd8108e..a538be55 100644 --- a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Consts.java +++ b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Consts.java @@ -59,6 +59,7 @@ public class SaOAuth2Consts { public static String refresh_token = "refresh_token"; public static String password = "password"; public static String client_credentials = "client_credentials"; + public static String implicit = "implicit"; } /** 表示OK的返回结果 */ 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 d7c5332f..0956bae4 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 @@ -35,10 +35,13 @@ public class SaOAuth2Handle { SaResponse res = SaHolder.getResponse(); SaOAuth2Config cfg = SaOAuth2Manager.getConfig(); + //读取client_id,此参数在所有模式中必填 + String clientId = req.getParamNotNull(Param.client_id); + // ------------------ 路由分发 ------------------ // 模式一:Code授权码 - if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.code) && cfg.isCode) { + if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.code) && (SaOAuth2Util.supportType(clientId,GrantType.authorization_code) || cfg.isCode)) { return authorize(req, res, cfg); } @@ -68,17 +71,17 @@ public class SaOAuth2Handle { } // 模式二:隐藏式 - if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.token) && cfg.isImplicit) { + if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.token) && (SaOAuth2Util.supportType(clientId,GrantType.implicit) || cfg.isImplicit)) { return authorize(req, res, cfg); } // 模式三:密码式 - if(req.isPath(Api.token) && req.isParam(Param.grant_type, GrantType.password) && cfg.isPassword) { + if(req.isPath(Api.token) && req.isParam(Param.grant_type, GrantType.password) && (SaOAuth2Util.supportType(clientId,GrantType.password) || cfg.isPassword)) { return password(req, res, cfg); } // 模式四:凭证式 - if(req.isPath(Api.client_token) && req.isParam(Param.grant_type, GrantType.client_credentials) && cfg.isClient) { + if(req.isPath(Api.client_token) && req.isParam(Param.grant_type, GrantType.client_credentials) && (SaOAuth2Util.supportType(clientId,GrantType.client_credentials) || cfg.isClient)) { return clientToken(req, res, cfg); } 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 8cc6482c..e135895a 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 @@ -9,6 +9,7 @@ import cn.dev33.satoken.oauth2.model.*; import cn.dev33.satoken.strategy.SaStrategy; import cn.dev33.satoken.util.SaFoxUtil; +import java.util.Arrays; import java.util.List; /** @@ -302,7 +303,7 @@ public class SaOAuth2Template { // 删除 Access-Token deleteAccessToken(accessToken); - deleteAccessTokenIndex(at.clientId, at.accessToken); + deleteAccessTokenIndex(at.clientId, at.loginId); // 删除对应的 Refresh-Token String refreshToken = getRefreshTokenValue(at.clientId, at.loginId); @@ -917,4 +918,12 @@ public class SaOAuth2Template { return SaManager.getConfig().getTokenName() + ":oauth2:grant-scope:" + clientId + ":" + loginId; } + /** + * 检查是否支持的type类型 + */ + public Boolean supportType(String clientId,String type){ + SaClientModel saClientModel = checkClientModel(clientId); + return Arrays.asList(saClientModel.getAllowType().split(",")).contains(type); + } + } diff --git a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Util.java b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Util.java index 068f9001..3e5a747f 100644 --- a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Util.java +++ b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Util.java @@ -292,6 +292,16 @@ public class SaOAuth2Util { public static String getGrantScope(String clientId, Object loginId) { return saOAuth2Template.getGrantScope(clientId, loginId); } + + /** + * 获取:检查是否支持的授权类型 + * @param clientId 应用id + * @param type 授权类型 + * @return 是否 + */ + public static Boolean supportType(String clientId, String type) { + return saOAuth2Template.supportType(clientId, type); + } 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 952f696c..c2672618 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 @@ -31,15 +31,21 @@ public class SaClientModel implements Serializable { */ public String allowUrl; + /** + * 应用允许授权的所有URL, 多个用逗号隔开 + */ + public String allowType; + public SaClientModel() { } - public SaClientModel(String clientId, String clientSecret, String contractScope, String allowUrl) { + public SaClientModel(String clientId, String clientSecret, String contractScope, String allowUrl,String allowType) { super(); this.clientId = clientId; this.clientSecret = clientSecret; this.contractScope = contractScope; this.allowUrl = allowUrl; + this.allowType = allowType; } /** @@ -105,6 +111,22 @@ public class SaClientModel implements Serializable { this.allowUrl = allowUrl; return this; } + + /** + * @return 应用允许的授权模式, 多个用逗号隔开 + */ + public String getAllowType() { + return allowType; + } + + /** + * @param allowType 应用允许的授权模式, 多个用逗号隔开 + * @return 对象自身 + */ + public SaClientModel setAllowType(String allowType) { + this.allowType = allowType; + return this; + } @Override public String toString() {