From 845b57e9311945b323c760ad66af59621e290573 Mon Sep 17 00:00:00 2001 From: xlsea <m@xlsea.cn> Date: 星期一, 08 一月 2024 11:54:30 +0800 Subject: [PATCH] JustAuth 整合 TopIam 单点登录 --- ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java | 100 +++++++++++++++++++++++++++++++++ script/sql/ry_vue_5.X.sql | 2 ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java | 5 + ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopiamSource.java | 51 +++++++++++++++++ ruoyi-admin/src/main/resources/application-dev.yml | 7 ++ ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialLoginConfigProperties.java | 7 ++ 6 files changed, 170 insertions(+), 2 deletions(-) diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 4aaea57..4929c1b 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -189,6 +189,13 @@ client-id: 876892492581044224 client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8 redirect-uri: ${justauth.address}/social-callback?source=maxkey + topiam: + # topiam 鏈嶅姟鍣ㄥ湴鍧� + server-url: http://127.0.0.1:1989/api/v1/authorize/y0q************spq***********8ol + client-id: 449c4*********937************759 + client-secret: ac7***********1e0************28d + redirect-uri: ${justauth.address}/social-callback?source=topiam + scopes: [openid, email, phone, profile] qq: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialLoginConfigProperties.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialLoginConfigProperties.java index 76be234..5f49d9c 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialLoginConfigProperties.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialLoginConfigProperties.java @@ -2,6 +2,8 @@ import lombok.Data; +import java.util.List; + /** * 绀句氦鐧诲綍閰嶇疆 * @@ -65,4 +67,9 @@ */ private String serverUrl; + /** + * 璇锋眰鑼冨洿 + */ + private List<String> scopes; + } diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java new file mode 100644 index 0000000..13649f9 --- /dev/null +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java @@ -0,0 +1,100 @@ +package org.dromara.common.social.topiam; + +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.StrUtil; +import com.xkcoding.http.support.HttpHeader; +import lombok.extern.slf4j.Slf4j; +import me.zhyd.oauth.cache.AuthStateCache; +import me.zhyd.oauth.config.AuthConfig; +import me.zhyd.oauth.exception.AuthException; +import me.zhyd.oauth.model.AuthCallback; +import me.zhyd.oauth.model.AuthToken; +import me.zhyd.oauth.model.AuthUser; +import me.zhyd.oauth.request.AuthDefaultRequest; +import me.zhyd.oauth.utils.HttpUtils; +import me.zhyd.oauth.utils.UrlBuilder; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.json.utils.JsonUtils; + +import static org.dromara.common.social.topiam.AuthTopiamSource.TOPIAM; + +/** + * TopIAM 璁よ瘉璇锋眰 + * + * @author xlsea + * @since 2024-01-06 + */ +@Slf4j +public class AuthTopIamRequest extends AuthDefaultRequest { + + public static final String SERVER_URL = SpringUtils.getProperty("justauth.type.topiam.server-url"); + + /** + * 璁惧畾褰掑睘鍩� + */ + public AuthTopIamRequest(AuthConfig config) { + super(config, TOPIAM); + } + + public AuthTopIamRequest(AuthConfig config, AuthStateCache authStateCache) { + super(config, TOPIAM, authStateCache); + } + + @Override + protected AuthToken getAccessToken(AuthCallback authCallback) { + String body = doPostAuthorizationCode(authCallback.getCode()); + Dict object = JsonUtils.parseMap(body); + checkResponse(object); + return AuthToken.builder() + .accessToken(object.getStr("access_token")) + .refreshToken(object.getStr("refresh_token")) + .idToken(object.getStr("id_token")) + .tokenType(object.getStr("token_type")) + .scope(object.getStr("scope")) + .build(); + } + + @Override + protected AuthUser getUserInfo(AuthToken authToken) { + String body = doGetUserInfo(authToken); + Dict object = JsonUtils.parseMap(body); + checkResponse(object); + return AuthUser.builder() + .uuid(object.getStr("sub")) + .username(object.getStr("preferred_username")) + .nickname(object.getStr("nickname")) + .avatar(object.getStr("picture")) + .email(object.getStr("email")) + .token(authToken) + .source(source.toString()) + .build(); + } + + + @Override + protected String doGetUserInfo(AuthToken authToken) { + return new HttpUtils(config.getHttpConfig()).get(source.userInfo(), null, new HttpHeader() + .add("Content-Type", "application/json") + .add("Authorization", "Bearer " + authToken.getAccessToken()), false).getBody(); + } + + + @Override + public String authorize(String state) { + return UrlBuilder.fromBaseUrl(super.authorize(state)) + .queryParam("scope", StrUtil.join("%20", config.getScopes())) + .build(); + } + + public static void checkResponse(Dict object) { + // oauth/token 楠岃瘉寮傚父 + if (object.containsKey("error")) { + throw new AuthException(object.getStr("error_description")); + } + // user 楠岃瘉寮傚父 + if (object.containsKey("message")) { + throw new AuthException(object.getStr("message")); + } + } + +} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopiamSource.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopiamSource.java new file mode 100644 index 0000000..e47d6c6 --- /dev/null +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopiamSource.java @@ -0,0 +1,51 @@ +package org.dromara.common.social.topiam; + +import me.zhyd.oauth.config.AuthSource; +import me.zhyd.oauth.request.AuthDefaultRequest; + +/** + * Oauth2 榛樿鎺ュ彛璇存槑 + * + * @author xlsea + * @since 2024-01-06 + */ +public enum AuthTopiamSource implements AuthSource { + + /** + * 娴嬭瘯 + */ + TOPIAM { + /** + * 鎺堟潈鐨刟pi + */ + @Override + public String authorize() { + return AuthTopIamRequest.SERVER_URL + "/oauth2/auth"; + } + + /** + * 鑾峰彇accessToken鐨刟pi + */ + @Override + public String accessToken() { + return AuthTopIamRequest.SERVER_URL + "/oauth2/token"; + } + + /** + * 鑾峰彇鐢ㄦ埛淇℃伅鐨刟pi + */ + @Override + public String userInfo() { + return AuthTopIamRequest.SERVER_URL + "/oauth2/userinfo"; + } + + /** + * 骞冲彴瀵瑰簲鐨� AuthRequest 瀹炵幇绫伙紝蹇呴』缁ф壙鑷� {@link AuthDefaultRequest} + */ + @Override + public Class<? extends AuthDefaultRequest> getTargetClass() { + return AuthTopIamRequest.class; + } + + } +} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java index 51b7e13..04f6214 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java @@ -11,6 +11,7 @@ import org.dromara.common.social.config.properties.SocialLoginConfigProperties; import org.dromara.common.social.config.properties.SocialProperties; import org.dromara.common.social.maxkey.AuthMaxKeyRequest; +import org.dromara.common.social.topiam.AuthTopIamRequest; /** * 璁よ瘉鎺堟潈宸ュ叿绫� @@ -38,7 +39,8 @@ AuthConfig.AuthConfigBuilder builder = AuthConfig.builder() .clientId(obj.getClientId()) .clientSecret(obj.getClientSecret()) - .redirectUri(obj.getRedirectUri()); + .redirectUri(obj.getRedirectUri()) + .scopes(obj.getScopes()); return switch (source.toLowerCase()) { case "dingtalk" -> new AuthDingTalkRequest(builder.build(), STATE_CACHE); case "baidu" -> new AuthBaiduRequest(builder.build(), STATE_CACHE); @@ -63,6 +65,7 @@ case "wechat_mp" -> new AuthWeChatMpRequest(builder.build(), STATE_CACHE); case "aliyun" -> new AuthAliyunRequest(builder.build(), STATE_CACHE); case "maxkey" -> new AuthMaxKeyRequest(builder.build(), STATE_CACHE); + case "topiam" -> new AuthTopIamRequest(builder.build(), STATE_CACHE); default -> throw new AuthException("鏈幏鍙栧埌鏈夋晥鐨凙uth閰嶇疆"); }; } diff --git a/script/sql/ry_vue_5.X.sql b/script/sql/ry_vue_5.X.sql index ea365bd..c66782b 100644 --- a/script/sql/ry_vue_5.X.sql +++ b/script/sql/ry_vue_5.X.sql @@ -21,7 +21,7 @@ union_id varchar(255) default null comment '鐢ㄦ埛鐨� unionid', scope varchar(255) default null comment '鎺堜簣鐨勬潈闄愶紝閮ㄥ垎骞冲彴鍙兘娌℃湁', token_type varchar(255) default null comment '涓埆骞冲彴鐨勬巿鏉冧俊鎭紝閮ㄥ垎骞冲彴鍙兘娌℃湁', - id_token varchar(255) default null comment 'id token锛岄儴鍒嗗钩鍙板彲鑳芥病鏈�', + id_token text default null comment 'id token锛岄儴鍒嗗钩鍙板彲鑳芥病鏈�', mac_algorithm varchar(255) default null comment '灏忕背骞冲彴鐢ㄦ埛鐨勯檮甯﹀睘鎬э紝閮ㄥ垎骞冲彴鍙兘娌℃湁', mac_key varchar(255) default null comment '灏忕背骞冲彴鐢ㄦ埛鐨勯檮甯﹀睘鎬э紝閮ㄥ垎骞冲彴鍙兘娌℃湁', code varchar(255) default null comment '鐢ㄦ埛鐨勬巿鏉僣ode锛岄儴鍒嗗钩鍙板彲鑳芥病鏈�', -- Gitblit v1.9.3