mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 18:28:43 +08:00 
			
		
		
		
	完整完成钉钉的三方接入
This commit is contained in:
		| @@ -1,6 +1,5 @@ | ||||
| package cn.iocoder.yudao.adminserver.modules.system.controller.auth; | ||||
|  | ||||
| import cn.hutool.json.JSONUtil; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.*; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysAuthConvert; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; | ||||
| @@ -23,9 +22,6 @@ import io.swagger.annotations.ApiImplicitParam; | ||||
| import io.swagger.annotations.ApiImplicitParams; | ||||
| import io.swagger.annotations.ApiOperation; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import me.zhyd.oauth.model.AuthCallback; | ||||
| import me.zhyd.oauth.model.AuthResponse; | ||||
| import me.zhyd.oauth.model.AuthUser; | ||||
| import me.zhyd.oauth.request.AuthRequest; | ||||
| import me.zhyd.oauth.utils.AuthStateUtils; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| @@ -100,16 +96,16 @@ public class SysAuthController { | ||||
|         return success(SysAuthConvert.INSTANCE.buildMenuTree(menuList)); | ||||
|     } | ||||
|  | ||||
|     // ========== 三方登陆相关 ========== | ||||
|     // ========== 社交登陆相关 ========== | ||||
|  | ||||
|     @GetMapping("/third-login-redirect") | ||||
|     @ApiOperation("三方登陆的跳转") | ||||
|     @GetMapping("/social-login-redirect") | ||||
|     @ApiOperation("社交登陆的跳转") | ||||
|     @ApiImplicitParams({ | ||||
|             @ApiImplicitParam(name = "type", value = "三方类型", required = true, dataTypeClass = Integer.class), | ||||
|             @ApiImplicitParam(name = "redirectUri", value = "回调路径", dataTypeClass = String.class) | ||||
|     }) | ||||
|     public CommonResult<String> thirdLoginRedirect(@RequestParam("type") Integer type, | ||||
|                                                    @RequestParam("redirectUri") String redirectUri) { | ||||
|     public CommonResult<String> socialLoginRedirect(@RequestParam("type") Integer type, | ||||
|                                                     @RequestParam("redirectUri") String redirectUri) { | ||||
|         // 获得对应的 AuthRequest 实现 | ||||
|         AuthRequest authRequest = authRequestFactory.get(SysUserSocialTypeEnum.valueOfType(type).getSource()); | ||||
|         // 生成跳转地址 | ||||
| @@ -118,20 +114,30 @@ public class SysAuthController { | ||||
|         return CommonResult.success(authorizeUri); | ||||
|     } | ||||
|  | ||||
|     @PostMapping("/third-login") | ||||
|     @ApiOperation("三方登陆,使用 code 授权码") | ||||
|     @PostMapping("/social-login") | ||||
|     @ApiOperation("社交登陆,使用 code 授权码") | ||||
|     @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 | ||||
|     public CommonResult<SysAuthLoginRespVO> thirdLogin(@RequestBody @Valid SysAuthThirdLoginReqVO reqVO) { | ||||
|         String token = authService.thirdLogin(reqVO, getClientIP(), getUserAgent()); | ||||
|         return null; | ||||
|     public CommonResult<SysAuthLoginRespVO> socialLogin(@RequestBody @Valid SysAuthSocialLoginReqVO reqVO) { | ||||
|         String token = authService.socialLogin(reqVO, getClientIP(), getUserAgent()); | ||||
|         // 返回结果 | ||||
|         return success(SysAuthLoginRespVO.builder().token(token).build()); | ||||
|     } | ||||
|  | ||||
|     @RequestMapping("/{type}/callback") | ||||
|     public AuthResponse login(@PathVariable String type, AuthCallback callback) { | ||||
|         AuthRequest authRequest = authRequestFactory.get(type); | ||||
|         AuthResponse<AuthUser> response = authRequest.login(callback); | ||||
|         log.info("【response】= {}", JSONUtil.toJsonStr(response)); | ||||
|         return response; | ||||
|     @PostMapping("/social-login2") | ||||
|     @ApiOperation("社交登陆,使用 code 授权码 + 账号密码") | ||||
|     @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 | ||||
|     public CommonResult<SysAuthLoginRespVO> socialLogin2(@RequestBody @Valid SysAuthSocialLogin2ReqVO reqVO) { | ||||
|         String token = authService.socialLogin2(reqVO, getClientIP(), getUserAgent()); | ||||
|         // 返回结果 | ||||
|         return success(SysAuthLoginRespVO.builder().token(token).build()); | ||||
|     } | ||||
|  | ||||
| //    @RequestMapping("/{type}/callback") | ||||
| //    public AuthResponse login(@PathVariable String type, AuthCallback callback) { | ||||
| //        AuthRequest authRequest = authRequestFactory.get(type); | ||||
| //        AuthResponse<AuthUser> response = authRequest.login(callback); | ||||
| //        log.info("【response】= {}", JSONUtil.toJsonStr(response)); | ||||
| //        return response; | ||||
| //    } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,48 @@ | ||||
| package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth; | ||||
|  | ||||
| import cn.iocoder.yudao.adminserver.modules.system.enums.user.SysUserSocialTypeEnum; | ||||
| import cn.iocoder.yudao.framework.common.validation.InEnum; | ||||
| import io.swagger.annotations.ApiModel; | ||||
| import io.swagger.annotations.ApiModelProperty; | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Builder; | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
| import org.hibernate.validator.constraints.Length; | ||||
|  | ||||
| import javax.validation.constraints.NotEmpty; | ||||
| import javax.validation.constraints.NotNull; | ||||
| import javax.validation.constraints.Pattern; | ||||
|  | ||||
| @ApiModel("社交登陆 Request VO,使用 code 授权码 + 账号密码") | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| @AllArgsConstructor | ||||
| @Builder | ||||
| public class SysAuthSocialLogin2ReqVO { | ||||
|  | ||||
|     @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值") | ||||
|     @InEnum(SysUserSocialTypeEnum.class) | ||||
|     @NotNull(message = "社交平台的类型不能为空") | ||||
|     private Integer type; | ||||
|  | ||||
|     @ApiModelProperty(value = "授权码", required = true, example = "1024") | ||||
|     @NotEmpty(message = "授权码不能为空") | ||||
|     private String code; | ||||
|  | ||||
|     @ApiModelProperty(value = "state", required = true, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62") | ||||
|     @NotEmpty(message = "state 不能为空") | ||||
|     private String state; | ||||
|  | ||||
|     @ApiModelProperty(value = "账号", required = true, example = "yudaoyuanma") | ||||
|     @NotEmpty(message = "登陆账号不能为空") | ||||
|     @Length(min = 4, max = 16, message = "账号长度为 4-16 位") | ||||
|     @Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母") | ||||
|     private String username; | ||||
|  | ||||
|     @ApiModelProperty(value = "密码", required = true, example = "buzhidao") | ||||
|     @NotEmpty(message = "密码不能为空") | ||||
|     @Length(min = 4, max = 16, message = "密码长度为 4-16 位") | ||||
|     private String password; | ||||
|  | ||||
| } | ||||
| @@ -14,16 +14,16 @@ import javax.validation.constraints.NotEmpty; | ||||
| import javax.validation.constraints.NotNull; | ||||
| import javax.validation.constraints.Pattern; | ||||
| 
 | ||||
| @ApiModel("三方登陆 Request VO,使用 code 授权码") | ||||
| @ApiModel("社交登陆 Request VO,使用 code 授权码") | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| @AllArgsConstructor | ||||
| @Builder | ||||
| public class SysAuthThirdLoginReqVO { | ||||
| public class SysAuthSocialLoginReqVO { | ||||
| 
 | ||||
|     @ApiModelProperty(value = "三方平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值") | ||||
|     @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值") | ||||
|     @InEnum(SysUserSocialTypeEnum.class) | ||||
|     @NotNull(message = "三方平台的类型不能为空") | ||||
|     @NotNull(message = "社交平台的类型不能为空") | ||||
|     private Integer type; | ||||
| 
 | ||||
|     @ApiModelProperty(value = "授权码", required = true, example = "1024") | ||||
| @@ -2,10 +2,10 @@ package cn.iocoder.yudao.adminserver.modules.system.convert.auth; | ||||
|  | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthMenuRespVO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthPermissionInfoRespVO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthThirdLoginReqVO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLogin2ReqVO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLoginReqVO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserCreateReqVO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO; | ||||
| @@ -13,10 +13,8 @@ import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuIdEnum; | ||||
| import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||||
| import cn.iocoder.yudao.framework.security.core.LoginUser; | ||||
| import me.zhyd.oauth.model.AuthCallback; | ||||
| import me.zhyd.oauth.model.AuthUser; | ||||
| import org.mapstruct.Mapper; | ||||
| import org.mapstruct.Mapping; | ||||
| import org.mapstruct.Mappings; | ||||
| import org.mapstruct.factory.Mappers; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| @@ -45,7 +43,9 @@ public interface SysAuthConvert { | ||||
|  | ||||
|     LoginUser convert(SysUserProfileUpdatePasswordReqVO reqVO); | ||||
|  | ||||
|     AuthCallback convert(SysAuthThirdLoginReqVO bean); | ||||
|     AuthCallback convert(SysAuthSocialLoginReqVO bean); | ||||
|  | ||||
|     AuthCallback convert(SysAuthSocialLogin2ReqVO bean); | ||||
|  | ||||
|     /** | ||||
|      * 将菜单列表,构建成菜单树 | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user; | ||||
| 
 | ||||
| import cn.iocoder.yudao.adminserver.modules.system.enums.user.SysUserSocialTypeEnum; | ||||
| import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||||
| import com.baomidou.mybatisplus.annotation.TableId; | ||||
| @@ -8,18 +7,18 @@ import com.baomidou.mybatisplus.annotation.TableName; | ||||
| import lombok.*; | ||||
| 
 | ||||
| /** | ||||
|  * 三方登陆信息 | ||||
|  * 通过 {@link SysUserSocialDO#getUserId()} 关联到对应的 {@link SysUserDO} | ||||
|  * 社交用户 | ||||
|  * 通过 {@link SysSocialUserDO#getUserId()} 关联到对应的 {@link SysUserDO} | ||||
|  * | ||||
|  * @author weir | ||||
|  */ | ||||
| @TableName(value = "sys_user_social", autoResultMap = true) | ||||
| @TableName(value = "sys_social_user", autoResultMap = true) | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @Builder | ||||
| @NoArgsConstructor | ||||
| @AllArgsConstructor | ||||
| public class SysUserSocialDO extends BaseDO { | ||||
| public class SysSocialUserDO extends BaseDO { | ||||
| 
 | ||||
|     /** | ||||
|      * 自增主键 | ||||
| @@ -27,7 +26,7 @@ public class SysUserSocialDO extends BaseDO { | ||||
|     @TableId | ||||
|     private Long id; | ||||
|     /** | ||||
|      * 用户编号 | ||||
|      * 关联的用户编号 | ||||
|      */ | ||||
|     private Long userId; | ||||
|     /** | ||||
| @@ -38,20 +37,22 @@ public class SysUserSocialDO extends BaseDO { | ||||
|     private Integer userType; | ||||
| 
 | ||||
|     /** | ||||
|      * 三方平台的类型 | ||||
|      * 社交平台的类型 | ||||
|      * | ||||
|      * 枚举 {@link UserTypeEnum} | ||||
|      */ | ||||
|     private SysUserSocialTypeEnum type; | ||||
|     private Integer type; | ||||
| 
 | ||||
|     /** | ||||
|      * 三方 openid | ||||
|      * 社交 openid | ||||
|      */ | ||||
|     private String openid; | ||||
|     /** | ||||
|      * 三方 token | ||||
|      * 社交 token | ||||
|      */ | ||||
|     private String token; | ||||
|     /** | ||||
|      * 三方的全局编号 | ||||
|      * 社交的全局编号 | ||||
|      * | ||||
|      * 例如说,微信平台的 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/union-id.html | ||||
|      * 如果没有 unionId 的平台,直接使用 openid 作为该字段的值 | ||||
| @@ -1,11 +1,11 @@ | ||||
| package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social; | ||||
|  | ||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserSocialDO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysSocialUserDO; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
|  | ||||
| @Mapper | ||||
| public interface SysSysUserSocialMapper extends BaseMapperX<SysUserSocialDO> { | ||||
| public interface SysSysUserSocialMapper extends BaseMapperX<SysSocialUserDO> { | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,11 +1,11 @@ | ||||
| package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social; | ||||
|  | ||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserSocialDO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysSocialUserDO; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
|  | ||||
| @Mapper | ||||
| public interface SysUserSocialMapper extends BaseMapperX<SysUserSocialDO> { | ||||
| public interface SysUserSocialMapper extends BaseMapperX<SysSocialUserDO> { | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,18 @@ | ||||
| package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.user; | ||||
|  | ||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysSocialUserDO; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| @Mapper | ||||
| public interface SysSocialUserMapper extends BaseMapperX<SysSocialUserDO> { | ||||
|  | ||||
|     default List<SysSocialUserDO> selectListByTypeAndUnionId(Integer userType, Integer type, String unionId) { | ||||
|         return selectList(new QueryWrapper<SysSocialUserDO>().eq("user_type", userType) | ||||
|                 .eq("type", type).eq("union_id", unionId)); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -2,6 +2,9 @@ package cn.iocoder.yudao.adminserver.modules.system.dal.redis; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; | ||||
| import cn.iocoder.yudao.framework.security.core.LoginUser; | ||||
| import me.zhyd.oauth.model.AuthUser; | ||||
|  | ||||
| import java.time.Duration; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING; | ||||
|  | ||||
| @@ -20,4 +23,8 @@ public interface SysRedisKeyConstants { | ||||
|             "captcha_code:%s", // 参数为 uuid | ||||
|             STRING, String.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); | ||||
|  | ||||
|     RedisKeyDefine AUTH_SOCIAL_USER = new RedisKeyDefine("认证的三方用户", | ||||
|             "auth_social_user:%d:%s", // 参数为 type,code | ||||
|             STRING, AuthUser.class, Duration.ofDays(1)); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,38 @@ | ||||
| package cn.iocoder.yudao.adminserver.modules.system.dal.redis.auth; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||||
| import me.zhyd.oauth.model.AuthCallback; | ||||
| import me.zhyd.oauth.model.AuthUser; | ||||
| import org.springframework.data.redis.core.StringRedisTemplate; | ||||
| import org.springframework.stereotype.Repository; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
|  | ||||
| import static cn.iocoder.yudao.adminserver.modules.system.dal.redis.SysRedisKeyConstants.AUTH_SOCIAL_USER; | ||||
|  | ||||
| /** | ||||
|  * 社交 {@link me.zhyd.oauth.model.AuthUser} 的 RedisDAO | ||||
|  * | ||||
|  * @author 芋道源码 | ||||
|  */ | ||||
| @Repository | ||||
| public class SysAuthSocialUserRedisDAO { | ||||
|  | ||||
|     @Resource | ||||
|     private StringRedisTemplate stringRedisTemplate; | ||||
|  | ||||
|     public AuthUser get(Integer type, AuthCallback authCallback) { | ||||
|         String redisKey = formatKey(type, authCallback.getCode()); | ||||
|         return JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(redisKey), AuthUser.class); | ||||
|     } | ||||
|  | ||||
|     public void set(Integer type, AuthCallback authCallback, AuthUser authUser) { | ||||
|         String redisKey = formatKey(type, authCallback.getCode()); | ||||
|         stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(authUser), AUTH_SOCIAL_USER.getTimeout()); | ||||
|     } | ||||
|  | ||||
|     private static String formatKey(Integer type, String code) { | ||||
|         return String.format(AUTH_SOCIAL_USER.getKeyTemplate(), type, code); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -22,7 +22,7 @@ public class SysLoginUserRedisDAO { | ||||
|     @Resource | ||||
|     private StringRedisTemplate stringRedisTemplate; | ||||
|     @Resource | ||||
|     private SysUserSessionService sysUserSessionService; | ||||
|     private SysUserSessionService sysUserSessionService; // TODO 芋艿:得看看怎么拿出去 | ||||
|  | ||||
|     public LoginUser get(String sessionId) { | ||||
|         String redisKey = formatKey(sessionId); | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package cn.iocoder.yudao.adminserver.modules.system.enums; | ||||
|  | ||||
| import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.config.ErrorCodeConfiguration; | ||||
| import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||||
|  | ||||
| /** | ||||
| @@ -15,6 +16,8 @@ public interface SysErrorCodeConstants { | ||||
|     ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1002000002, "登录失败"); // 登陆失败的兜底,位置原因 | ||||
|     ErrorCode AUTH_LOGIN_CAPTCHA_NOT_FOUND = new ErrorCode(1002000003, "验证码不存在"); | ||||
|     ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1002000004, "验证码不正确"); | ||||
|     ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1002000005, "未绑定账号,需要进行绑定"); | ||||
|     ErrorCode AUTH_THIRD_OAUTH_FAILURE = new ErrorCode(1002000006, "三方授权失败,原因是:{}"); | ||||
|  | ||||
|     // ========== TOKEN 模块 1002001000 ========== | ||||
|     ErrorCode TOKEN_EXPIRED = new ErrorCode(1002001000, "Token 已经过期"); | ||||
|   | ||||
| @@ -11,6 +11,7 @@ import lombok.Getter; | ||||
| public enum SysLoginLogTypeEnum { | ||||
|  | ||||
|     LOGIN_USERNAME(100), // 使用账号登录 | ||||
|     LOGIN_SOCIAL(101), // 使用社交登陆 | ||||
|  | ||||
|     LOGOUT_SELF(200),  // 自己主动登出 | ||||
|     LOGOUT_TIMEOUT(201), // 超时登出 | ||||
|   | ||||
| @@ -1,17 +1,14 @@ | ||||
| package cn.iocoder.yudao.adminserver.modules.system.enums.user; | ||||
|  | ||||
| import cn.hutool.core.util.ArrayUtil; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.enums.errorcode.SysErrorCodeTypeEnum; | ||||
| import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | ||||
| import com.fasterxml.jackson.annotation.JsonCreator; | ||||
| import jodd.util.ArraysUtil; | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Getter; | ||||
|  | ||||
| import java.util.Arrays; | ||||
|  | ||||
| /** | ||||
|  * 用户的三方平台的类型枚举 | ||||
|  * 用户的社交平台的类型枚举 | ||||
|  * | ||||
|  * @author 芋道源码 | ||||
|  */ | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package cn.iocoder.yudao.adminserver.modules.system.service.auth; | ||||
|  | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthThirdLoginReqVO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLogin2ReqVO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLoginReqVO; | ||||
| import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO; | ||||
|  | ||||
| @@ -24,13 +25,23 @@ public interface SysAuthService extends SecurityAuthFrameworkService { | ||||
|     String login(SysAuthLoginReqVO reqVO, String userIp, String userAgent); | ||||
|  | ||||
|     /** | ||||
|      * 三方登陆用户,使用 code 授权码 | ||||
|      * 社交登陆用户,使用 code 授权码 | ||||
|      * | ||||
|      * @param reqVO 登陆信息 | ||||
|      * @param userIp 用户 IP | ||||
|      * @param userAgent 用户 UA | ||||
|      * @return 身份令牌,使用 JWT 方式 | ||||
|      */ | ||||
|     String thirdLogin(SysAuthThirdLoginReqVO reqVO, String userIp, String userAgent); | ||||
|     String socialLogin(SysAuthSocialLoginReqVO reqVO, String userIp, String userAgent); | ||||
|  | ||||
|     /** | ||||
|      * 社交登陆用户,使用 code 授权码 + 账号密码 | ||||
|      * | ||||
|      * @param reqVO 登陆信息 | ||||
|      * @param userIp 用户 IP | ||||
|      * @param userAgent 用户 UA | ||||
|      * @return 身份令牌,使用 JWT 方式 | ||||
|      */ | ||||
|     String socialLogin2(SysAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,15 @@ | ||||
| package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl; | ||||
|  | ||||
| import cn.hutool.json.JSONUtil; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthThirdLoginReqVO; | ||||
| import cn.hutool.core.collection.CollUtil; | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLogin2ReqVO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLoginReqVO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysSocialUserDO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.user.SysSocialUserMapper; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.redis.auth.SysAuthSocialUserRedisDAO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.enums.user.SysUserSocialTypeEnum; | ||||
| import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||||
| import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||||
| import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; | ||||
| import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||||
| import cn.iocoder.yudao.framework.security.core.LoginUser; | ||||
| @@ -40,6 +46,8 @@ import org.springframework.stereotype.Service; | ||||
| import org.springframework.util.Assert; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
| import java.util.Set; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||||
| @@ -58,6 +66,7 @@ public class SysAuthServiceImpl implements SysAuthService { | ||||
|     @Resource | ||||
|     @Lazy // 延迟加载,因为存在相互依赖的问题 | ||||
|     private AuthenticationManager authenticationManager; | ||||
|  | ||||
|     @Resource | ||||
|     private SysUserService userService; | ||||
|     @Resource | ||||
| @@ -69,6 +78,11 @@ public class SysAuthServiceImpl implements SysAuthService { | ||||
|     @Resource | ||||
|     private SysUserSessionService userSessionService; | ||||
|  | ||||
|     @Resource | ||||
|     private SysAuthSocialUserRedisDAO authSocialUserRedisDAO; | ||||
|     @Resource | ||||
|     private SysSocialUserMapper socialUserMapper; | ||||
|  | ||||
|     @Resource | ||||
|     private AuthRequestFactory authRequestFactory; | ||||
|  | ||||
| @@ -109,24 +123,6 @@ public class SysAuthServiceImpl implements SysAuthService { | ||||
|         return userSessionService.createUserSession(loginUser, userIp, userAgent); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String thirdLogin(SysAuthThirdLoginReqVO reqVO, String userIp, String userAgent) { | ||||
|         // 使用 code 授权码,进行登陆 | ||||
|         AuthRequest authRequest = authRequestFactory.get(SysUserSocialTypeEnum.valueOfType(reqVO.getType()).getSource()); | ||||
|         AuthCallback authCallback = SysAuthConvert.INSTANCE.convert(reqVO); | ||||
|         AuthResponse<?> authResponse = authRequest.login(authCallback); | ||||
|         log.info("[thirdLogin][请求三方平台 type({}) request({}) response({})]", reqVO.getType(), JsonUtils.toJsonString(authCallback), | ||||
|                 JsonUtils.toJsonString(authResponse)); | ||||
|         if (!authResponse.ok()) { | ||||
|             throw new RuntimeException(""); // TODO 芋艿:补全 | ||||
|         } | ||||
|         AuthUser authUser = (AuthUser) authResponse.getData(); | ||||
|  | ||||
|         // 查找到对应的 | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     private void verifyCaptcha(String username, String captchaUUID, String captchaCode) { | ||||
|         String code = captchaService.getCaptchaCode(captchaUUID); | ||||
|         // 验证码不存在 | ||||
| @@ -190,6 +186,124 @@ public class SysAuthServiceImpl implements SysAuthService { | ||||
|         return permissionService.getUserRoleIds(userId, singleton(CommonStatusEnum.ENABLE.getStatus())); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String socialLogin(SysAuthSocialLoginReqVO reqVO, String userIp, String userAgent) { | ||||
|         // 使用 code 授权码,进行登陆 | ||||
|         AuthCallback authCallback = SysAuthConvert.INSTANCE.convert(reqVO); | ||||
|         AuthUser authUser = this.obtainAuthUserFromCache(reqVO.getType(), authCallback); | ||||
|  | ||||
|         // 如果未绑定 SysSocialUserDO 用户,则无法自动登陆,进行报错 | ||||
|         String unionId = getAuthUserUnionId(authUser); | ||||
|         List<SysSocialUserDO> socialUsers = socialUserMapper.selectListByTypeAndUnionId(UserTypeEnum.ADMIN.getValue(), | ||||
|                 reqVO.getType(), unionId); | ||||
|         if (CollUtil.isEmpty(socialUsers)) { | ||||
|             throw exception(AUTH_THIRD_LOGIN_NOT_BIND); | ||||
|         } | ||||
|  | ||||
|         // 使用账号密码,进行登陆。 | ||||
|         SysUserDO user = userService.getUser(socialUsers.get(0).getUserId()); | ||||
|         if (user == null) { | ||||
|             throw exception(USER_NOT_EXISTS); | ||||
|         } | ||||
|         LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user); | ||||
|         // TODO 芋艿:需要改造下,增加各种登陆方式 | ||||
|         loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表 | ||||
|  | ||||
|         // 保存社交用户 | ||||
|         this.saveSocialUser(reqVO.getType(), socialUsers, loginUser.getId(), authUser); | ||||
|  | ||||
|         // 缓存登陆用户到 Redis 中,返回 sessionId 编号 | ||||
|         return userSessionService.createUserSession(loginUser, userIp, userAgent); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String socialLogin2(SysAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent) { | ||||
|         // 使用 code 授权码,进行登陆 | ||||
|         AuthCallback authCallback = SysAuthConvert.INSTANCE.convert(reqVO); | ||||
|         AuthUser authUser = this.obtainAuthUserFromCache(reqVO.getType(), authCallback); | ||||
|  | ||||
|         // 查询社交对应的 SysSocialUserDO 用户 | ||||
|         String unionId = getAuthUserUnionId(authUser); | ||||
|         List<SysSocialUserDO> socialUsers = socialUserMapper.selectListByTypeAndUnionId(UserTypeEnum.ADMIN.getValue(), | ||||
|                 reqVO.getType(), unionId); | ||||
|  | ||||
|         // 使用账号密码,进行登陆。 | ||||
|         LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword()); // TODO 芋艿:需要改造下,增加各种登陆方式 | ||||
|         loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表 | ||||
|  | ||||
|         // 保存社交用户 | ||||
|         this.saveSocialUser(reqVO.getType(), socialUsers, loginUser.getId(), authUser); | ||||
|  | ||||
|         // 缓存登陆用户到 Redis 中,返回 sessionId 编号 | ||||
|         return userSessionService.createUserSession(loginUser, userIp, userAgent); | ||||
|     } | ||||
|  | ||||
|     private static String getAuthUserUnionId(AuthUser authUser) { | ||||
|         return StrUtil.blankToDefault(authUser.getToken().getUnionId(), authUser.getUuid()); | ||||
|     } | ||||
|  | ||||
|     private AuthUser obtainAuthUserFromCache(Integer type, AuthCallback authCallback) { | ||||
|         // 从缓存中获取 | ||||
|         AuthUser authUser = authSocialUserRedisDAO.get(type, authCallback); | ||||
|         if (authUser != null) { | ||||
|             return authUser; | ||||
|         } | ||||
|  | ||||
|         // 请求获取 | ||||
|         authUser = this.obtainAuthUser(type, authCallback); | ||||
|         authSocialUserRedisDAO.set(type, authCallback, authUser); | ||||
|         return authUser; | ||||
|     } | ||||
|  | ||||
|     private AuthUser obtainAuthUser(Integer type, AuthCallback authCallback) { | ||||
|         AuthRequest authRequest = authRequestFactory.get(SysUserSocialTypeEnum.valueOfType(type).getSource()); | ||||
|         AuthResponse<?> authResponse = authRequest.login(authCallback); | ||||
|         log.info("[obtainAuthUser][请求三方平台 type({}) request({}) response({})]", type, JsonUtils.toJsonString(authCallback), | ||||
|                 JsonUtils.toJsonString(authResponse)); | ||||
|         if (!authResponse.ok()) { | ||||
|             throw exception(AUTH_THIRD_OAUTH_FAILURE, authResponse.getMsg()); | ||||
|         } | ||||
|         return (AuthUser) authResponse.getData(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 保存社交用户 | ||||
|      * | ||||
|      * @param socialUsers 已存在的社交用户列表 | ||||
|      * @param userId 绑定的用户编号 | ||||
|      * @param authUser 需要保存的社交用户信息 | ||||
|      */ | ||||
|     private void saveSocialUser(Integer type, List<SysSocialUserDO> socialUsers, Long userId, AuthUser authUser) { | ||||
|         // 逻辑一:如果 socialUsers 指定的 userId 改变,需要进行更新 | ||||
|         // 例如说,一个微信 unionId 对应了多个社交账号,结果其中有个关联了新的 userId,则其它也要跟着修改 | ||||
|         // 考虑到 socialUsers 一般比较少,直接 for 循环更新即可 | ||||
|         socialUsers.forEach(socialUser -> { | ||||
|             if (Objects.equals(socialUser.getUserId(), userId)) { | ||||
|                 return; | ||||
|             } | ||||
|             socialUserMapper.updateById(new SysSocialUserDO().setUserId(socialUser.getUserId()).setUserId(userId)); | ||||
|         }); | ||||
|  | ||||
|         // 逻辑二:如果 authUser 不存在于 socialUsers 中,则进行新增;否则,进行更新 | ||||
|         SysSocialUserDO saveSocialUser = CollUtil.findOneByField(socialUsers, "openid", authUser.getUuid()); | ||||
|         if (saveSocialUser == null) { | ||||
|             saveSocialUser = new SysSocialUserDO(); | ||||
|             saveSocialUser.setUserId(userId).setUserType(UserTypeEnum.ADMIN.getValue()); | ||||
|             saveSocialUser.setType(type).setOpenid(authUser.getUuid()).setToken(authUser.getToken().getAccessToken()) | ||||
|                     .setUnionId(getAuthUserUnionId(authUser)).setRawTokenInfo(JsonUtils.toJsonString(authUser.getToken())); | ||||
|             saveSocialUser.setNickname(authUser.getNickname()).setAvatar(authUser.getAvatar()) | ||||
|                             .setRawUserInfo(JsonUtils.toJsonString(authUser.getRawUserInfo())); | ||||
|             socialUserMapper.insert(saveSocialUser); | ||||
|         } else { | ||||
|             saveSocialUser = new SysSocialUserDO().setId(saveSocialUser.getId()); | ||||
|             saveSocialUser.setToken(authUser.getToken().getAccessToken()).setUnionId(getAuthUserUnionId(authUser)) | ||||
|                     .setRawTokenInfo(JsonUtils.toJsonString(authUser.getToken())); | ||||
|             saveSocialUser.setNickname(authUser.getNickname()).setAvatar(authUser.getAvatar()) | ||||
|                     .setRawUserInfo(JsonUtils.toJsonString(authUser.getRawUserInfo())); | ||||
|             socialUserMapper.updateById(saveSocialUser); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void logout(String token) { | ||||
|         // 查询用户信息 | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil; | ||||
| import cn.hutool.core.io.IoUtil; | ||||
| import cn.hutool.core.util.IdUtil; | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserSocialDO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysSocialUserDO; | ||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social.SysUserSocialMapper; | ||||
| import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||||
| import cn.iocoder.yudao.framework.common.exception.ServiceException; | ||||
| @@ -80,7 +80,7 @@ public class SysUserServiceImpl implements SysUserService { | ||||
|  | ||||
|     @Override | ||||
|     public Long bindSocialUSer(Long sysUserId, String socialUSerId) { | ||||
|         SysUserSocialDO userSocialDO = new SysUserSocialDO(); | ||||
|         SysSocialUserDO userSocialDO = new SysSocialUserDO(); | ||||
|         userSocialDO.setUserId(sysUserId); | ||||
| //        userSocialDO.setSocialUserId(socialUSerId); | ||||
|         userSocialMapper.insert(userSocialDO); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV