mirror of
				https://github.com/dromara/RuoYi-Vue-Plus.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	JustAuth 整合 TopIam 单点登录
This commit is contained in:
		@@ -189,6 +189,13 @@ justauth:
 | 
			
		||||
      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
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,8 @@ package org.dromara.common.social.config.properties;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 社交登录配置
 | 
			
		||||
 *
 | 
			
		||||
@@ -65,4 +67,9 @@ public class SocialLoginConfigProperties {
 | 
			
		||||
     */
 | 
			
		||||
    private String serverUrl;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 请求范围
 | 
			
		||||
     */
 | 
			
		||||
    private List<String> scopes;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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"));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -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 {
 | 
			
		||||
        /**
 | 
			
		||||
         * 授权的api
 | 
			
		||||
         */
 | 
			
		||||
        @Override
 | 
			
		||||
        public String authorize() {
 | 
			
		||||
            return AuthTopIamRequest.SERVER_URL + "/oauth2/auth";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * 获取accessToken的api
 | 
			
		||||
         */
 | 
			
		||||
        @Override
 | 
			
		||||
        public String accessToken() {
 | 
			
		||||
            return AuthTopIamRequest.SERVER_URL + "/oauth2/token";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * 获取用户信息的api
 | 
			
		||||
         */
 | 
			
		||||
        @Override
 | 
			
		||||
        public String userInfo() {
 | 
			
		||||
            return AuthTopIamRequest.SERVER_URL + "/oauth2/userinfo";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * 平台对应的 AuthRequest 实现类,必须继承自 {@link AuthDefaultRequest}
 | 
			
		||||
         */
 | 
			
		||||
        @Override
 | 
			
		||||
        public Class<? extends AuthDefaultRequest> getTargetClass() {
 | 
			
		||||
            return AuthTopIamRequest.class;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -11,6 +11,7 @@ import org.dromara.common.core.utils.SpringUtils;
 | 
			
		||||
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 @@ public class SocialUtils  {
 | 
			
		||||
        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 @@ public class SocialUtils  {
 | 
			
		||||
            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("未获取到有效的Auth配置");
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ create table sys_social
 | 
			
		||||
    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 '用户的授权code,部分平台可能没有',
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user