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

This commit is contained in:
timfruit 2021-10-31 13:09:55 +08:00
parent 8dbd6143bf
commit 8aa45406fd
23 changed files with 288 additions and 99 deletions

View File

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

View File

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

View File

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

View File

@ -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.dal.dataobject.user.SysUserDO;
import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService; 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.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.coreservice.modules.system.service.user.SysUserCoreService;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.framework.security.core.LoginUser;
@ -66,7 +66,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
@MockBean @MockBean
private SysUserSessionCoreService userSessionCoreService; private SysUserSessionCoreService userSessionCoreService;
@MockBean @MockBean
private SysSocialService socialService; private SysSocialCoreService socialService;
@Test @Test
public void testLoadUserByUsername_success() { public void testLoadUserByUsername_success() {

View File

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

View File

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

View File

@ -10,9 +10,8 @@ import javax.annotation.Resource;
import static cn.iocoder.yudao.coreservice.modules.system.dal.redis.SysRedisKeyCoreConstants.SOCIAL_AUTH_USER; 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 芋道源码 * @author 芋道源码
*/ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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; import me.zhyd.oauth.config.AuthSource;

View File

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

View File

@ -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.cache.AuthStateCache;
import me.zhyd.oauth.config.AuthConfig; import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.exception.AuthException; 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.HttpUtils;
import me.zhyd.oauth.utils.UrlBuilder; 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) { protected AuthToken getAccessToken(AuthCallback authCallback) {
// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html // 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())); 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); this.checkResponse(accessTokenObject);
AuthExtendToken token = new AuthExtendToken(); AuthExtendToken token = new AuthExtendToken();
token.setMiniSessionKey(accessTokenObject.getString("session_key")); token.setMiniSessionKey(accessTokenObject.session_key);
token.setOpenId(accessTokenObject.getString("openid")); token.setOpenId(accessTokenObject.openid);
token.setUnionId(accessTokenObject.getString("unionid")); token.setUnionId(accessTokenObject.unionid);
return token; return token;
} }
@ -64,10 +64,9 @@ public class AuthWeChatMiniProgramRequest extends AuthDefaultRequest {
* *
* @param object 请求响应内容 * @param object 请求响应内容
*/ */
private void checkResponse(JSONObject object) { private void checkResponse(CodeSessionResponse object) {
int code = object.getIntValue("errcode"); if (object.errcode != 0) {
if(code != 0){ // TODO @timfruitif (code != 0) { 注意空格 throw new AuthException(object.errcode, object.errmsg);
throw new AuthException(object.getIntValue("errcode"), object.getString("errmsg"));
} }
} }
@ -87,4 +86,13 @@ public class AuthWeChatMiniProgramRequest extends AuthDefaultRequest {
.build(); .build();
} }
@Data
private static class CodeSessionResponse {
private int errcode;
private String errmsg;
private String session_key;
private String openid;
private String unionid;
}
} }

View File

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

View File

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

View File

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

View File

@ -145,24 +145,16 @@ yudao:
justauth: justauth:
enabled: true enabled: true
type: # TODO @timfruitGITEE、DINGTALK、WECHAT_ENTERPRISE 这个几个,对于用户端是不需要的哈,可以删除噢 type:
GITEE: # Gitee 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: 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
client-id: wxa5a05b85ac361f96 client-id: wxa5a05b85ac361f96
client-secret: 247073c7cebb67f27f0e769195c2a57e client-secret: 247073c7cebb67f27f0e769195c2a57e
ignore-check-redirect-uri: true 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: cache:
type: REDIS type: REDIS
prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE:: prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE::

View File

@ -165,17 +165,13 @@ justauth:
# client-id: wx5b23ba7a5589ecbb # TODO 芋艿:自己的测试,后续可以删除 # client-id: wx5b23ba7a5589ecbb # TODO 芋艿:自己的测试,后续可以删除
# client-secret: 2a7b3b20c537e52e74afd395eb85f61f # client-secret: 2a7b3b20c537e52e74afd395eb85f61f
ignore-check-redirect-uri: true ignore-check-redirect-uri: true
extend: 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
enum-class: cn.iocoder.yudao.coreservice.modules.system.compent.justauth.AuthExtendSource client-id: wx44d047d87e6284d8
config: client-secret: 21c3b7a8a51ee1b8f5cf875848ed4466
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: wx63c280fe3248a3e7 # TODO 芋艿:自己的测试,后续可以删除
request-class: cn.iocoder.yudao.coreservice.modules.system.compent.justauth.AuthWeChatMiniProgramRequest # client-secret: 6f270509224a7ae1296bbf1c8cb97aed
client-id: wx44d047d87e6284d8 ignore-check-redirect-uri: true
client-secret: 21c3b7a8a51ee1b8f5cf875848ed4466 ignore-check-state: true
# client-id: wx63c280fe3248a3e7 # TODO 芋艿:自己的测试,后续可以删除
# client-secret: 6f270509224a7ae1296bbf1c8cb97aed
ignore-check-redirect-uri: true
ignore-check-state: true
cache: cache:
type: REDIS type: REDIS
prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE:: prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE::