Browse Source

拓展授权登录抽取成单独的starter,拓展配置和默认配置齐平

timfruit 3 years atrás
parent
commit
8aa45406fd
23 changed files with 288 additions and 99 deletions
  1. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java
  2. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserProfileController.java
  3. 8 9
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java
  4. 2 2
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthServiceImplTest.java
  5. 4 6
      yudao-core-service/pom.xml
  6. 1 2
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/social/SysSocialUserMapper.java
  7. 1 2
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/redis/social/SysSocialAuthUserRedisDAO.java
  8. 6 4
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/social/SysSocialService.java
  9. 8 8
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/social/impl/SysSocialServiceImpl.java
  10. 9 10
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/social/SysSocialServiceTest.java
  11. 6 0
      yudao-dependencies/pom.xml
  12. 1 0
      yudao-framework/pom.xml
  13. 50 0
      yudao-framework/yudao-spring-boot-starter-biz-social/pom.xml
  14. 29 0
      yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/config/YudaoSocialAutoConfiguration.java
  15. 108 0
      yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java
  16. 1 1
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthExtendSource.java
  17. 3 2
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthExtendToken.java
  18. 21 13
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthWeChatMiniProgramRequest.java
  19. 2 0
      yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring.factories
  20. 2 2
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java
  21. 8 8
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/impl/SysAuthServiceImpl.java
  22. 7 15
      yudao-user-server/src/main/resources/application-dev.yaml
  23. 7 11
      yudao-user-server/src/main/resources/application-local.yaml

+ 2 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java

@@ -9,7 +9,7 @@ import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
-import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
+import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
@@ -50,7 +50,7 @@ public class SysAuthController {
     @Resource
     private SysPermissionService permissionService;
     @Resource
-    private SysSocialService socialService;
+    private SysSocialCoreService socialService;
 
     @PostMapping("/login")
     @ApiOperation("使用账号密码登录")

+ 2 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserProfileController.java

@@ -15,7 +15,7 @@ import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleSer
 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
-import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
+import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
@@ -56,7 +56,7 @@ public class SysUserProfileController {
     @Resource
     private SysRoleService roleService;
     @Resource
-    private SysSocialService socialService;
+    private SysSocialCoreService socialService;
 
     @GetMapping("/get")
     @ApiOperation("获得登录用户信息")

+ 8 - 9
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java

@@ -17,7 +17,7 @@ import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO
 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
-import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
+import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
@@ -73,10 +73,9 @@ public class SysAuthServiceImpl implements SysAuthService {
     @Resource
     private SysUserSessionCoreService userSessionCoreService;
     @Resource
-    private SysSocialService socialService;
+    private SysSocialCoreService socialService;
 
-    // TODO @timfruit:静态枚举类,需要都大写,例如说 USER_TYPE_ENUM;静态变量,放在普通变量前面;这个实践不错哈。
-    private static final UserTypeEnum userTypeEnum = UserTypeEnum.ADMIN;
+    private static final UserTypeEnum USER_TYPE_ENUM = UserTypeEnum.ADMIN;
 
     @Override
     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
@@ -201,7 +200,7 @@ public class SysAuthServiceImpl implements SysAuthService {
 
         // 如果未绑定 SysSocialUserDO 用户,则无法自动登录,进行报错
         String unionId = socialService.getAuthUserUnionId(authUser);
-        List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, userTypeEnum);
+        List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, USER_TYPE_ENUM);
         if (CollUtil.isEmpty(socialUsers)) {
             throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
         }
@@ -218,7 +217,7 @@ public class SysAuthServiceImpl implements SysAuthService {
         loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
 
         // 绑定社交用户(更新)
-        socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, userTypeEnum);
+        socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, USER_TYPE_ENUM);
 
         // 缓存登录用户到 Redis 中,返回 sessionId 编号
         return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
@@ -235,7 +234,7 @@ public class SysAuthServiceImpl implements SysAuthService {
         loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
 
         // 绑定社交用户(新增)
-        socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, userTypeEnum);
+        socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, USER_TYPE_ENUM);
 
         // 缓存登录用户到 Redis 中,返回 sessionId 编号
         return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
