mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-06-28 13:34:18 +08:00
feat(oauth2): 新增 UnionId 联合id 实现
This commit is contained in:
parent
e7694bd6fb
commit
21d5e02c67
@ -187,7 +187,7 @@
|
||||
client_id: '1001',
|
||||
client_secret: 'aaaa-bbbb-cccc-dddd-eeee',
|
||||
redirect_uri: location.href.split('?')[0].split('#')[0],
|
||||
scope: 'userinfo,userid,openid,oidc',
|
||||
scope: 'userinfo,userid,openid,unionid,oidc',
|
||||
username: 'sa',
|
||||
password: '123456'
|
||||
}
|
||||
|
@ -27,7 +27,8 @@ public class SaClientMockDao {
|
||||
.setClientId("1001") // client id
|
||||
.setClientSecret("aaaa-bbbb-cccc-dddd-eeee") // client 秘钥
|
||||
.addAllowRedirectUris("*") // 所有允许授权的 url
|
||||
.addContractScopes("openid", "userid", "userinfo", "oidc") // 所有签约的权限
|
||||
.addContractScopes("openid", "unionid", "userid", "userinfo", "oidc") // 所有签约的权限
|
||||
.setSubjectId("1000001") // 主体 id (可选)
|
||||
.addAllowGrantTypes( // 所有允许的授权模式
|
||||
GrantType.authorization_code, // 授权码式
|
||||
GrantType.implicit, // 隐式式
|
||||
@ -43,7 +44,8 @@ public class SaClientMockDao {
|
||||
.setClientId("1002")
|
||||
.setClientSecret("aaaa-bbbb-cccc-dddd-eeee")
|
||||
.addAllowRedirectUris("*")
|
||||
.addContractScopes("openid", "userid", "userinfo", "oidc")
|
||||
.addContractScopes("openid", "unionid", "userid", "userinfo", "oidc")
|
||||
.setSubjectId("1000001") // 主体 id (可选)
|
||||
.addAllowGrantTypes(
|
||||
GrantType.authorization_code,
|
||||
GrantType.implicit,
|
||||
@ -58,7 +60,7 @@ public class SaClientMockDao {
|
||||
.setClientId("1003")
|
||||
.setClientSecret("aaaa-bbbb-cccc-dddd-eeee")
|
||||
.addAllowRedirectUris("*")
|
||||
.addContractScopes("openid", "userid", "userinfo", "oidc")
|
||||
.addContractScopes("openid", "unionid", "userid", "userinfo", "oidc")
|
||||
.addAllowGrantTypes(
|
||||
GrantType.authorization_code,
|
||||
GrantType.implicit,
|
||||
|
@ -69,6 +69,9 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
/** 默认 openid 生成算法中使用的摘要前缀 */
|
||||
public String openidDigestPrefix = SaOAuth2Consts.OPENID_DEFAULT_DIGEST_PREFIX;
|
||||
|
||||
/** 默认 unionid 生成算法中使用的摘要前缀 */
|
||||
public String unionidDigestPrefix = SaOAuth2Consts.UNIONID_DEFAULT_DIGEST_PREFIX;
|
||||
|
||||
/** 指定高级权限,多个用逗号隔开 */
|
||||
public String higherScope;
|
||||
|
||||
@ -264,6 +267,22 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return unionidDigestPrefix
|
||||
*/
|
||||
public String getUnionidDigestPrefix() {
|
||||
return unionidDigestPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param unionidDigestPrefix 要设置的 unionidDigestPrefix
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaOAuth2ServerConfig setUnionidDigestPrefix(String unionidDigestPrefix) {
|
||||
this.unionidDigestPrefix = unionidDigestPrefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 指定高级权限,多个用逗号隔开
|
||||
*
|
||||
@ -403,6 +422,7 @@ public class SaOAuth2ServerConfig implements Serializable {
|
||||
", clientTokenTimeout=" + clientTokenTimeout +
|
||||
", lowerClientTokenTimeout=" + lowerClientTokenTimeout +
|
||||
", openidDigestPrefix='" + openidDigestPrefix +
|
||||
", unionidDigestPrefix='" + unionidDigestPrefix +
|
||||
", higherScope='" + higherScope +
|
||||
", lowerScope='" + lowerScope +
|
||||
", mode4ReturnAccessToken='" + mode4ReturnAccessToken +
|
||||
|
@ -90,6 +90,7 @@ public class SaOAuth2Consts {
|
||||
* 扩展字段
|
||||
*/
|
||||
public static final class ExtraField {
|
||||
public static String unionid = "unionid";
|
||||
public static String openid = "openid";
|
||||
public static String userid = "userid";
|
||||
public static String id_token = "id_token";
|
||||
@ -99,6 +100,9 @@ public class SaOAuth2Consts {
|
||||
/** 默认 openid 生成算法中使用的前缀 */
|
||||
public static final String OPENID_DEFAULT_DIGEST_PREFIX = "openid_default_digest_prefix";
|
||||
|
||||
/** 默认 unionid 生成算法中使用的前缀 */
|
||||
public static final String UNIONID_DEFAULT_DIGEST_PREFIX = "unionid_default_digest_prefix";
|
||||
|
||||
/** 表示OK的返回结果 */
|
||||
public static final String OK = "ok";
|
||||
|
||||
|
@ -57,7 +57,7 @@ public interface SaOAuth2DataLoader {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ClientId 和 LoginId 获取openid
|
||||
* 根据 ClientId 和 LoginId 获取openid
|
||||
*
|
||||
* @param clientId 应用id
|
||||
* @param loginId 账号id
|
||||
@ -67,4 +67,15 @@ public interface SaOAuth2DataLoader {
|
||||
return SaSecureUtil.md5(SaOAuth2Manager.getServerConfig().getOpenidDigestPrefix() + "_" + clientId + "_" + loginId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 SubjectId 和 LoginId 获取 unionid
|
||||
*
|
||||
* @param subjectId 应用主体id
|
||||
* @param loginId 账号id
|
||||
* @return 此账号在此Client下的openid
|
||||
*/
|
||||
default String getUnionid(String subjectId, Object loginId) {
|
||||
return SaSecureUtil.md5(SaOAuth2Manager.getServerConfig().getUnionidDigestPrefix() + "_" + subjectId + "_" + loginId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Client应用信息 Model
|
||||
* Client 应用信息 Model
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.23.0
|
||||
@ -58,6 +58,11 @@ public class SaClientModel implements Serializable {
|
||||
*/
|
||||
public List<String> allowGrantTypes = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 主体id
|
||||
*/
|
||||
public String subjectId;
|
||||
|
||||
/** 单独配置此Client:是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token [默认取全局配置] */
|
||||
public Boolean isNewRefresh;
|
||||
|
||||
@ -171,6 +176,25 @@ public class SaClientModel implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 主体id
|
||||
*
|
||||
* @return subjectId 主体id
|
||||
*/
|
||||
public String getSubjectId() {
|
||||
return this.subjectId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 主体id
|
||||
*
|
||||
* @param subjectId 主体id
|
||||
*/
|
||||
public SaClientModel setSubjectId(String subjectId) {
|
||||
this.subjectId = subjectId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 此Client:是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token [默认取全局配置]
|
||||
*/
|
||||
@ -261,6 +285,7 @@ public class SaClientModel implements Serializable {
|
||||
", contractScopes=" + contractScopes +
|
||||
", allowRedirectUris=" + allowRedirectUris +
|
||||
", allowGrantTypes=" + allowGrantTypes +
|
||||
", subjectId=" + subjectId +
|
||||
", isNewRefresh=" + isNewRefresh +
|
||||
", accessTokenTimeout=" + accessTokenTimeout +
|
||||
", refreshTokenTimeout=" + refreshTokenTimeout +
|
||||
|
@ -31,6 +31,11 @@ public final class CommonScope {
|
||||
*/
|
||||
public static final String OPENID = "openid";
|
||||
|
||||
/**
|
||||
* 获取 unionid
|
||||
*/
|
||||
public static final String UNIONID = "unionid";
|
||||
|
||||
/**
|
||||
* 获取 userid
|
||||
*/
|
||||
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.oauth2.scope.handler;
|
||||
|
||||
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
|
||||
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts;
|
||||
import cn.dev33.satoken.oauth2.data.loader.SaOAuth2DataLoader;
|
||||
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.ClientTokenModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel;
|
||||
import cn.dev33.satoken.oauth2.scope.CommonScope;
|
||||
|
||||
/**
|
||||
* UnionId Scope 处理器,在返回的 AccessToken 中增加 unionid 字段
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.40.0
|
||||
*/
|
||||
public class UnionIdScopeHandler implements SaOAuth2ScopeHandlerInterface {
|
||||
|
||||
@Override
|
||||
public String getHandlerScope() {
|
||||
return CommonScope.UNIONID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void workAccessToken(AccessTokenModel at) {
|
||||
SaOAuth2DataLoader dataLoader = SaOAuth2Manager.getDataLoader();
|
||||
SaClientModel cm = dataLoader.getClientModelNotNull(at.clientId);
|
||||
at.extraData.put(SaOAuth2Consts.ExtraField.unionid, dataLoader.getUnionid(cm.subjectId, at.loginId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void workClientToken(ClientTokenModel ct) {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -30,10 +30,7 @@ import cn.dev33.satoken.oauth2.granttype.handler.PasswordGrantTypeHandler;
|
||||
import cn.dev33.satoken.oauth2.granttype.handler.RefreshTokenGrantTypeHandler;
|
||||
import cn.dev33.satoken.oauth2.granttype.handler.SaOAuth2GrantTypeHandlerInterface;
|
||||
import cn.dev33.satoken.oauth2.scope.CommonScope;
|
||||
import cn.dev33.satoken.oauth2.scope.handler.OidcScopeHandler;
|
||||
import cn.dev33.satoken.oauth2.scope.handler.OpenIdScopeHandler;
|
||||
import cn.dev33.satoken.oauth2.scope.handler.SaOAuth2ScopeHandlerInterface;
|
||||
import cn.dev33.satoken.oauth2.scope.handler.UserIdScopeHandler;
|
||||
import cn.dev33.satoken.oauth2.scope.handler.*;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
@ -70,6 +67,7 @@ public final class SaOAuth2Strategy {
|
||||
*/
|
||||
public void registerDefaultScopeHandler() {
|
||||
scopeHandlerMap.put(CommonScope.OPENID, new OpenIdScopeHandler());
|
||||
scopeHandlerMap.put(CommonScope.UNIONID, new UnionIdScopeHandler());
|
||||
scopeHandlerMap.put(CommonScope.USERID, new UserIdScopeHandler());
|
||||
scopeHandlerMap.put(CommonScope.OIDC, new OidcScopeHandler());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user