RuoYi-Vue-Plus之第三方授权

文档地址:点击这里

项目地址:点击这里

功能介绍:点击这里


第三方授权

要实现第三方授权,不同的第三方需要配置的信息不一样,下面是一部分第三方应用的配置信息。

配置文件

配置类

@Data
@Component
@ConfigurationProperties(prefix = "justauth")
public class SocialProperties {

    /**
     * 是否启用
     */
    private Boolean enabled;

    /**
     * 授权类型
     * SocialLoginConfigProperties已在上图指出
     */
    private Map<String, SocialLoginConfigProperties> type;

}

SocialUtils工具类

/**
 * 认证授权工具类
 *
 * @author thiszhc
 */
public class SocialUtils  {

    private static final AuthRedisStateCache STATE_CACHE = SpringUtils.getBean(AuthRedisStateCache.class);

    @SuppressWarnings("unchecked")
    public static AuthResponse<AuthUser> loginAuth(String source, String code, String state, SocialProperties socialProperties) throws AuthException {
        AuthRequest authRequest = getAuthRequest(source, socialProperties);
        AuthCallback callback = new AuthCallback();
        callback.setCode(code);
        callback.setState(state);
        // 实现第三方登录
        return authRequest.login(callback);
    }
    
    public static AuthRequest getAuthRequest(String source, SocialProperties socialProperties) throws AuthException {
        SocialLoginConfigProperties obj = socialProperties.getType().get(source);
         if (ObjectUtil.isNull(obj)) {
            throw new AuthException("不支持的第三方登录类型");
        }
        AuthConfig.AuthConfigBuilder builder = AuthConfig.builder()
            .clientId(obj.getClientId())
            .clientSecret(obj.getClientSecret())
            .redirectUri(obj.getRedirectUri());
        return switch (source.toLowerCase()) {
            case "dingtalk" -> new AuthDingTalkRequest(builder.build(), STATE_CACHE);
            case "baidu" -> new AuthBaiduRequest(builder.build(), STATE_CACHE);
            case "github" -> new AuthGithubRequest(builder.build(), STATE_CACHE);
            case "gitee" -> new AuthGiteeRequest(builder.build(), STATE_CACHE);
            case "weibo" -> new AuthWeiboRequest(builder.build(), STATE_CACHE);
            case "coding" -> new AuthCodingRequest(builder.build(), STATE_CACHE);
            case "oschina" -> new AuthOschinaRequest(builder.build(), STATE_CACHE);
            // 支付宝在创建回调地址时,不允许使用localhost或者127.0.0.1,所以这儿的回调地址使用的局域网内的ip
            case "alipay_wallet" -> new AuthAlipayRequest(builder.build(), socialProperties.getType().get("alipay_wallet").getAlipayPublicKey(), STATE_CACHE);
            case "qq" -> new AuthQqRequest(builder.build(), STATE_CACHE);
            case "wechat_open" -> new AuthWeChatOpenRequest(builder.build(), STATE_CACHE);
            case "taobao" -> new AuthTaobaoRequest(builder.build(), STATE_CACHE);
            case "douyin" -> new AuthDouyinRequest(builder.build(), STATE_CACHE);
            case "linkedin" -> new AuthLinkedinRequest(builder.build(), STATE_CACHE);
            case "microsoft" -> new AuthMicrosoftRequest(builder.build(), STATE_CACHE);
            case "renren" -> new AuthRenrenRequest(builder.build(), STATE_CACHE);
            case "stack_overflow" -> new AuthStackOverflowRequest(builder.stackOverflowKey("").build(), STATE_CACHE);
            case "huawei" -> new AuthHuaweiRequest(builder.build(), STATE_CACHE);
            case "wechat_enterprise" -> new AuthWeChatEnterpriseQrcodeRequest(builder.agentId("").build(), STATE_CACHE);
            case "gitlab" -> new AuthGitlabRequest(builder.build(), STATE_CACHE);
            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);
            default -> throw new AuthException("未获取到有效的Auth配置");
        };
    }
}

国外平台配置

如果配置的是国外平台授权登录,例如google,修改一下getAuthRequest()方法,在switch语句中加上 case "google" -> new AuthGoogleRequest(builder.build(), STATE_CACHE);,然后

例如我的微屁恩,选择http/https的ip

或者打开代理设置

请求登录

控制层方法

/**
     * 第三方登录请求
     *
     * @param source 登录来源
     * @return 结果
     */
    @GetMapping("/binding/{source}")
    public R<String> authBinding(@PathVariable("source") String source) {
        if (!socialProperties.getEnabled()) {
            return R.fail("第三方授权登录已关闭");
        }
        // 从配置文件中获得信息
        SocialLoginConfigProperties obj = socialProperties.getType().get(source);
        if (ObjectUtil.isNull(obj)) {
            return R.fail(source + "平台账号暂不支持");
        }
        AuthRequest authRequest = SocialUtils.getAuthRequest(source, socialProperties);
        String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
        return R.ok("操作成功", authorizeUrl);
    }

分析authRequest.authorize(AuthStateUtils.createState())

AuthStateUtils.createState():生成uuid

进入方法源码:

经过追溯源码,发现该方法主要作用就是构建url以及把uuid缓存到redis中

绑定授权

控制层方法

/**
     * 第三方登录回调业务处理 绑定授权
     *
     * @param loginBody 请求体
     * @return 结果
     */
    @PostMapping("/social/callback")
    public R<Void> socialCallback(@RequestBody SocialLoginBody loginBody) {
        if (!socialProperties.getEnabled()) {
            return R.fail("第三方授权登录已关闭");
        }
        // 获取第三方登录信息
        AuthResponse<AuthUser> response = SocialUtils.loginAuth(
                loginBody.getSource(), loginBody.getSocialCode(),
                loginBody.getSocialState(), socialProperties);
        AuthUser authUserData = response.getData();
        // 判断授权响应是否成功
        if (!response.ok()) {
            return R.fail(response.getMsg());
        }
        loginService.socialRegister(authUserData);
        return R.ok();
    }

当我们需要绑定第三方应用时,会先调用请求登录接口,如果请求成功,然后再调用绑定授权接口。进入到SocialUtils.loginAuth(),然后进入authRequest.login()。

分析Request.login(callback)

进入authRequest.login()源方法

进入getAccessToken()方法

进入getUserInfo()方法

最终咱们可以获取到:将用户信息设置到授权相应类AuthResponse。然后进行下一步的处理:存到数据库中。

取消绑定

从数据库删除 需要取消绑定的用户即可。


RuoYi-Vue-Plus之第三方授权
http://example.com/2024/04/21/RuoYi-Vue-Plus之第三方授权/
发布于
2024年4月21日
更新于
2024年5月11日
许可协议