thiszhc
2023-06-15 5110961eb98d820881a7c4a218e9e93fea07870e
第三方授权登录,加上配置
已添加2个文件
已修改3个文件
379 ■■■■■ 文件已修改
ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-dev.yml 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/DeviceType.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/ConfigProperties.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/AuthRedisStateCache.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java
@@ -2,9 +2,18 @@
import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import me.zhyd.oauth.cache.AuthStateCache;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.model.EmailLoginBody;
import org.dromara.common.core.domain.model.LoginBody;
@@ -13,9 +22,16 @@
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.social.config.SocialConfig;
import org.dromara.common.social.config.properties.ConfigProperties;
import org.dromara.common.social.config.properties.SocialProperties;
import org.dromara.common.social.utils.AuthRedisStateCache;
import org.dromara.common.social.utils.SocialUtils;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.system.domain.bo.SysTenantBo;
import org.dromara.system.domain.vo.SysTenantVo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.service.ISocialUserService;
import org.dromara.system.service.ISysConfigService;
import org.dromara.system.service.ISysTenantService;
import org.dromara.web.domain.vo.LoginTenantVo;
@@ -26,8 +42,10 @@
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Map;
/**
 * è®¤è¯
@@ -41,10 +59,14 @@
@RequestMapping("/auth")
public class AuthController {
    private final SocialProperties socialProperties;
    private final SysLoginService loginService;
    private final SysRegisterService registerService;
    private final ISysConfigService configService;
    private final ISysTenantService tenantService;
    private final ISocialUserService socialUserService;
    /**
     * ç™»å½•方法
@@ -115,6 +137,71 @@
        return R.ok(loginVo);
    }
    /**
     * è®¤è¯æŽˆæƒ
     * @param source
     */
    @GetMapping("/binding/{source}")
    @ResponseBody
    public R<LoginVo> authBinding(@PathVariable("source") String source, HttpServletRequest request){
        SysUserVo userLoding = new SysUserVo();
        if (ObjectUtil.isNull(userLoding)) {
            return R.fail("授权失败,请先登录再绑定");
        }
        if (socialUserService.isExistByUserIdAndSource(userLoding.getUserId(),source))
        {
            return R.fail(source + "平台账号已经被账号绑定");
        }
        ConfigProperties obj = socialProperties.getType().get(source);
        if (ObjectUtil.isNull(obj)){
            return R.fail(source + "平台账号暂不支持");
        }
        AuthRequest authRequest = SocialUtils.getAuthRequest(source,
            obj.getClientId(),
            obj.getClientSecret(),
            obj.getRedirectUri());
        String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
        return R.ok(authorizeUrl);
    }
    /**
     * ç¬¬ä¸‰æ–¹ç™»å½•回调业务处理
     * @param source
     * @param callback
     * @param request
     * @return
     */
    @SuppressWarnings("unchecked")
    @GetMapping("/social-login/{source}")
    public R<String> socialLogin(@PathVariable("source") String source, AuthCallback callback, HttpServletRequest request) throws IOException {
        ConfigProperties obj = socialProperties.getType().get(source);
        if (ObjectUtil.isNull(obj)){
            return R.fail(source + "平台账号暂不支持");
        }
        AuthRequest authRequest = SocialUtils.getAuthRequest(source,
            obj.getClientId(),
            obj.getClientSecret(),
            obj.getRedirectUri());
        AuthResponse<AuthUser> response = authRequest.login(callback);
        return loginService.socialLogin(source, response, request);
    }
    /**
     * å–消授权
     * @param socialId
     */
    @DeleteMapping(value = "/unlock/{socialId}")
    public R<Void> unlockSocial(@PathVariable Long socialId)
    {
        Boolean rows = socialUserService.deleteWithValidById(socialId);
        return rows ? R.ok() : R.fail("取消授权失败");
    }
    /**
     * é€€å‡ºç™»å½•
     */
ruoyi-admin/src/main/resources/application-dev.yml
@@ -169,3 +169,151 @@
  signName: æµ‹è¯•
  # è…¾è®¯ä¸“用
  sdkAppId:
justauth:
  enabled: true
  type:
    QQ:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/qq/callback
      union-id: false
    WEIBO:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/weibo/callback
    gitee:
      client-id: 38eaaa1b77b5e064313057a2f5745ce3a9f3e7686d9bd302c7df2f308ef6db81
      client-secret: 2e633af8780cb9fe002c4c7291b722db944402e271efb99b062811f52d7da1ff
      redirect-uri: http://localhost:8888/social-login?source=gitee
    DINGTALK:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/dingtalk/callback
    BAIDU:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/baidu/callback
    CSDN:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/csdn/callback
    CODING:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/coding/callback
      coding-group-name: xx
    OSCHINA:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/oschina/callback
    ALIPAY:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/alipay/callback
      alipay-public-key: MIIB**************DAQAB
    WECHAT_OPEN:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/wechat_open/callback
    WECHAT_MP:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/wechat_mp/callback
    WECHAT_ENTERPRISE:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/wechat_enterprise/callback
      agent-id: 1000002
    TAOBAO:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/taobao/callback
    GOOGLE:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/google/callback
    FACEBOOK:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/facebook/callback
    DOUYIN:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/douyin/callback
    LINKEDIN:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/linkedin/callback
    MICROSOFT:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/microsoft/callback
    MI:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/mi/callback
    TOUTIAO:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/toutiao/callback
    TEAMBITION:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/teambition/callback
    RENREN:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/renren/callback
    PINTEREST:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/pinterest/callback
    STACK_OVERFLOW:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/stack_overflow/callback
      stack-overflow-key: asd*********asd
    HUAWEI:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/huawei/callback
    KUJIALE:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/kujiale/callback
    GITLAB:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/gitlab/callback
    MEITUAN:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/meituan/callback
    ELEME:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/eleme/callback
    TWITTER:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/twitter/callback
    XMLY:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/xmly/callback
      # è®¾å¤‡å”¯ä¸€æ ‡è¯†ID
      device-id: xxxxxxxxxxxxxx
      # å®¢æˆ·ç«¯æ“ä½œç³»ç»Ÿç±»åž‹ï¼Œ1-iOS系统,2-Android系统,3-Web
      client-os-type: 3
      # å®¢æˆ·ç«¯åŒ…名,如果 clientOsType ä¸º1或2时必填。对Android客户端是包名,对IOS客户端是Bundle ID
      #pack-id: xxxx
    FEISHU:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/feishu/callback
    JD:
      client-id: 10**********6
      client-secret: 1f7d08**********5b7**********29e
      redirect-uri: http://oauth.xkcoding.com/demo/oauth/jd/callback
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/DeviceType.java
@@ -26,7 +26,12 @@
    /**
     * å°ç¨‹åºç«¯
     */
    XCX("xcx");
    XCX("xcx"),
    /**
     * social第三方端
     */
    SOCIAL("social");
    private final String device;
}
ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/ConfigProperties.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
package org.dromara.common.social.config.properties;
import lombok.Data;
@Data
public class ConfigProperties {
    /**
     * åº”用 ID
     */
    private String clientId;
    /**
     * åº”用密钥
     */
    private String clientSecret;
    /**
     * å›žè°ƒåœ°å€
     */
    private String redirectUri;
    /**
     * æ˜¯å¦èŽ·å–unionId
     */
    private boolean unionId;
    /**
     * Coding ä¼ä¸šåç§°
     */
    private String codingGroupName;
    /**
     * æ”¯ä»˜å®å…¬é’¥
     */
    private String alipayPublicKey;
    /**
     * ä¼ä¸šå¾®ä¿¡åº”用ID
     */
    private String agentId;
    /**
     * stackoverflow api key
     */
    private String stackOverflowKey;
    /**
     * è®¾å¤‡ID
     */
    private String deviceId;
    /**
     * å®¢æˆ·ç«¯ç³»ç»Ÿç±»åž‹
     */
    private String clientOsType;
}
ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/AuthRedisStateCache.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,79 @@
package org.dromara.common.social.utils;
import jakarta.annotation.PostConstruct;
import me.zhyd.oauth.cache.AuthStateCache;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.social.config.properties.SocialProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import java.time.Duration;
public class AuthRedisStateCache implements AuthStateCache {
    private final SocialProperties socialProperties;
    private final RedisTemplate<String, String> redisTemplate;
    private ValueOperations<String, String> valueOperations;
    @PostConstruct
    public void init() {
        valueOperations = redisTemplate.opsForValue();
    }
    public AuthRedisStateCache() {
        this.socialProperties = new SocialProperties();
        redisTemplate = new RedisTemplate<>();
    }
    /**
     * å­˜å…¥ç¼“å­˜
     *
     * @param key   ç¼“å­˜key
     * @param value ç¼“存内容
     */
    @Override
    public void cache(String key, String value) {
        // TODO: è‡ªå®šä¹‰å­˜å…¥ç¼“å­˜
        RedisUtils.setCacheObject(key, value, Duration.ofMillis(socialProperties.getTimeout()));
    }
    /**
     * å­˜å…¥ç¼“å­˜
     *
     * @param key     ç¼“å­˜key
     * @param value   ç¼“存内容
     * @param timeout æŒ‡å®šç¼“存过期时间(毫秒)
     */
    @Override
    public void cache(String key, String value, long timeout) {
        // TODO: è‡ªå®šä¹‰å­˜å…¥ç¼“å­˜
        RedisUtils.setCacheObject(key, value, Duration.ofMillis(timeout));
    }
    /**
     * èŽ·å–ç¼“å­˜å†…å®¹
     *
     * @param key ç¼“å­˜key
     * @return ç¼“存内容
     */
    @Override
    public String get(String key) {
        // TODO: è‡ªå®šä¹‰èŽ·å–ç¼“å­˜å†…å®¹
        return RedisUtils.getCacheObject(key);
    }
    /**
     * æ˜¯å¦å­˜åœ¨key,如果对应key的value值已过期,也返回false
     *
     * @param key ç¼“å­˜key
     * @return true:存在key,并且value没过期;false:key不存在或者已过期
     */
    @Override
    public boolean containsKey(String key) {
        // TODO: è‡ªå®šä¹‰åˆ¤æ–­key是否存在
        return RedisUtils.hasKey(key);
    }
}