@@ -248,7 +247,7 @@ public class SysAuthServiceImpl implements SysAuthService {
         Assert.notNull(authUser, "授权用户不为空");
 
         // 绑定社交用户(新增)
-        socialService.bindSocialUser(userId, reqVO.getType(), authUser, userTypeEnum);
+        socialService.bindSocialUser(userId, reqVO.getType(), authUser, USER_TYPE_ENUM);
     }
 
     @Override
@@ -269,7 +268,7 @@ public class SysAuthServiceImpl implements SysAuthService {
         reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());
         reqDTO.setTraceId(TracerUtils.getTraceId());
         reqDTO.setUserId(userId);
-        reqDTO.setUserType(userTypeEnum.getValue());
+        reqDTO.setUserType(USER_TYPE_ENUM.getValue());
         reqDTO.setUsername(username);
         reqDTO.setUserAgent(ServletUtils.getUserAgent());
         reqDTO.setUserIp(ServletUtils.getClientIP());

+ 2 - 2
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthServiceImplTest.java

@@ -11,7 +11,7 @@ import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
-import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
+import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.security.core.LoginUser;
@@ -66,7 +66,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
     @MockBean
     private SysUserSessionCoreService userSessionCoreService;
     @MockBean
-    private SysSocialService socialService;
+    private SysSocialCoreService socialService;
 
     @Test
     public void testLoadUserByUsername_success() {

+ 4 - 6
yudao-core-service/pom.xml

@@ -36,6 +36,10 @@
             <groupId>cn.iocoder.boot</groupId>
             <artifactId>yudao-spring-boot-starter-biz-pay</artifactId>
         </dependency>
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-biz-social</artifactId>
+        </dependency>
 
         <!-- Web 相关 -->
         <dependency>
@@ -96,12 +100,6 @@
             <artifactId>guava</artifactId>
         </dependency>
 
-        <!-- 三方云服务相关 -->
-        <dependency>
-            <groupId>com.xkcoding.justauth</groupId>
-            <artifactId>justauth-spring-boot-starter</artifactId>
-        </dependency>
-
     </dependencies>
 
 </project>

+ 1 - 2
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/social/SysSocialUserMapper.java

@@ -8,9 +8,8 @@ import org.apache.ibatis.annotations.Mapper;
 import java.util.Collection;
 import java.util.List;
 
-// TODO @timfruit:SysSocialUserCoreMapper 改名,方便区分
 @Mapper
-public interface SysSocialUserMapper extends BaseMapperX<SysSocialUserDO> {
+public interface SysSocialUserCoreMapper extends BaseMapperX<SysSocialUserDO> {
 
     default List<SysSocialUserDO> selectListByTypeAndUnionId(Integer userType, Collection<Integer> types, String unionId) {
         return selectList(new QueryWrapper<SysSocialUserDO>().eq("user_type", userType)

+ 1 - 2
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/redis/social/SysSocialAuthUserRedisDAO.java

@@ -10,9 +10,8 @@ import javax.annotation.Resource;
 
 import static cn.iocoder.yudao.coreservice.modules.system.dal.redis.SysRedisKeyCoreConstants.SOCIAL_AUTH_USER;
 
-// TODO @timfruit,这里的 AuthUser 还是保留全路径,主要想体现出来,不是自己定义的
 /**
- * 社交 {@link AuthUser} 的 RedisDAO
+ * 社交 {@link me.zhyd.oauth.model.AuthUser} 的 RedisDAO
  *
  * @author 芋道源码
  */

+ 6 - 4
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/social/SysSocialService.java

@@ -15,8 +15,7 @@ import java.util.List;
  *
  * @author 芋道源码
  */
-// TODO @timfruit:SysSocialCoreService 改名,方便区分
-public interface SysSocialService {
+public interface SysSocialCoreService {
 
     /**
      * 获得社交平台的授权 URL
@@ -50,6 +49,7 @@ public interface SysSocialService {
      * @param type 社交平台的类型 {@link SysSocialTypeEnum}
      * @param unionId 社交平台的 unionId
      * @return 社交用户列表
+     * @param userTypeEnum 全局用户类型
      */
     List<SysSocialUserDO> getAllSocialUserList(Integer type, String unionId, UserTypeEnum userTypeEnum);
 
@@ -58,6 +58,7 @@ public interface SysSocialService {
      *
      * @param userId 用户编号
      * @return 社交用户列表
+     * @param userTypeEnum 全局用户类型
      */
     List<SysSocialUserDO> getSocialUserList(Long userId, UserTypeEnum userTypeEnum);
 
@@ -67,6 +68,7 @@ public interface SysSocialService {
      * @param userId 用户编号
      * @param type 社交平台的类型 {@link SysSocialTypeEnum}
      * @param authUser 授权用户
+     * @param userTypeEnum 全局用户类型
      */
     void bindSocialUser(Long userId, Integer type, AuthUser authUser, UserTypeEnum userTypeEnum);
 
@@ -76,8 +78,8 @@ public interface SysSocialService {
      * @param userId 用户编号
      * @param type 社交平台的类型 {@link SysSocialTypeEnum}
      * @param unionId 社交平台的 unionId
+     * @param userTypeEnum 全局用户类型
      */
-    void unbindSocialUser(Long userId, Integer type, String unionId,UserTypeEnum userTypeEnum);
-    // TODO @timfruit:逗号后面要有空格;缺少了 @userTypeEnum 的注释,都补充下哈。
+    void unbindSocialUser(Long userId, Integer type, String unionId, UserTypeEnum userTypeEnum);
 
 }

+ 8 - 8
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/social/impl/SysSocialServiceImpl.java

@@ -2,15 +2,15 @@ package cn.iocoder.yudao.coreservice.modules.system.service.social.impl;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
-import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.social.SysSocialUserMapper;
+import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.social.SysSocialUserCoreMapper;
 import cn.iocoder.yudao.coreservice.modules.system.dal.redis.social.SysSocialAuthUserRedisDAO;
 import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
-import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
+import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
+import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory;
 import com.google.common.annotations.VisibleForTesting;
-import com.xkcoding.justauth.AuthRequestFactory;
 import lombok.extern.slf4j.Slf4j;
 import me.zhyd.oauth.model.AuthCallback;
 import me.zhyd.oauth.model.AuthResponse;
@@ -38,21 +38,21 @@ import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString
 @Service
 @Validated
 @Slf4j
-public class SysSocialServiceImpl implements SysSocialService {
+public class SysSocialCoreServiceImpl implements SysSocialCoreService {
 
     @Resource
-    private AuthRequestFactory authRequestFactory;
+    private YudaoAuthRequestFactory yudaoAuthRequestFactory;
 
     @Resource
     private SysSocialAuthUserRedisDAO authSocialUserRedisDAO;
 
     @Resource
-    private SysSocialUserMapper socialUserMapper;
+    private SysSocialUserCoreMapper socialUserMapper;
 
     @Override
     public String getAuthorizeUrl(Integer type, String redirectUri) {
         // 获得对应的 AuthRequest 实现
-        AuthRequest authRequest = authRequestFactory.get(SysSocialTypeEnum.valueOfType(type).getSource());
+        AuthRequest authRequest = yudaoAuthRequestFactory.get(SysSocialTypeEnum.valueOfType(type).getSource());
         // 生成跳转地址
         String authorizeUri = authRequest.authorize(AuthStateUtils.createState());
         return HttpUtils.replaceUrlQuery(authorizeUri, "redirect_uri", redirectUri);
@@ -161,7 +161,7 @@ public class SysSocialServiceImpl implements SysSocialService {
      * @return 授权的用户
      */
     private AuthUser getAuthUser0(Integer type, AuthCallback authCallback) {
-        AuthRequest authRequest = authRequestFactory.get(SysSocialTypeEnum.valueOfType(type).getSource());
+        AuthRequest authRequest = yudaoAuthRequestFactory.get(SysSocialTypeEnum.valueOfType(type).getSource());
         AuthResponse<?> authResponse = authRequest.login(authCallback);
         log.info("[getAuthUser0][请求社交平台 type({}) request({}) response({})]", type, toJsonString(authCallback),
                 toJsonString(authResponse));

+ 9 - 10
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/social/SysSocialServiceTest.java

@@ -1,11 +1,11 @@
-package cn.iocoder.yudao.adminserver.modules.system.service.social;
+package cn.iocoder.yudao.coreservice.modules.system.service.social;
 
-import cn.iocoder.yudao.adminserver.BaseDbAndRedisUnitTest;
+import cn.iocoder.yudao.coreservice.BaseDbAndRedisUnitTest;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
-import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.social.SysSocialUserMapper;
+import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.social.SysSocialUserCoreMapper;
 import cn.iocoder.yudao.coreservice.modules.system.dal.redis.social.SysSocialAuthUserRedisDAO;
 import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
-import cn.iocoder.yudao.coreservice.modules.system.service.social.impl.SysSocialServiceImpl;
+import cn.iocoder.yudao.coreservice.modules.system.service.social.impl.SysSocialCoreServiceImpl;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import com.xkcoding.justauth.AuthRequestFactory;
 import me.zhyd.oauth.model.AuthUser;
@@ -23,20 +23,19 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-// TODO @timfruit:这个单元测试,挪到 yudao-core-service
 /**
- * {@link SysSocialServiceImpl} 的单元测试类
+ * {@link SysSocialCoreServiceImpl} 的单元测试类
  *
  * @author 芋道源码
  */
-@Import({SysSocialServiceImpl.class, SysSocialAuthUserRedisDAO.class})
-public class SysSocialServiceTest extends BaseDbAndRedisUnitTest {
+@Import({SysSocialCoreServiceImpl.class, SysSocialAuthUserRedisDAO.class})
+public class SysSocialCoreServiceTest extends BaseDbAndRedisUnitTest {
 
     @Resource
-    private SysSocialServiceImpl socialService;
+    private SysSocialCoreServiceImpl socialService;
 
     @Resource
-    private SysSocialUserMapper socialUserMapper;
+    private SysSocialUserCoreMapper socialUserMapper;
 
     @MockBean
     private AuthRequestFactory authRequestFactory;

+ 6 - 0
yudao-dependencies/pom.xml

@@ -351,6 +351,12 @@
             </dependency>
 
             <dependency>
+                <groupId>cn.iocoder.boot</groupId>
+                <artifactId>yudao-spring-boot-starter-biz-social</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <dependency>
                 <groupId>org.projectlombok</groupId>
                 <artifactId>lombok</artifactId>
                 <version>${lombok.version}</version>

+ 1 - 0
yudao-framework/pom.xml

@@ -31,6 +31,7 @@
         <module>yudao-spring-boot-starter-biz-pay</module>
         <module>yudao-spring-boot-starter-biz-weixin</module>
         <module>yudao-spring-boot-starter-extension</module>
+        <module>yudao-spring-boot-starter-biz-social</module>
     </modules>
 
     <artifactId>yudao-framework</artifactId>

+ 50 - 0
yudao-framework/yudao-spring-boot-starter-biz-social/pom.xml

@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>cn.iocoder.boot</groupId>
+        <artifactId>yudao-framework</artifactId>
+        <version>${revision}</version>
+    </parent>
+    <packaging>jar</packaging>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>yudao-spring-boot-starter-biz-social</artifactId>
+    <name>${artifactId}</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-common</artifactId>
+        </dependency>
+        <!-- Spring 核心 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+        <!-- Web 相关 -->
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-web</artifactId>
+        </dependency>
+        <!-- spring boot 配置所需依赖 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <!-- 三方云服务相关 -->
+        <dependency>
+            <groupId>com.xkcoding.justauth</groupId>
+            <artifactId>justauth-spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-redis</artifactId>
+        </dependency>
+
+    </dependencies>
+
+
+</project>

+ 29 - 0
yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/config/YudaoSocialAutoConfiguration.java

@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.framework.social.config;
+
+import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory;
+import com.xkcoding.justauth.autoconfigure.JustAuthProperties;
+import lombok.extern.slf4j.Slf4j;
+import me.zhyd.oauth.cache.AuthStateCache;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 社交自动装配类
+ *
+ * @author timfruit
+ * @date 2021-10-30
+ */
+@Slf4j
+@Configuration
+@EnableConfigurationProperties(JustAuthProperties.class)
+public class YudaoSocialAutoConfiguration {
+
+    @Bean
+    @ConditionalOnProperty(prefix = "justauth", value = "enabled", havingValue = "true", matchIfMissing = true)
+    public YudaoAuthRequestFactory yudaoAuthRequestFactory(JustAuthProperties properties, AuthStateCache authStateCache) {
+        return new YudaoAuthRequestFactory(properties, authStateCache);
+    }
+
+}

+ 108 - 0
yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java

@@ -0,0 +1,108 @@
+package cn.iocoder.yudao.framework.social.core;
+
+import cn.hutool.core.util.EnumUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.social.core.enums.AuthExtendSource;
+import cn.iocoder.yudao.framework.social.core.request.AuthWeChatMiniProgramRequest;
+import com.xkcoding.http.config.HttpConfig;
+import com.xkcoding.justauth.AuthRequestFactory;
+import com.xkcoding.justauth.autoconfigure.JustAuthProperties;
+import me.zhyd.oauth.cache.AuthStateCache;
+import me.zhyd.oauth.config.AuthConfig;
+import me.zhyd.oauth.config.AuthSource;
+import me.zhyd.oauth.request.AuthRequest;
+import org.springframework.util.CollectionUtils;
+
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.util.Map;
+
+/**
+ * 第三方授权拓展request工厂类
+ *
+ * @author timfruit
+ * @date 2021-10-31
+ */
+public class YudaoAuthRequestFactory extends AuthRequestFactory {
+    protected JustAuthProperties properties;
+    protected AuthStateCache authStateCache;
+
+    public YudaoAuthRequestFactory(JustAuthProperties properties, AuthStateCache authStateCache) {
+        super(properties, authStateCache);
+        this.properties = properties;
+        this.authStateCache = authStateCache;
+    }
+
+    /**
+     * 返回AuthRequest对象
+     *
+     * @param source {@link AuthSource}
+     * @return {@link AuthRequest}
+     */
+    public AuthRequest get(String source) {
+        //先尝试获取自定义扩展的
+        AuthRequest authRequest = getExtendRequest(source);
+
+        if (authRequest == null) {
+            authRequest = super.get(source);
+        }
+
+        return authRequest;
+    }
+
+
+    protected AuthRequest getExtendRequest(String source) {
+        AuthExtendSource authExtendSource;
+
+        try {
+            authExtendSource = EnumUtil.fromString(AuthExtendSource.class, source.toUpperCase());
+        } catch (IllegalArgumentException e) {
+            // 无自定义匹配
+            return null;
+        }
+
+        // 拓展配置和默认配置齐平,properties放在一起
+        AuthConfig config = properties.getType().get(authExtendSource.name());
+        // 找不到对应关系,直接返回空
+        if (config == null) {
+            return null;
+        }
+
+        // 配置 http config
+        configureHttpConfig(authExtendSource.name(), config, properties.getHttpConfig());
+
+        switch (authExtendSource) {
+            case WECHAT_MINI_PROGRAM:
+                return new AuthWeChatMiniProgramRequest(config, authStateCache);
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * 配置 http 相关的配置
+     *
+     * @param authSource {@link AuthSource}
+     * @param authConfig {@link AuthConfig}
+     */
+    protected void configureHttpConfig(String authSource, AuthConfig authConfig, JustAuthProperties.JustAuthHttpConfig httpConfig) {
+        if (null == httpConfig) {
+            return;
+        }
+        Map<String, JustAuthProperties.JustAuthProxyConfig> proxyConfigMap = httpConfig.getProxy();
+        if (CollectionUtils.isEmpty(proxyConfigMap)) {
+            return;
+        }
+        JustAuthProperties.JustAuthProxyConfig proxyConfig = proxyConfigMap.get(authSource);
+
+        if (null == proxyConfig) {
+            return;
+        }
+
+        authConfig.setHttpConfig(HttpConfig.builder()
+                .timeout(httpConfig.getTimeout())
+                .proxy(new Proxy(Proxy.Type.valueOf(proxyConfig.getType()), new InetSocketAddress(proxyConfig.getHostname(), proxyConfig.getPort())))
+                .build());
+    }
+
+}

+ 1 - 1
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthExtendSource.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.coreservice.modules.system.compent.justauth;
+package cn.iocoder.yudao.framework.social.core.enums;
 
 import me.zhyd.oauth.config.AuthSource;
 

+ 3 - 2
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthExtendToken.java

@@ -1,10 +1,11 @@
-package cn.iocoder.yudao.coreservice.modules.system.compent.justauth;
+package cn.iocoder.yudao.framework.social.core.model;
 
 import lombok.*;
 import me.zhyd.oauth.model.AuthToken;
 
 /**
- * TODO @timfruit:类注释
+ * 授权所需的token 拓展类
+ *
  * @author timfruit
  * @date 2021-10-29
  */

+ 21 - 13
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthWeChatMiniProgramRequest.java

@@ -1,6 +1,9 @@
-package cn.iocoder.yudao.coreservice.modules.system.compent.justauth;
+package cn.iocoder.yudao.framework.social.core.request;
 
-import com.alibaba.fastjson.JSONObject;
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.framework.social.core.enums.AuthExtendSource;
+import cn.iocoder.yudao.framework.social.core.model.AuthExtendToken;
+import lombok.Data;
 import me.zhyd.oauth.cache.AuthStateCache;
 import me.zhyd.oauth.config.AuthConfig;
 import me.zhyd.oauth.exception.AuthException;
@@ -11,9 +14,6 @@ import me.zhyd.oauth.request.AuthDefaultRequest;
 import me.zhyd.oauth.utils.HttpUtils;
 import me.zhyd.oauth.utils.UrlBuilder;
 
-// TODO @timfruit:新建一个 yudao-spring-boot-starter-biz-social 包,把这个拓展拿进去哈。另外,可以思考下。
-// 1. application-local.yaml 的配置里,justauth.extend.enum-class 能否不配置,而是自动配置好
-// 2. application-local.yaml 的配置里,justauth.extend.extend.config.WECHAT_MINI_PROGRAM 有办法和 justauth.type.WECHAT_MP 持平
 /**
  * 微信小程序登陆
  *
@@ -34,14 +34,14 @@ public class AuthWeChatMiniProgramRequest extends AuthDefaultRequest {
     protected AuthToken getAccessToken(AuthCallback authCallback) {
         // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
         String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl(authCallback.getCode()));
-        JSONObject accessTokenObject = JSONObject.parseObject(response); // TODO @timfruit:使用 JsonUtils,项目尽量避免直接使用某个 json 库
+        CodeSessionResponse accessTokenObject = JsonUtils.parseObject(response, CodeSessionResponse.class);
 
         this.checkResponse(accessTokenObject);
 
         AuthExtendToken token = new AuthExtendToken();
-        token.setMiniSessionKey(accessTokenObject.getString("session_key"));
-        token.setOpenId(accessTokenObject.getString("openid"));
-        token.setUnionId(accessTokenObject.getString("unionid"));
+        token.setMiniSessionKey(accessTokenObject.session_key);
+        token.setOpenId(accessTokenObject.openid);
+        token.setUnionId(accessTokenObject.unionid);
         return token;
     }
 
@@ -64,10 +64,9 @@ public class AuthWeChatMiniProgramRequest extends AuthDefaultRequest {
      *
      * @param object 请求响应内容
      */
-    private void checkResponse(JSONObject object) {
-        int code = object.getIntValue("errcode");
-        if(code != 0){ // TODO @timfruit:if (code != 0) { ,注意空格
-            throw new AuthException(object.getIntValue("errcode"), object.getString("errmsg"));
+    private void checkResponse(CodeSessionResponse object) {
+        if (object.errcode != 0) {
+            throw new AuthException(object.errcode, object.errmsg);
         }
     }
 
@@ -87,4 +86,13 @@ public class AuthWeChatMiniProgramRequest extends AuthDefaultRequest {
                 .build();
     }
 
+    @Data
+    private static class CodeSessionResponse {
+        private int errcode;
+        private String errmsg;
+        private String session_key;
+        private String openid;
+        private String unionid;
+    }
+
 }

+ 2 - 0
yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+  cn.iocoder.yudao.framework.social.config.YudaoSocialAutoConfiguration

+ 2 - 2
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.userserver.modules.system.controller.auth;
 
-import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
+import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.*;
@@ -36,7 +36,7 @@ public class SysAuthController {
     @Resource
     private SysSmsCodeService smsCodeService;
     @Resource
-    private SysSocialService socialService;
+    private SysSocialCoreService socialService;
 
 
     @PostMapping("/login")

+ 8 - 8
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/impl/SysAuthServiceImpl.java

@@ -9,7 +9,7 @@ import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginResultEn
 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
-import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
+import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
@@ -64,8 +64,8 @@ public class SysAuthServiceImpl implements SysAuthService {
     @Resource
     private SysUserSessionCoreService userSessionCoreService;
     @Resource
-    private SysSocialService socialService;
-    private static final UserTypeEnum userTypeEnum = UserTypeEnum.MEMBER;
+    private SysSocialCoreService socialService;
+    private static final UserTypeEnum USER_TYPE_ENUM = UserTypeEnum.MEMBER;
 
     @Override
     public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException {
@@ -114,7 +114,7 @@ public class SysAuthServiceImpl implements SysAuthService {
 
         // 如果未绑定 SysSocialUserDO 用户,则无法自动登录,进行报错
         String unionId = socialService.getAuthUserUnionId(authUser);
-        List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, userTypeEnum);
+        List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, USER_TYPE_ENUM);
         if (CollUtil.isEmpty(socialUsers)) {
             throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
         }
@@ -130,7 +130,7 @@ public class SysAuthServiceImpl implements SysAuthService {
         LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
 
         // 绑定社交用户(更新)
-        socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, userTypeEnum);
+        socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, USER_TYPE_ENUM);
 
         // 缓存登录用户到 Redis 中,返回 sessionId 编号
         return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
@@ -147,7 +147,7 @@ public class SysAuthServiceImpl implements SysAuthService {
 //        loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
 
         // 绑定社交用户(新增)
-        socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, userTypeEnum);
+        socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, USER_TYPE_ENUM);
 
         // 缓存登录用户到 Redis 中,返回 sessionId 编号
         return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
@@ -160,7 +160,7 @@ public class SysAuthServiceImpl implements SysAuthService {
         org.springframework.util.Assert.notNull(authUser, "授权用户不为空");
 
         // 绑定社交用户(新增)
-        socialService.bindSocialUser(userId, reqVO.getType(), authUser, userTypeEnum);
+        socialService.bindSocialUser(userId, reqVO.getType(), authUser, USER_TYPE_ENUM);
     }
 
     private LoginUser login0(String username, String password) {
@@ -271,7 +271,7 @@ public class SysAuthServiceImpl implements SysAuthService {
         reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());
         reqDTO.setTraceId(TracerUtils.getTraceId());
         reqDTO.setUserId(userId);
-        reqDTO.setUserType(userTypeEnum.getValue());
+        reqDTO.setUserType(USER_TYPE_ENUM.getValue());
         reqDTO.setUsername(username);
         reqDTO.setUserAgent(ServletUtils.getUserAgent());
         reqDTO.setUserIp(ServletUtils.getClientIP());

+ 7 - 15
yudao-user-server/src/main/resources/application-dev.yaml

@@ -145,24 +145,16 @@ yudao:
 
 justauth:
   enabled: true
-  type: # TODO @timfruit:GITEE、DINGTALK、WECHAT_ENTERPRISE 这个几个,对于用户端是不需要的哈,可以删除噢
-    GITEE: # Gitee
-      client-id: ee61f0374a4c6c404a8717094caa7a410d76950e45ff60348015830c519ba5c1
-      client-secret: 7c044a5671be3b051414db0cf2cec6ad702dd298d2416ba24ceaf608e6fa26f9
-      ignore-check-redirect-uri: true
-    DINGTALK: # 钉钉
-      client-id: dingvrnreaje3yqvzhxg
-      client-secret: i8E6iZyDvZj51JIb0tYsYfVQYOks9Cq1lgryEjFRqC79P3iJcrxEwT6Qk2QvLrLI
-      ignore-check-redirect-uri: true
-    WECHAT_ENTERPRISE: # 企业微信
-      client-id: wwd411c69a39ad2e54
-      client-secret: 1wTb7hYxnpT2TUbIeHGXGo7T0odav1ic10mLdyyATOw
-      agent-id: 1000004
-      ignore-check-redirect-uri: true
-    WECHAT_MP: # 微信公众平台 - H5  https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
+  type:
+    WECHAT_MP: # 微信公众平台 - 移动端 H5 https://www.yuque.com/docs/share/a795bef6-ee8a-494a-8dc4-2ef41927743b?#%20%E3%80%8A%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%8F%B7%E6%B5%8B%E8%AF%95%E3%80%8B
       client-id: wxa5a05b85ac361f96
       client-secret: 247073c7cebb67f27f0e769195c2a57e
       ignore-check-redirect-uri: true
+    WECHAT_MINI_PROGRAM: # 微信小程序 https://www.yuque.com/docs/share/88e3d30a-6830-45fc-8c25-dae485aef3aa?#%20%E3%80%8A%E5%B0%8F%E7%A8%8B%E5%BA%8F%E6%8E%88%E6%9D%83%E7%99%BB%E5%BD%95%E3%80%8B
+      client-id: wx44d047d87e6284d8
+      client-secret: 21c3b7a8a51ee1b8f5cf875848ed4466
+      ignore-check-redirect-uri: true
+      ignore-check-state: true
   cache:
     type: REDIS
     prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE::

+ 7 - 11
yudao-user-server/src/main/resources/application-local.yaml

@@ -165,17 +165,13 @@ justauth:
 #      client-id: wx5b23ba7a5589ecbb # TODO 芋艿:自己的测试,后续可以删除
 #      client-secret: 2a7b3b20c537e52e74afd395eb85f61f
       ignore-check-redirect-uri: true
-  extend:
-    enum-class: cn.iocoder.yudao.coreservice.modules.system.compent.justauth.AuthExtendSource
-    config:
-      WECHAT_MINI_PROGRAM: # 微信小程序 https://www.yuque.com/docs/share/88e3d30a-6830-45fc-8c25-dae485aef3aa?#%20%E3%80%8A%E5%B0%8F%E7%A8%8B%E5%BA%8F%E6%8E%88%E6%9D%83%E7%99%BB%E5%BD%95%E3%80%8B
-        request-class: cn.iocoder.yudao.coreservice.modules.system.compent.justauth.AuthWeChatMiniProgramRequest
-        client-id: wx44d047d87e6284d8
-        client-secret: 21c3b7a8a51ee1b8f5cf875848ed4466
-#        client-id: wx63c280fe3248a3e7  # TODO 芋艿:自己的测试,后续可以删除
-#        client-secret: 6f270509224a7ae1296bbf1c8cb97aed
-        ignore-check-redirect-uri: true
-        ignore-check-state: true
+    WECHAT_MINI_PROGRAM: # 微信小程序 https://www.yuque.com/docs/share/88e3d30a-6830-45fc-8c25-dae485aef3aa?#%20%E3%80%8A%E5%B0%8F%E7%A8%8B%E5%BA%8F%E6%8E%88%E6%9D%83%E7%99%BB%E5%BD%95%E3%80%8B
+      client-id: wx44d047d87e6284d8
+      client-secret: 21c3b7a8a51ee1b8f5cf875848ed4466
+      #        client-id: wx63c280fe3248a3e7  # TODO 芋艿:自己的测试,后续可以删除
+      #        client-secret: 6f270509224a7ae1296bbf1c8cb97aed
+      ignore-check-redirect-uri: true
+      ignore-check-state: true
   cache:
     type: REDIS
     prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE::