Conflicts:
	yudao-core-service/pom.xml
	yudao-dependencies/pom.xml
	yudao-framework/pom.xml
This commit is contained in:
YunaiV 2021-12-15 10:07:21 +08:00
commit a55c0cfca5
32 changed files with 424 additions and 148 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 socialCoreService;
@PostMapping("/login") @PostMapping("/login")
@ApiOperation("使用账号密码登录") @ApiOperation("使用账号密码登录")
@ -102,7 +102,7 @@ public class SysAuthController {
}) })
public CommonResult<String> socialAuthRedirect(@RequestParam("type") Integer type, public CommonResult<String> socialAuthRedirect(@RequestParam("type") Integer type,
@RequestParam("redirectUri") String redirectUri) { @RequestParam("redirectUri") String redirectUri) {
return CommonResult.success(socialService.getAuthorizeUrl(type, redirectUri)); return CommonResult.success(socialCoreService.getAuthorizeUrl(type, redirectUri));
} }
@PostMapping("/social-login") @PostMapping("/social-login")
@ -133,7 +133,7 @@ public class SysAuthController {
@DeleteMapping("/social-unbind") @DeleteMapping("/social-unbind")
@ApiOperation("取消社交绑定") @ApiOperation("取消社交绑定")
public CommonResult<Boolean> socialUnbind(@RequestBody SysAuthSocialUnbindReqVO reqVO) { public CommonResult<Boolean> socialUnbind(@RequestBody SysAuthSocialUnbindReqVO reqVO) {
socialService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId(), UserTypeEnum.ADMIN); socialCoreService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId(), UserTypeEnum.ADMIN);
return CommonResult.success(true); return CommonResult.success(true);
} }

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

@ -19,7 +19,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;
@ -60,6 +60,8 @@ import static java.util.Collections.singleton;
@Slf4j @Slf4j
public class SysAuthServiceImpl implements SysAuthService { public class SysAuthServiceImpl implements SysAuthService {
private static final UserTypeEnum USER_TYPE_ENUM = UserTypeEnum.ADMIN;
@Resource @Resource
@Lazy // 延迟加载因为存在相互依赖的问题 @Lazy // 延迟加载因为存在相互依赖的问题
private AuthenticationManager authenticationManager; private AuthenticationManager authenticationManager;
@ -79,10 +81,8 @@ public class SysAuthServiceImpl implements SysAuthService {
@Resource @Resource
private SysPostService postService; private SysPostService postService;
@Resource @Resource
private SysSocialService socialService; private SysSocialCoreService socialService;
// TODO @timfruit静态枚举类需要都大写例如说 USER_TYPE_ENUM静态变量放在普通变量前面这个实践不错哈
private static final UserTypeEnum userTypeEnum = UserTypeEnum.ADMIN;
@Override @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
@ -216,7 +216,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);
} }
@ -232,7 +232,7 @@ public class SysAuthServiceImpl implements SysAuthService {
LoginUser loginUser = this.buildLoginUser(user); LoginUser loginUser = this.buildLoginUser(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);
@ -248,7 +248,7 @@ public class SysAuthServiceImpl implements SysAuthService {
LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword()); LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
// 绑定社交用户新增 // 绑定社交用户新增
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);
@ -261,7 +261,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
@ -282,7 +282,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

@ -12,7 +12,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;
@ -68,7 +68,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
@MockBean @MockBean
private SysUserSessionCoreService userSessionCoreService; private SysUserSessionCoreService userSessionCoreService;
@MockBean @MockBean
private SysSocialService socialService; private SysSocialCoreService socialService;
@MockBean @MockBean
private SysPostService postService; private SysPostService postService;

View File

@ -101,12 +101,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,10 +2,10 @@ 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;
@ -38,7 +38,7 @@ 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 AuthRequestFactory authRequestFactory;
@ -47,7 +47,7 @@ public class SysSocialServiceImpl implements SysSocialService {
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) {

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

@ -8,3 +8,4 @@ DELETE FROM "sys_user_session";
DELETE FROM "sys_dict_data"; DELETE FROM "sys_dict_data";
DELETE FROM "sys_sms_template"; DELETE FROM "sys_sms_template";
DELETE FROM "sys_sms_log"; DELETE FROM "sys_sms_log";
DELETE FROM "sys_social_user";

View File

@ -177,3 +177,23 @@ CREATE TABLE IF NOT EXISTS `sys_login_log` (
"tenant_id" bigint not null default '0', "tenant_id" bigint not null default '0',
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) COMMENT ='系统访问记录'; ) COMMENT ='系统访问记录';
CREATE TABLE IF NOT EXISTS "sys_social_user" (
"id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"user_id" bigint NOT NULL,
"user_type" tinyint NOT NULL DEFAULT '0',
"type" tinyint NOT NULL,
"openid" varchar(32) NOT NULL,
"token" varchar(256) DEFAULT NULL,
"union_id" varchar(32) NOT NULL,
"raw_token_info" varchar(1024) NOT NULL,
"nickname" varchar(32) NOT NULL,
"avatar" varchar(255) DEFAULT NULL,
"raw_user_info" varchar(1024) NOT NULL,
"creator" varchar(64) DEFAULT '',
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT '社交用户';

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,86 @@
package cn.iocoder.yudao.framework.social.core;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.iocoder.yudao.framework.social.core.enums.AuthExtendSource;
import cn.iocoder.yudao.framework.social.core.request.AuthWeChatMiniProgramRequest;
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 java.lang.reflect.Method;
/**
* 第三方授权拓展 request 工厂类
* 为使得拓展配置 {@link AuthConfig} 和默认配置齐平所以自定义本工厂类
*
* @author timfruit
* @date 2021-10-31
*/
// TODO @timfruit单测
public class YudaoAuthRequestFactory extends AuthRequestFactory {
protected JustAuthProperties properties;
protected AuthStateCache authStateCache;
/**
* 由于父类 configureHttpConfig 方法是 private 修饰所以获取后进行反射调用
*/
private final Method configureHttpConfigMethod = ReflectUtil.getMethod(AuthRequestFactory.class,
"configureHttpConfig", String.class, AuthConfig.class, JustAuthProperties.JustAuthHttpConfig.class);
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
ReflectUtil.invoke(this, configureHttpConfigMethod,
authExtendSource.name(), config, properties.getHttpConfig());
// 获得拓展的 Request
// noinspection SwitchStatementWithTooFewBranches
switch (authExtendSource) {
case WECHAT_MINI_PROGRAM:
return new AuthWeChatMiniProgramRequest(config, authStateCache);
default:
return null;
}
}
}

View File

@ -1,13 +1,21 @@
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;
/**
* 拓展JustAuth各api需要的url 用枚举类分平台类型管理
*
* 默认配置 {@link me.zhyd.oauth.config.AuthDefaultSource}
*
* @author timfruit
*/
public enum AuthExtendSource implements AuthSource { public enum AuthExtendSource implements AuthSource {
/** /**
* 微信小程序授权登录 * 微信小程序授权登录
*/ */
WECHAT_MINI_PROGRAM{ WECHAT_MINI_PROGRAM {
@Override @Override
public String authorize() { public String authorize() {
// https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html // https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
@ -28,6 +36,4 @@ public enum AuthExtendSource implements 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
*/ */
@ -15,7 +16,7 @@ import me.zhyd.oauth.model.AuthToken;
public class AuthExtendToken extends AuthToken { public class AuthExtendToken extends AuthToken {
/** /**
* 微信小程序 会话密钥 * 微信小程序 - 会话密钥
*/ */
private String miniSessionKey; private String miniSessionKey;

View File

@ -1,6 +1,10 @@
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 com.fasterxml.jackson.annotation.JsonProperty;
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 +15,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 +35,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.sessionKey);
token.setOpenId(accessTokenObject.getString("openid")); token.setOpenId(accessTokenObject.openid);
token.setUnionId(accessTokenObject.getString("unionid")); token.setUnionId(accessTokenObject.unionid);
return token; return token;
} }
@ -64,10 +65,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 +87,14 @@ public class AuthWeChatMiniProgramRequest extends AuthDefaultRequest {
.build(); .build();
} }
@Data
private static class CodeSessionResponse {
private int errcode;
private String errmsg;
@JsonProperty("session_key")
private String sessionKey;
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.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
@ -38,7 +38,7 @@ public class SysAuthController {
@Resource @Resource
private SysSmsCodeService smsCodeService; private SysSmsCodeService smsCodeService;
@Resource @Resource
private SysSocialService socialService; private SysSocialCoreService socialService;
@PostMapping("/login") @PostMapping("/login")
@ApiOperation("使用手机 + 密码登录") @ApiOperation("使用手机 + 密码登录")
@ -115,19 +115,6 @@ public class SysAuthController {
return CommonResult.success(socialService.getAuthorizeUrl(type, redirectUri)); return CommonResult.success(socialService.getAuthorizeUrl(type, redirectUri));
} }
// TODO @timfruit这个接口是要删除的么
@GetMapping("/social-login-get")
@ApiOperation("微信公众号授权回调地址输出social-login2的必要参数用于测试使用 code 授权码")
@ResponseBody
@Deprecated
public CommonResult<MbrAuthSocialLoginReqVO> socialLoginGet(HttpServletRequest request,String code,String state) {
// 返回结果
MbrAuthSocialLoginReqVO reqVO = MbrAuthSocialLoginReqVO.builder().state(state).code(code).build();
reqVO.setType(12);
//输出social-login2的必要参数用于测试
System.out.println(JSON.toJSON(reqVO));
return success(reqVO);
}
@PostMapping("/social-login") @PostMapping("/social-login")
@ApiOperation("社交登录,使用 code 授权码") @ApiOperation("社交登录,使用 code 授权码")
@ -136,10 +123,9 @@ public class SysAuthController {
return success(SysAuthLoginRespVO.builder().token(token).build()); return success(SysAuthLoginRespVO.builder().token(token).build());
} }
// TODO @timfruit社交登陆时使用手机验证码来验证哈这块我当时没设计好改改嘿嘿
@PostMapping("/social-login2") @PostMapping("/social-login2")
@ApiOperation("社交登录,使用 code 授权码 + 账号密") @ApiOperation("社交登录,使用 手机号 + 手机验证")
public CommonResult<SysAuthLoginRespVO> socialLogin2(@RequestBody @Valid MbrAuthSocialLogin2ReqVO reqVO) { public CommonResult<SysAuthLoginRespVO> socialLogin2(@RequestBody @Valid MbrAuthSocialLogin2ReqVO reqVO) {
String token = authService.socialLogin2(reqVO, getClientIP(), getUserAgent()); String token = authService.socialLogin2(reqVO, getClientIP(), getUserAgent());
return success(SysAuthLoginRespVO.builder().token(token).build()); return success(SysAuthLoginRespVO.builder().token(token).build());

View File

@ -34,15 +34,16 @@ public class MbrAuthSocialLogin2ReqVO {
@NotEmpty(message = "state 不能为空") @NotEmpty(message = "state 不能为空")
private String state; private String state;
@ApiModelProperty(value = "账号", required = true, example = "yudaoyuanma") @ApiModelProperty(value = "手机号", required = true, example = "15119100000")
@NotEmpty(message = "登录账号不能为空") @NotEmpty(message = "手机号不能为空")
@Length(min = 4, max = 16, message = "账号长度为 4-16 位") @Length(min = 11, max = 11, message = "手机号是11位数字")
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母") private String mobile;
private String username;
@ApiModelProperty(value = "手机验证码", required = true, example = "1024")
@NotEmpty(message = "手机验证码不能为空")
@Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位")
@Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
private String smsCode;
@ApiModelProperty(value = "密码", required = true, example = "buzhidao")
@NotEmpty(message = "密码不能为空")
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
private String password;
} }

View File

@ -46,7 +46,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService {
String socialLogin(@Valid MbrAuthSocialLoginReqVO reqVO, String userIp, String userAgent); String socialLogin(@Valid MbrAuthSocialLoginReqVO reqVO, String userIp, String userAgent);
/** /**
* 社交登录使用 code 授权码 + 账号密 * 社交登录使用 手机号 + 手机验证
* *
* @param reqVO 登录信息 * @param reqVO 登录信息
* @param userIp 用户 IP * @param userIp 用户 IP

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;
@ -57,6 +57,8 @@ import static cn.iocoder.yudao.userserver.modules.system.enums.SysErrorCodeConst
@Slf4j @Slf4j
public class SysAuthServiceImpl implements SysAuthService { public class SysAuthServiceImpl implements SysAuthService {
private static final UserTypeEnum USER_TYPE_ENUM = UserTypeEnum.MEMBER;
@Resource @Resource
@Lazy // 延迟加载因为存在相互依赖的问题 @Lazy // 延迟加载因为存在相互依赖的问题
private AuthenticationManager authenticationManager; private AuthenticationManager authenticationManager;
@ -70,7 +72,8 @@ public class SysAuthServiceImpl implements SysAuthService {
@Resource @Resource
private SysUserSessionCoreService userSessionCoreService; private SysUserSessionCoreService userSessionCoreService;
@Resource @Resource
private SysSocialService socialService; private SysSocialCoreService socialService;
@Resource @Resource
private StringRedisTemplate stringRedisTemplate; private StringRedisTemplate stringRedisTemplate;
@Resource @Resource
@ -127,7 +130,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);
} }
@ -143,7 +146,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);
@ -151,19 +154,21 @@ public class SysAuthServiceImpl implements SysAuthService {
@Override @Override
public String socialLogin2(MbrAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent) { public String socialLogin2(MbrAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent) {
// 使用 code 授权码进行登录
AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState()); AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState());
org.springframework.util.Assert.notNull(authUser, "授权用户不为空"); org.springframework.util.Assert.notNull(authUser, "授权用户不为空");
// 使用账号密码进行登录 // 使用手机号手机验证码登录
LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword()); SysAuthSmsLoginReqVO loginReqVO = SysAuthSmsLoginReqVO
// loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表 .builder()
.mobile(reqVO.getMobile())
.code(reqVO.getSmsCode())
.build();
String sessionId = this.smsLogin(loginReqVO, userIp, userAgent);
LoginUser loginUser = userSessionCoreService.getLoginUser(sessionId);
// 绑定社交用户新增 // 绑定社交用户新增
socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, userTypeEnum); socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, USER_TYPE_ENUM);
return sessionId;
// 缓存登录用户到 Redis 返回 sessionId 编号
return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
} }
@Override @Override
@ -173,7 +178,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) {
@ -347,7 +352,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(getClientIP()); reqDTO.setUserIp(getClientIP());

View File

@ -150,24 +150,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

@ -170,17 +170,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::

View File

@ -0,0 +1,13 @@
## 微信公众号
参考文章https://www.yuque.com/docs/share/0e2966dd-89f8-4b69-980d-b876168725df
① 访问 social-login.html 选择【微信公众号】
② 微信公众号授权完成后,跳转回 social-login2.html输入手机号 + 密码,进行绑定
## 微信小程序
参考文章https://www.yuque.com/docs/share/88e3d30a-6830-45fc-8c25-dae485aef3aa
① 暂时使用 mini-program-test 项目

View File

@ -13,14 +13,16 @@
</div> </div>
</body> </body>
<script> <script>
let server = 'http://127.0.0.1:28080'; // let server = 'http://127.0.0.1:28080';
let server = 'http://192.168.1.2:28080';
// 微信公众号 // 微信公众号
$( "#wx_pub").on( "click", function() { $( "#wx_pub").on( "click", function() {
// 获得授权链接 // 获得授权链接
$.ajax({ $.ajax({
url: server + "/api/social-auth-redirect?type=31&redirectUri=" + url: server + "/api/social-auth-redirect?type=31&redirectUri=" +
encodeURIComponent(server + '/api/social-login-get'), encodeURIComponent(server + '/static/social-login2.html'), //重定向地址
method: 'GET', method: 'GET',
success: function( result ) { success: function( result ) {
if (result.code !== 0) { if (result.code !== 0) {

View File

@ -0,0 +1,87 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
<title>社交登陆测试页</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
</head>
<body>
<div>点击如下按钮,授权登录</div>
<div>
手机号<input id="mobile" value="15601691300"><br>
手机验证码<input id="smsCode">
<button id="send_sms_code">发送手机验证码</button>
<br>
<button id="wx_pub">微信公众号授权登录</button>
</div>
</body>
<script>
// let server = 'http://127.0.0.1:28080';
let server = 'http://192.168.1.2:28080';
let type = 31; //登录类型 微信公众号
// 微信公众号
$("#wx_pub").on("click", function () {
let code = getUrlParam("code"); // 访问授权连接后会回调本页面地址参数在本页面url后面
let state = getUrlParam("state");
console.log("获取code: " + code + ", state: " + state)
let data = {
'mobile': $('#mobile').val(),
'smsCode': $('#smsCode').val(),
'code': code,
'state': state,
'type': type
}
// 调用授权登录接口
$.ajax({
url: server + "/api/social-login2",
method: 'POST',
data: JSON.stringify(data),
contentType: "application/json;charset=utf-8",
dataType: "json",
success: function( result ) {
if (result.code !== 0) {
alert('调用授权登录接口失败,原因:' + result.msg)
return;
}
alert("授权登录成功, token: "+result.data.token)
}
})
});
// 发送手机验证码
$("#send_sms_code").on("click", function () {
let data = {
'mobile': $('#mobile').val(),
'scene': 1 // 手机号登陆 类型
}
$.ajax({
url: server + "/api/send-sms-code",
method: 'POST',
data: JSON.stringify(data),
contentType: "application/json;charset=utf-8",
dataType: "json",
success: function (result) {
if (result.code !== 0) {
alert('发送手机验证码失败,原因:' + result.msg)
return;
}
alert("发送成功, 请查看日志");
}
})
})
//获取url中的参数
function getUrlParam(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
var r = window.location.search.substr(1).match(reg); //匹配目标参数
if (r != null) return unescape(r[2]);
return null; //返回参数值
}
</script>
</html>

View File

@ -4,6 +4,7 @@ import cn.iocoder.yudao.userserver.modules.member.controller.user.SysUserProfile
import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService; import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService; import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
import org.mockito.Mock; import org.mockito.Mock;
@ -46,6 +47,7 @@ public class SysUserProfileControllerTest {
} }
@Test @Test
@Ignore
public void testUpdateMobile_success() throws Exception { public void testUpdateMobile_success() throws Exception {
//模拟接口调用 //模拟接口调用
this.mockMvc.perform(post("/system/user/profile/update-mobile") this.mockMvc.perform(post("/system/user/profile/update-mobile")

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.userserver.modules.system.controller; package cn.iocoder.yudao.userserver.modules.system.controller;
import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService; import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
import cn.iocoder.yudao.userserver.modules.system.controller.auth.SysAuthController; import cn.iocoder.yudao.userserver.modules.system.controller.auth.SysAuthController;
import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService; import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService;
import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService; import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
@ -14,9 +14,7 @@ import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.springframework.http.HttpHeaders.AUTHORIZATION; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/** /**
@ -36,8 +34,7 @@ public class SysAuthControllerTest {
@Mock @Mock
private SysSmsCodeService smsCodeService; private SysSmsCodeService smsCodeService;
@Mock @Mock
private SysSocialService socialService; private SysSocialCoreService socialService;
@Before @Before
public void setup() { public void setup() {
@ -50,26 +47,22 @@ public class SysAuthControllerTest {
@Test @Test
public void testResetPassword_success() throws Exception { public void testResetPassword_success() throws Exception {
//模拟接口调用 // 模拟接口调用
this.mockMvc.perform(post("/reset-password") this.mockMvc.perform(post("/reset-password")
.contentType(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON)
.content("{\"password\":\"1123\",\"code\":\"123456\"}}")) .content("{\"password\":\"1123\",\"code\":\"123456\"}}"))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andDo(MockMvcResultHandlers.print()); .andDo(MockMvcResultHandlers.print());
} }
@Test @Test
public void testUpdatePassword_success() throws Exception { public void testUpdatePassword_success() throws Exception {
//模拟接口调用 // 模拟接口调用
this.mockMvc.perform(post("/update-password") this.mockMvc.perform(post("/update-password")
.contentType(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON)
.content("{\"password\":\"1123\",\"code\":\"123456\",\"oldPassword\":\"1123\"}}")) .content("{\"password\":\"1123\",\"code\":\"123456\",\"oldPassword\":\"1123\"}}"))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andDo(MockMvcResultHandlers.print()); .andDo(MockMvcResultHandlers.print());
} }
} }

View File

@ -3,7 +3,7 @@ package cn.iocoder.yudao.userserver.modules.system.service;
import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO; import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
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.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
@ -53,7 +53,7 @@ public class SysAuthServiceTest extends BaseDbAndRedisUnitTest {
@MockBean @MockBean
private SysUserSessionCoreService userSessionCoreService; private SysUserSessionCoreService userSessionCoreService;
@MockBean @MockBean
private SysSocialService socialService; private SysSocialCoreService socialService;
@Resource @Resource
private StringRedisTemplate stringRedisTemplate; private StringRedisTemplate stringRedisTemplate;
@MockBean @MockBean

View File

@ -14,6 +14,7 @@ CREATE TABLE IF NOT EXISTS "mbr_user" (
"updater" varchar(64) NULL DEFAULT '' COMMENT '更新者', "updater" varchar(64) NULL DEFAULT '' COMMENT '更新者',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
"deleted" bit(1) NOT NULL DEFAULT '0' COMMENT '是否删除', "deleted" bit(1) NOT NULL DEFAULT '0' COMMENT '是否删除',
"tenant_id" bigint not null default '0',
PRIMARY KEY ("id") PRIMARY KEY ("id")
) COMMENT '会员表'; ) COMMENT '会员表';