Ver código fonte

1. 修复“登陆”=》“登录”
2. 增加社交平台的绑定与解绑

YunaiV 3 anos atrás
pai
commit
4a23a696f4
56 arquivos alterados com 329 adições e 149 exclusões
  1. 2 2
      README.md
  2. 9 9
      sql/ruoyi-vue-pro.sql
  3. 24 10
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java
  4. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthLoginReqVO.java
  5. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthLoginRespVO.java
  6. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthMenuRespVO.java
  7. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthPermissionInfoRespVO.java
  8. 35 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialBindReqVO.java
  9. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialLogin2ReqVO.java
  10. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialLoginReqVO.java
  11. 31 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialUnbindReqVO.java
  12. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/session/SysUserSessionPageItemRespVO.java
  13. 4 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/SysLoginLogController.java
  14. 3 3
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogBaseVO.java
  15. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogCreateReqVO.java
  16. 4 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogExcelVO.java
  17. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogExportReqVO.java
  18. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogPageReqVO.java
  19. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogRespVO.java
  20. 3 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserProfileController.http
  21. 7 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserProfileController.java
  22. 17 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/profile/SysUserProfileRespVO.java
  23. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserRespVO.java
  24. 3 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/user/SysUserConvert.java
  25. 3 3
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/logger/SysLoginLogDO.java
  26. 4 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/social/SysSocialUserMapper.java
  27. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/redis/SysRedisKeyConstants.java
  28. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysDictTypeConstants.java
  29. 3 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java
  30. 3 3
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/logger/SysLoginLogTypeEnum.java
  31. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/logger/SysLoginResultEnum.java
  32. 21 13
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthService.java
  33. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionService.java
  34. 25 15
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java
  35. 6 6
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysLoginLogService.java
  36. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/impl/SysLoginLogServiceImpl.java
  37. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysPermissionServiceImpl.java
  38. 18 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/social/SysSocialService.java
  39. 53 24
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/social/impl/SysSocialServiceImpl.java
  40. 1 1
      yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsServiceIntegrationTest.java
  41. 1 1
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthServiceImplTest.java
  42. 5 5
      yudao-admin-ui/src/api/login.js
  43. 2 2
      yudao-admin-ui/src/store/modules/user.js
  44. 1 1
      yudao-admin-ui/src/views/index_old.vue
  45. 3 3
      yudao-admin-ui/src/views/login.vue
  46. 2 2
      yudao-admin-ui/src/views/socialLogin.vue
  47. 1 1
      yudao-admin-ui/src/views/system/loginlog/index.vue
  48. 1 1
      yudao-admin-ui/src/views/system/session/index.vue
  49. 1 1
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java
  50. 1 1
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
  51. 1 1
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java
  52. 2 2
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/annotations/PreAuthenticated.java
  53. 1 1
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JwtAuthenticationTokenFilter.java
  54. 1 1
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java
  55. 1 1
      yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java
  56. 1 1
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/auth/SysAuthService.java

+ 2 - 2
README.md

@@ -127,11 +127,11 @@
 
 | 模块 | biu |  biu | biu |
 | --- | --- | --- | --- |
-| 登 & 首页 | ![登录](https://static.iocoder.cn/images/ruoyi-vue-pro/登录.jpg) | ![首页](https://static.iocoder.cn/images/ruoyi-vue-pro/首页.jpg) | ![个人中心](https://static.iocoder.cn/images/ruoyi-vue-pro/个人中心.jpg) |
+| 登 & 首页 | ![登录](https://static.iocoder.cn/images/ruoyi-vue-pro/登录.jpg) | ![首页](https://static.iocoder.cn/images/ruoyi-vue-pro/首页.jpg) | ![个人中心](https://static.iocoder.cn/images/ruoyi-vue-pro/个人中心.jpg) |
 | 用户 | ![用户管理](https://static.iocoder.cn/images/ruoyi-vue-pro/用户管理.jpg) | ![在线用户](https://static.iocoder.cn/images/ruoyi-vue-pro/在线用户.jpg) | - |
 | 部门 & 岗位 | ![部门管理](https://static.iocoder.cn/images/ruoyi-vue-pro/部门管理.jpg) | ![岗位管理](https://static.iocoder.cn/images/ruoyi-vue-pro/岗位管理.jpg) | - |
 | 菜单 & 角色 | ![菜单管理](https://static.iocoder.cn/images/ruoyi-vue-pro/菜单管理.jpg) | ![角色管理](https://static.iocoder.cn/images/ruoyi-vue-pro/角色管理.jpg) | - |
-| 审计日志 | ![操作日志](https://static.iocoder.cn/images/ruoyi-vue-pro/操作日志.jpg) | ![登陆日志](https://static.iocoder.cn/images/ruoyi-vue-pro/登陆日志.jpg) | - |
+| 审计日志 | ![操作日志](https://static.iocoder.cn/images/ruoyi-vue-pro/操作日志.jpg) | ![登录日志](https://static.iocoder.cn/images/ruoyi-vue-pro/登录日志.jpg) | - |
 | 短信 | ![短信渠道](https://static.iocoder.cn/images/ruoyi-vue-pro/短信渠道.jpg) | ![短信模板](https://static.iocoder.cn/images/ruoyi-vue-pro/短信模板.jpg) | ![短信日志](https://static.iocoder.cn/images/ruoyi-vue-pro/短信日志.jpg) |
 | 字典 | ![字典类型](https://static.iocoder.cn/images/ruoyi-vue-pro/字典类型.jpg) | ![字典数据](https://static.iocoder.cn/images/ruoyi-vue-pro/字典数据.jpg) | - |
 | 错误码 & 通知 | ![错误码管理](https://static.iocoder.cn/images/ruoyi-vue-pro/错误码管理.jpg) | ![通知公告](https://static.iocoder.cn/images/ruoyi-vue-pro/通知公告.jpg) | - |

+ 9 - 9
sql/ruoyi-vue-pro.sql

@@ -299,12 +299,12 @@ INSERT INTO `sys_dict_data` VALUES (35, 2, '指定部门数据权限', '2', 'sys
 INSERT INTO `sys_dict_data` VALUES (36, 3, '本部门数据权限', '3', 'sys_data_scope', 0, '本部门数据权限', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 19:38:29', b'0');
 INSERT INTO `sys_dict_data` VALUES (37, 4, '本部门及以下数据权限', '4', 'sys_data_scope', 0, '本部门及以下数据权限', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 19:38:32', b'0');
 INSERT INTO `sys_dict_data` VALUES (38, 5, '仅本人数据权限', '5', 'sys_data_scope', 0, '仅本人数据权限', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 19:38:38', b'0');
-INSERT INTO `sys_dict_data` VALUES (39, 0, '成功', '0', 'sys_login_result', 0, '登结果 - 成功', '', '2021-01-18 06:17:36', '', '2021-01-18 06:17:36', b'0');
-INSERT INTO `sys_dict_data` VALUES (40, 10, '账号或密码不正确', '10', 'sys_login_result', 0, '登结果 - 账号或密码不正确', '', '2021-01-18 06:17:54', '', '2021-01-18 06:17:54', b'0');
-INSERT INTO `sys_dict_data` VALUES (41, 20, '用户被禁用', '20', 'sys_login_result', 0, '登结果 - 用户被禁用', '', '2021-01-18 06:17:54', '', '2021-01-18 06:19:02', b'0');
-INSERT INTO `sys_dict_data` VALUES (42, 30, '验证码不存在', '30', 'sys_login_result', 0, '登结果 - 验证码不存在', '', '2021-01-18 06:17:54', '', '2021-01-18 06:19:24', b'0');
-INSERT INTO `sys_dict_data` VALUES (43, 31, '验证码不正确', '31', 'sys_login_result', 0, '登结果 - 验证码不正确', '', '2021-01-18 06:17:54', '', '2021-01-18 06:19:33', b'0');
-INSERT INTO `sys_dict_data` VALUES (44, 100, '未知异常', '100', 'sys_login_result', 0, '登结果 - 未知异常', '', '2021-01-18 06:17:54', '', '2021-01-18 06:19:57', b'0');
+INSERT INTO `sys_dict_data` VALUES (39, 0, '成功', '0', 'sys_login_result', 0, '登结果 - 成功', '', '2021-01-18 06:17:36', '', '2021-01-18 06:17:36', b'0');
+INSERT INTO `sys_dict_data` VALUES (40, 10, '账号或密码不正确', '10', 'sys_login_result', 0, '登结果 - 账号或密码不正确', '', '2021-01-18 06:17:54', '', '2021-01-18 06:17:54', b'0');
+INSERT INTO `sys_dict_data` VALUES (41, 20, '用户被禁用', '20', 'sys_login_result', 0, '登结果 - 用户被禁用', '', '2021-01-18 06:17:54', '', '2021-01-18 06:19:02', b'0');
+INSERT INTO `sys_dict_data` VALUES (42, 30, '验证码不存在', '30', 'sys_login_result', 0, '登结果 - 验证码不存在', '', '2021-01-18 06:17:54', '', '2021-01-18 06:19:24', b'0');
+INSERT INTO `sys_dict_data` VALUES (43, 31, '验证码不正确', '31', 'sys_login_result', 0, '登结果 - 验证码不正确', '', '2021-01-18 06:17:54', '', '2021-01-18 06:19:33', b'0');
+INSERT INTO `sys_dict_data` VALUES (44, 100, '未知异常', '100', 'sys_login_result', 0, '登结果 - 未知异常', '', '2021-01-18 06:17:54', '', '2021-01-18 06:19:57', b'0');
 INSERT INTO `sys_dict_data` VALUES (45, 1, '是', 'true', 'sys_boolean_string', 0, 'Boolean 是否类型 - 是', '', '2021-01-19 03:20:55', '', '2021-01-19 03:21:08', b'0');
 INSERT INTO `sys_dict_data` VALUES (46, 1, '否', 'false', 'sys_boolean_string', 0, 'Boolean 是否类型 - 否', '', '2021-01-19 03:20:55', '', '2021-01-19 03:21:39', b'0');
 INSERT INTO `sys_dict_data` VALUES (47, 1, '永不超时', '1', 'inf_redis_timeout_type', 0, 'Redis 未设置超时的情况', '', '2021-01-26 00:53:17', '', '2021-01-26 00:53:17', b'0');
@@ -380,7 +380,7 @@ INSERT INTO `sys_dict_type` VALUES (8, '通知状态', 'sys_notice_status', 0, N
 INSERT INTO `sys_dict_type` VALUES (9, '操作类型', 'sys_oper_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 17:03:48', b'0');
 INSERT INTO `sys_dict_type` VALUES (10, '系统状态', 'sys_common_status', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 17:03:48', b'0');
 INSERT INTO `sys_dict_type` VALUES (11, 'Boolean 是否类型', 'sys_boolean_string', 0, 'boolean 转是否', '', '2021-01-19 03:20:08', '', '2021-01-19 03:20:08', b'0');
-INSERT INTO `sys_dict_type` VALUES (104, '登陆结果', 'sys_login_result', 0, '登陆结果', '', '2021-01-18 06:17:11', '', '2021-01-18 06:17:11', b'0');
+INSERT INTO `sys_dict_type` VALUES (104, '登录结果', 'sys_login_result', 0, '登录结果', '', '2021-01-18 06:17:11', '', '2021-01-18 06:17:11', b'0');
 INSERT INTO `sys_dict_type` VALUES (105, 'Redis 超时类型', 'inf_redis_timeout_type', 0, 'RedisKeyDefine.TimeoutTypeEnum', '', '2021-01-26 00:52:50', '', '2021-01-26 00:52:50', b'0');
 INSERT INTO `sys_dict_type` VALUES (106, '代码生成模板类型', 'tool_codegen_template_type', 0, NULL, '', '2021-02-05 07:08:06', '', '2021-02-05 07:08:06', b'0');
 INSERT INTO `sys_dict_type` VALUES (107, '定时任务状态', 'inf_job_status', 0, NULL, '', '2021-02-07 07:44:16', '', '2021-02-07 07:44:16', b'0');
@@ -392,7 +392,7 @@ INSERT INTO `sys_dict_type` VALUES (112, '短信模板的类型', 'sys_sms_templ
 INSERT INTO `sys_dict_type` VALUES (113, '短信发送状态', 'sys_sms_send_status', 0, NULL, '1', '2021-04-11 20:18:03', '1', '2021-04-11 09:30:02', b'0');
 INSERT INTO `sys_dict_type` VALUES (114, '短信接收状态', 'sys_sms_receive_status', 0, NULL, '1', '2021-04-11 20:27:14', '1', '2021-04-11 20:27:14', b'0');
 INSERT INTO `sys_dict_type` VALUES (115, '错误码的类型', 'sys_error_code_type', 0, NULL, '1', '2021-04-21 00:06:30', '1', '2021-04-13 22:07:12', b'0');
-INSERT INTO `sys_dict_type` VALUES (116, '登陆日志的类型', 'sys_login_type', 0, '登陆日志的类型', '1', '2021-10-06 00:50:46', '1', '2021-10-06 00:50:46', b'0');
+INSERT INTO `sys_dict_type` VALUES (116, '登录日志的类型', 'sys_login_type', 0, '登录日志的类型', '1', '2021-10-06 00:50:46', '1', '2021-10-06 00:50:46', b'0');
 COMMIT;
 
 -- ----------------------------
@@ -511,7 +511,7 @@ CREATE TABLE `sys_login_log` (
   `user_id` bigint NOT NULL DEFAULT '0' COMMENT '用户编号',
   `user_type` tinyint NOT NULL DEFAULT '0' COMMENT '用户类型',
   `username` varchar(50) NOT NULL DEFAULT '' COMMENT '用户账号',
-  `result` tinyint NOT NULL COMMENT '登结果',
+  `result` tinyint NOT NULL COMMENT '登结果',
   `user_ip` varchar(50) NOT NULL COMMENT '用户 IP',
   `user_agent` varchar(512) NOT NULL COMMENT '浏览器 UA',
   `creator` varchar(64) DEFAULT '' COMMENT '创建者',

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

@@ -70,7 +70,7 @@ public class SysAuthController {
     }
 
     @GetMapping("/get-permission-info")
-    @ApiOperation("获取登用户的权限信息")
+    @ApiOperation("获取登用户的权限信息")
     public CommonResult<SysAuthPermissionInfoRespVO> getPermissionInfo() {
         // 获得用户信息
         SysUserDO user = userService.getUser(getLoginUserId());
@@ -81,7 +81,7 @@ public class SysAuthController {
         List<SysRoleDO> roleList = roleService.getRolesFromCache(getLoginUserRoleIds());
         // 获得菜单列表
         List<SysMenuDO> menuList = permissionService.getRoleMenusFromCache(
-                getLoginUserRoleIds(), // 注意,基于登的角色,因为后续的权限判断也是基于它
+                getLoginUserRoleIds(), // 注意,基于登的角色,因为后续的权限判断也是基于它
                 SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType(), MenuTypeEnum.BUTTON.getType()),
                 SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus()));
         // 拼接结果返回
@@ -89,32 +89,32 @@ public class SysAuthController {
     }
 
     @GetMapping("list-menus")
-    @ApiOperation("获得登用户的菜单列表")
+    @ApiOperation("获得登用户的菜单列表")
     public CommonResult<List<SysAuthMenuRespVO>> getMenus() {
         // 获得用户拥有的菜单列表
         List<SysMenuDO> menuList = permissionService.getRoleMenusFromCache(
-                getLoginUserRoleIds(), // 注意,基于登的角色,因为后续的权限判断也是基于它
+                getLoginUserRoleIds(), // 注意,基于登的角色,因为后续的权限判断也是基于它
                 SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType()), // 只要目录和菜单类型
                 SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus())); // 只要开启的
         // 转换成 Tree 结构返回
         return success(SysAuthConvert.INSTANCE.buildMenuTree(menuList));
     }
 
-    // ========== 社交登相关 ==========
+    // ========== 社交登相关 ==========
 
-    @GetMapping("/social-login-redirect")
-    @ApiOperation("社交登陆的跳转")
+    @GetMapping("/social-auth-redirect")
+    @ApiOperation("社交授权的跳转")
     @ApiImplicitParams({
             @ApiImplicitParam(name = "type", value = "社交类型", required = true, dataTypeClass = Integer.class),
             @ApiImplicitParam(name = "redirectUri", value = "回调路径", dataTypeClass = String.class)
     })
-    public CommonResult<String> socialLoginRedirect(@RequestParam("type") Integer type,
+    public CommonResult<String> socialAuthRedirect(@RequestParam("type") Integer type,
                                                     @RequestParam("redirectUri") String redirectUri) {
         return CommonResult.success(socialService.getAuthorizeUrl(type, redirectUri));
     }
 
     @PostMapping("/social-login")
-    @ApiOperation("社交登,使用 code 授权码")
+    @ApiOperation("社交登,使用 code 授权码")
     @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
     public CommonResult<SysAuthLoginRespVO> socialLogin(@RequestBody @Valid SysAuthSocialLoginReqVO reqVO) {
         String token = authService.socialLogin(reqVO, getClientIP(), getUserAgent());
@@ -123,7 +123,7 @@ public class SysAuthController {
     }
 
     @PostMapping("/social-login2")
-    @ApiOperation("社交登,使用 code 授权码 + 账号密码")
+    @ApiOperation("社交登,使用 code 授权码 + 账号密码")
     @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
     public CommonResult<SysAuthLoginRespVO> socialLogin2(@RequestBody @Valid SysAuthSocialLogin2ReqVO reqVO) {
         String token = authService.socialLogin2(reqVO, getClientIP(), getUserAgent());
@@ -131,4 +131,18 @@ public class SysAuthController {
         return success(SysAuthLoginRespVO.builder().token(token).build());
     }
 
+    @PostMapping("/social-bind")
+    @ApiOperation("社交绑定,使用 code 授权码")
+    public CommonResult<Boolean> socialBind(@RequestBody @Valid SysAuthSocialBindReqVO reqVO) {
+        authService.socialBind(getLoginUserId(), reqVO);
+        return CommonResult.success(true);
+    }
+
+    @DeleteMapping("/social-unbind")
+    @ApiOperation("取消社交绑定")
+    public CommonResult<Boolean> socialUnbind(@RequestBody SysAuthSocialUnbindReqVO reqVO) {
+        socialService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId());
+        return CommonResult.success(true);
+    }
+
 }

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

@@ -11,7 +11,7 @@ import org.hibernate.validator.constraints.Length;
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.Pattern;
 
-@ApiModel("账号密码登 Request VO")
+@ApiModel("账号密码登 Request VO")
 @Data
 @NoArgsConstructor
 @AllArgsConstructor
@@ -19,7 +19,7 @@ import javax.validation.constraints.Pattern;
 public class SysAuthLoginReqVO {
 
     @ApiModelProperty(value = "账号", required = true, example = "yudaoyuanma")
-    @NotEmpty(message = "登账号不能为空")
+    @NotEmpty(message = "登账号不能为空")
     @Length(min = 4, max = 16, message = "账号长度为 4-16 位")
     @Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
     private String username;

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthLoginRespVO.java

@@ -7,7 +7,7 @@ import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
-@ApiModel("账号密码登 Response VO")
+@ApiModel("账号密码登 Response VO")
 @Data
 @NoArgsConstructor
 @AllArgsConstructor

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthMenuRespVO.java

@@ -9,7 +9,7 @@ import lombok.NoArgsConstructor;
 
 import java.util.List;
 
-@ApiModel("登用户的菜单信息 Response VO")
+@ApiModel("登用户的菜单信息 Response VO")
 @Data
 @NoArgsConstructor
 @AllArgsConstructor

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthPermissionInfoRespVO.java

@@ -9,7 +9,7 @@ import lombok.NoArgsConstructor;
 
 import java.util.Set;
 
-@ApiModel(value = "登用户的权限信息 Response VO", description = "额外包括用户信息和角色列表")
+@ApiModel(value = "登用户的权限信息 Response VO", description = "额外包括用户信息和角色列表")
 @Data
 @NoArgsConstructor
 @AllArgsConstructor

+ 35 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialBindReqVO.java

@@ -0,0 +1,35 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth;
+
+import cn.iocoder.yudao.adminserver.modules.system.enums.user.SysSocialTypeEnum;
+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 javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@ApiModel("社交绑定 Request VO,使用 code 授权码")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class SysAuthSocialBindReqVO {
+
+    @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值")
+    @InEnum(SysSocialTypeEnum.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;
+
+}

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

@@ -14,7 +14,7 @@ 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
@@ -35,7 +35,7 @@ public class SysAuthSocialLogin2ReqVO {
     private String state;
 
     @ApiModelProperty(value = "账号", required = true, example = "yudaoyuanma")
-    @NotEmpty(message = "登账号不能为空")
+    @NotEmpty(message = "登账号不能为空")
     @Length(min = 4, max = 16, message = "账号长度为 4-16 位")
     @Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
     private String username;

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialLoginReqVO.java

@@ -12,7 +12,7 @@ import lombok.NoArgsConstructor;
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
 
-@ApiModel("社交登 Request VO,使用 code 授权码")
+@ApiModel("社交登 Request VO,使用 code 授权码")
 @Data
 @NoArgsConstructor
 @AllArgsConstructor

+ 31 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialUnbindReqVO.java

@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth;
+
+import cn.iocoder.yudao.adminserver.modules.system.enums.user.SysSocialTypeEnum;
+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 javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@ApiModel("取消社交绑定 Request VO,使用 code 授权码")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class SysAuthSocialUnbindReqVO {
+
+    @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值")
+    @InEnum(SysSocialTypeEnum.class)
+    @NotNull(message = "社交平台的类型不能为空")
+    private Integer type;
+
+    @ApiModelProperty(value = "社交的全局编号", required = true, example = "IPRmJ0wvBptiPIlGEZiPewGwiEiE")
+    @NotEmpty(message = "社交的全局编号不能为空")
+    private String unionId;
+
+}

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/session/SysUserSessionPageItemRespVO.java

@@ -26,7 +26,7 @@ public class SysUserSessionPageItemRespVO extends PageParam {
     @ApiModelProperty(value = "浏览器 UserAgent", required = true, example = "Mozilla/5.0")
     private String userAgent;
 
-    @ApiModelProperty(value = "登时间", required = true)
+    @ApiModelProperty(value = "登时间", required = true)
     private Date createTime;
 
     @ApiModelProperty(value = "用户账号", required = true, example = "yudao")

+ 4 - 4
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/SysLoginLogController.java

@@ -27,7 +27,7 @@ import java.util.List;
 
 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
 
-@Api(tags = "登日志")
+@Api(tags = "登日志")
 @RestController
 @RequestMapping("/system/login-log")
 @Validated
@@ -37,7 +37,7 @@ public class SysLoginLogController {
     private SysLoginLogService loginLogService;
 
     @GetMapping("/page")
-    @ApiOperation("获得登日志分页列表")
+    @ApiOperation("获得登日志分页列表")
     @PreAuthorize("@ss.hasPermission('system:login-log:query')")
     public CommonResult<PageResult<SysLoginLogRespVO>> getLoginLogPage(@Valid SysLoginLogPageReqVO reqVO) {
         PageResult<SysLoginLogDO> page = loginLogService.getLoginLogPage(reqVO);
@@ -45,7 +45,7 @@ public class SysLoginLogController {
     }
 
     @GetMapping("/export")
-    @ApiOperation("导出登日志 Excel")
+    @ApiOperation("导出登日志 Excel")
     @PreAuthorize("@ss.hasPermission('system:login-log:export')")
     @OperateLog(type = EXPORT)
     public void exportLoginLog(HttpServletResponse response, @Valid SysLoginLogExportReqVO reqVO) throws IOException {
@@ -53,7 +53,7 @@ public class SysLoginLogController {
         // 拼接数据
         List<SysLoginLogExcelVO> data = SysLoginLogConvert.INSTANCE.convertList(list);
         // 输出
-        ExcelUtils.write(response, "登日志.xls", "数据列表", SysLoginLogExcelVO.class, data);
+        ExcelUtils.write(response, "登日志.xls", "数据列表", SysLoginLogExcelVO.class, data);
     }
 
 }

+ 3 - 3
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogBaseVO.java

@@ -9,7 +9,7 @@ import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
 
 /**
- * 登日志 Base VO,提供给添加、修改、详细的子 VO 使用
+ * 登日志 Base VO,提供给添加、修改、详细的子 VO 使用
  * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  */
 @Data
@@ -28,8 +28,8 @@ public class SysLoginLogBaseVO {
     @Size(max = 30, message = "用户账号长度不能超过30个字符")
     private String username;
 
-    @ApiModelProperty(value = "登结果", required = true, example = "1", notes = "参见 SysLoginResultEnum 枚举类")
-    @NotNull(message = "登结果不能为空")
+    @ApiModelProperty(value = "登结果", required = true, example = "1", notes = "参见 SysLoginResultEnum 枚举类")
+    @NotNull(message = "登结果不能为空")
     private Integer result;
 
     @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1")

+ 2 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogCreateReqVO.java

@@ -5,8 +5,8 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
-@ApiModel(value = "登日志创建 Request VO",
-        description = "暂时提供给前端,仅仅后端记录登日志时,进行使用")
+@ApiModel(value = "登日志创建 Request VO",
+        description = "暂时提供给前端,仅仅后端记录登日志时,进行使用")
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)

+ 4 - 4
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogExcelVO.java

@@ -9,7 +9,7 @@ import lombok.Data;
 import java.util.Date;
 
 /**
- * 登日志 Excel 导出响应 VO
+ * 登日志 Excel 导出响应 VO
  */
 @Data
 public class SysLoginLogExcelVO {
@@ -24,17 +24,17 @@ public class SysLoginLogExcelVO {
     @DictFormat(SysDictTypeConstants.LOGIN_TYPE)
     private Integer logType;
 
-    @ExcelProperty(value = "登结果", converter = DictConvert.class)
+    @ExcelProperty(value = "登结果", converter = DictConvert.class)
     @DictFormat(SysDictTypeConstants.LOGIN_RESULT)
     private Integer result;
 
-    @ExcelProperty("登 IP")
+    @ExcelProperty("登 IP")
     private String userIp;
 
     @ExcelProperty("浏览器 UA")
     private String userAgent;
 
-    @ExcelProperty("登时间")
+    @ExcelProperty("登时间")
     private Date createTime;
 
 }

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogExportReqVO.java

@@ -9,7 +9,7 @@ import java.util.Date;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-@ApiModel("登日志分页列表 Request VO")
+@ApiModel("登日志分页列表 Request VO")
 @Data
 public class SysLoginLogExportReqVO {
 

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogPageReqVO.java

@@ -11,7 +11,7 @@ import java.util.Date;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-@ApiModel("登日志分页列表 Request VO")
+@ApiModel("登日志分页列表 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
 public class SysLoginLogPageReqVO extends PageParam {

+ 2 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogRespVO.java

@@ -9,7 +9,7 @@ import lombok.ToString;
 import javax.validation.constraints.NotNull;
 import java.util.Date;
 
-@ApiModel("登日志 Response VO")
+@ApiModel("登日志 Response VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
@@ -26,7 +26,7 @@ public class SysLoginLogRespVO extends SysLoginLogBaseVO {
     @NotNull(message = "用户类型不能为空")
     private Integer userType;
 
-    @ApiModelProperty(value = "登时间", required = true)
+    @ApiModelProperty(value = "登时间", required = true)
     private Date createTime;
 
 }

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

@@ -0,0 +1,3 @@
+### 请求 /system/user/profile/get 接口 => 没有权限
+GET {{baseUrl}}/system/user/profile/get
+Authorization: Bearer test1

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

@@ -1,6 +1,8 @@
 package cn.iocoder.yudao.adminserver.modules.system.controller.user;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO;
+import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService;
 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileRespVO;
@@ -52,6 +54,8 @@ public class SysUserProfileController {
     private SysPermissionService permissionService;
     @Resource
     private SysRoleService roleService;
+    @Resource
+    private SysSocialService socialService;
 
     @GetMapping("/get")
     @ApiOperation("获得登录用户信息")
@@ -72,6 +76,9 @@ public class SysUserProfileController {
             List<SysPostDO> posts = postService.getPosts(user.getPostIds());
             resp.setPosts(SysUserConvert.INSTANCE.convertList02(posts));
         }
+        // 获得社交用户信息
+        List<SysSocialUserDO> socialUsers = socialService.getSocialUserList(user.getId());
+        resp.setSocialUsers(SysUserConvert.INSTANCE.convertList03(socialUsers));
         return success(resp);
     }
 

+ 17 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/profile/SysUserProfileRespVO.java

@@ -25,7 +25,7 @@ public class SysUserProfileRespVO extends SysUserBaseVO {
     @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 SysCommonStatusEnum 枚举类")
     private Integer status;
 
-    @ApiModelProperty(value = "最后登 IP", required = true, example = "192.168.1.1")
+    @ApiModelProperty(value = "最后登 IP", required = true, example = "192.168.1.1")
     private String loginIp;
 
     @ApiModelProperty(value = "最后登录时间", required = true, example = "时间戳格式")
@@ -48,6 +48,10 @@ public class SysUserProfileRespVO extends SysUserBaseVO {
      * 所属岗位数组
      */
     private List<Post> posts;
+    /**
+     * 社交用户数组
+     */
+    private List<SocialUser> socialUsers;
 
     @ApiModel("角色")
     @Data
@@ -85,4 +89,16 @@ public class SysUserProfileRespVO extends SysUserBaseVO {
 
     }
 
+    @ApiModel("社交用户")
+    @Data
+    public static class SocialUser {
+
+        @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysSocialTypeEnum 枚举类")
+        private Integer type;
+
+        @ApiModelProperty(value = "社交的全局编号", required = true, example = "IPRmJ0wvBptiPIlGEZiPewGwiEiE")
+        private String unionId;
+
+    }
+
 }

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserRespVO.java

@@ -19,7 +19,7 @@ public class SysUserRespVO extends SysUserBaseVO {
     @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 SysCommonStatusEnum 枚举类")
     private Integer status;
 
-    @ApiModelProperty(value = "最后登 IP", required = true, example = "192.168.1.1")
+    @ApiModelProperty(value = "最后登 IP", required = true, example = "192.168.1.1")
     private String loginIp;
 
     @ApiModelProperty(value = "最后登录时间", required = true, example = "时间戳格式")

+ 3 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/user/SysUserConvert.java

@@ -7,6 +7,7 @@ import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.*;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO;
+import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
@@ -42,4 +43,6 @@ public interface SysUserConvert {
 
     List<SysUserProfileRespVO.Post> convertList02(List<SysPostDO> list);
 
+    List<SysUserProfileRespVO.SocialUser> convertList03(List<SysSocialUserDO> list);
+
 }

+ 3 - 3
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/logger/SysLoginLogDO.java

@@ -10,9 +10,9 @@ import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
 /**
- * 登日志表
+ * 登日志表
  *
- * 注意,包括登和登出两种行为
+ * 注意,包括登和登出两种行为
  *
  * @author ruoyi
  */
@@ -53,7 +53,7 @@ public class SysLoginLogDO extends BaseDO {
      */
     private String username;
     /**
-     * 登结果
+     * 登结果
      *
      * 枚举 {@link SysLoginResultEnum}
      */

+ 4 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/social/SysSocialUserMapper.java

@@ -21,4 +21,8 @@ public interface SysSocialUserMapper extends BaseMapperX<SysSocialUserDO> {
                 .in("type", types).eq("user_id", userId));
     }
 
+    default List<SysSocialUserDO> selectListByUserId(Integer userType, Long userId) {
+        return selectList(new QueryWrapper<SysSocialUserDO>().eq("user_type", userType).eq("user_id", userId));
+    }
+
 }

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/redis/SysRedisKeyConstants.java

@@ -15,7 +15,7 @@ import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.S
  */
 public interface SysRedisKeyConstants {
 
-    RedisKeyDefine LOGIN_USER = new RedisKeyDefine("登用户的缓存",
+    RedisKeyDefine LOGIN_USER = new RedisKeyDefine("登用户的缓存",
             "login_user:%s", // 参数为 sessionId
             STRING, LoginUser.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC);
 

+ 2 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysDictTypeConstants.java

@@ -12,8 +12,8 @@ public interface SysDictTypeConstants {
 
     String USER_SEX = "sys_user_sex"; // 用户性别
     String OPERATE_TYPE = "sys_operate_type"; // 操作类型
-    String LOGIN_TYPE = "sys_login_type"; // 登日志的类型
-    String LOGIN_RESULT = "sys_login_result"; // 登结果
+    String LOGIN_TYPE = "sys_login_type"; // 登日志的类型
+    String LOGIN_RESULT = "sys_login_result"; // 登结果
     String CONFIG_TYPE = "sys_config_type"; // 参数配置类型
     String BOOLEAN_STRING = "sys_boolean_string"; // Boolean 是否类型
 

+ 3 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java

@@ -2,6 +2,7 @@ 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;
+import org.springframework.validation.Errors;
 
 /**
  * System 错误码枚举类
@@ -13,7 +14,7 @@ public interface SysErrorCodeConstants {
     // ========== AUTH 模块 1002000000 ==========
     ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确");
     ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1002000001, "登录失败,账号被禁用");
-    ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1002000002, "登录失败"); // 登失败的兜底,位置原因
+    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, "未绑定账号,需要进行绑定");
@@ -99,5 +100,6 @@ public interface SysErrorCodeConstants {
 
     // ========== 社交模块 1002014000 ==========
     ErrorCode SOCIAL_AUTH_FAILURE = new ErrorCode(1002014000, "社交授权失败,原因是:{}");
+    ErrorCode SOCIAL_UNBIND_NOT_SELF = new ErrorCode(1002014001, "社交解绑失败,非当前用户绑定");
 
 }

+ 3 - 3
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/logger/SysLoginLogTypeEnum.java

@@ -4,15 +4,15 @@ import lombok.AllArgsConstructor;
 import lombok.Getter;
 
 /**
- * 登日志的类型枚举
+ * 登日志的类型枚举
  */
 @Getter
 @AllArgsConstructor
 public enum SysLoginLogTypeEnum {
 
     LOGIN_USERNAME(100), // 使用账号登录
-    LOGIN_SOCIAL(101), // 使用社交登
-    LOGIN_MOCK(102), // 使用 Mock 登
+    LOGIN_SOCIAL(101), // 使用社交登
+    LOGIN_MOCK(102), // 使用 Mock 登
 
     LOGOUT_SELF(200),  // 自己主动登出
     LOGOUT_TIMEOUT(201), // 超时登出

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/logger/SysLoginResultEnum.java

@@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
 import lombok.Getter;
 
 /**
- * 登结果的枚举类
+ * 登结果的枚举类
  */
 @Getter
 @AllArgsConstructor

+ 21 - 13
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthService.java

@@ -1,47 +1,55 @@
 package cn.iocoder.yudao.adminserver.modules.system.service.auth;
 
-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.auth.vo.auth.*;
 import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
-import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO;
+
+import javax.validation.Valid;
 
 /**
  * 认证 Service 接口
  *
- * 提供用户的账号密码登、token 的校验等认证相关的功能
+ * 提供用户的账号密码登、token 的校验等认证相关的功能
  *
  * @author 芋道源码
  */
 public interface SysAuthService extends SecurityAuthFrameworkService {
 
     /**
-     * 登陆用户
+     * 账号登录
      *
-     * @param reqVO 登信息
+     * @param reqVO 登信息
      * @param userIp 用户 IP
      * @param userAgent 用户 UA
      * @return 身份令牌,使用 JWT 方式
      */
-    String login(SysAuthLoginReqVO reqVO, String userIp, String userAgent);
+    String login(@Valid SysAuthLoginReqVO reqVO, String userIp, String userAgent);
 
     /**
-     * 社交登陆用户,使用 code 授权码
+     * 社交登,使用 code 授权码
      *
-     * @param reqVO 登信息
+     * @param reqVO 登信息
      * @param userIp 用户 IP
      * @param userAgent 用户 UA
      * @return 身份令牌,使用 JWT 方式
      */
-    String socialLogin(SysAuthSocialLoginReqVO reqVO, String userIp, String userAgent);
+    String socialLogin(@Valid SysAuthSocialLoginReqVO reqVO, String userIp, String userAgent);
 
     /**
-     * 社交登陆用户,使用 code 授权码 + 账号密码
+     * 社交登,使用 code 授权码 + 账号密码
      *
-     * @param reqVO 登信息
+     * @param reqVO 登信息
      * @param userIp 用户 IP
      * @param userAgent 用户 UA
      * @return 身份令牌,使用 JWT 方式
      */
-    String socialLogin2(SysAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent);
+    String socialLogin2(@Valid SysAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent);
+
+    /**
+     * 社交绑定,使用 code 授权码
+     *
+     * @param userId 用户编号
+     * @param reqVO 绑定信息
+     */
+    void socialBind(Long userId, @Valid SysAuthSocialBindReqVO reqVO);
 
 }

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

@@ -15,7 +15,7 @@ public interface SysUserSessionService {
     /**
      * 创建在线用户 Session
      *
-     * @param loginUser 登用户
+     * @param loginUser 登用户
      * @param userIp 用户 IP
      * @param userAgent 用户 UA
      * @return Session 编号
@@ -26,7 +26,7 @@ public interface SysUserSessionService {
      * 刷新在线用户 Session 的更新时间
      *
      * @param sessionId Session 编号
-     * @param loginUser 登用户
+     * @param loginUser 登用户
      */
     void refreshUserSession(String sessionId, LoginUser loginUser);
 

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

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialBindReqVO;
 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.logger.vo.loginlog.SysLoginLogCreateReqVO;
@@ -18,7 +19,6 @@ import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermiss
 import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService;
 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
 import cn.iocoder.yudao.framework.security.core.LoginUser;
@@ -101,11 +101,11 @@ public class SysAuthServiceImpl implements SysAuthService {
         // 判断验证码是否正确
         this.verifyCaptcha(reqVO.getUsername(), reqVO.getUuid(), reqVO.getCode());
 
-        // 使用账号密码,进行登
+        // 使用账号密码,进行登
         LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
         loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
 
-        // 缓存登用户到 Redis 中,返回 sessionId 编号
+        // 缓存登用户到 Redis 中,返回 sessionId 编号
         return userSessionService.createUserSession(loginUser, userIp, userAgent);
     }
 
@@ -114,13 +114,13 @@ public class SysAuthServiceImpl implements SysAuthService {
         String code = captchaService.getCaptchaCode(captchaUUID);
         // 验证码不存在
         if (code == null) {
-            // 创建登失败日志(验证码不存在)
+            // 创建登失败日志(验证码不存在)
             this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.CAPTCHA_NOT_FOUND);
             throw exception(AUTH_LOGIN_CAPTCHA_NOT_FOUND);
         }
         // 验证码不正确
         if (!code.equals(captchaCode)) {
-            // 创建登失败日志(验证码不正确)
+            // 创建登失败日志(验证码不正确)
             this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.CAPTCHA_CODE_ERROR);
             throw exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR);
         }
@@ -147,7 +147,7 @@ public class SysAuthServiceImpl implements SysAuthService {
             this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.UNKNOWN_ERROR);
             throw exception(AUTH_LOGIN_FAIL_UNKNOWN);
         }
-        // 登成功的日志
+        // 登成功的日志
         Assert.notNull(authentication.getPrincipal(), "Principal 不会为空");
         this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.SUCCESS);
         return (LoginUser) authentication.getPrincipal();
@@ -176,18 +176,18 @@ public class SysAuthServiceImpl implements SysAuthService {
 
     @Override
     public String socialLogin(SysAuthSocialLoginReqVO reqVO, String userIp, String userAgent) {
-        // 使用 code 授权码,进行登
+        // 使用 code 授权码,进行登
         AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState());
         Assert.notNull(authUser, "授权用户不为空");
 
-        // 如果未绑定 SysSocialUserDO 用户,则无法自动登,进行报错
+        // 如果未绑定 SysSocialUserDO 用户,则无法自动登,进行报错
         String unionId = socialService.getAuthUserUnionId(authUser);
         List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(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);
@@ -196,33 +196,43 @@ public class SysAuthServiceImpl implements SysAuthService {
 
         // 创建 LoginUser 对象
         LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
-        // TODO 芋艿:需要改造下,增加各种登方式
+        // TODO 芋艿:需要改造下,增加各种登方式
         loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
 
         // 绑定社交用户(更新)
         socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser);
 
-        // 缓存登用户到 Redis 中,返回 sessionId 编号
+        // 缓存登用户到 Redis 中,返回 sessionId 编号
         return userSessionService.createUserSession(loginUser, userIp, userAgent);
     }
 
     @Override
     public String socialLogin2(SysAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent) {
-        // 使用 code 授权码,进行登
+        // 使用 code 授权码,进行登
         AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState());
         Assert.notNull(authUser, "授权用户不为空");
 
-        // 使用账号密码,进行登
+        // 使用账号密码,进行登
         LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
         loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
 
         // 绑定社交用户(新增)
         socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser);
 
-        // 缓存登用户到 Redis 中,返回 sessionId 编号
+        // 缓存登用户到 Redis 中,返回 sessionId 编号
         return userSessionService.createUserSession(loginUser, userIp, userAgent);
     }
 
+    @Override
+    public void socialBind(Long userId, SysAuthSocialBindReqVO reqVO) {
+        // 使用 code 授权码,进行登录
+        AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState());
+        Assert.notNull(authUser, "授权用户不为空");
+
+        // 绑定社交用户(新增)
+        socialService.bindSocialUser(userId, reqVO.getType(), authUser);
+    }
+
     @Override
     public void logout(String token) {
         // 查询用户信息
@@ -269,7 +279,7 @@ public class SysAuthServiceImpl implements SysAuthService {
         // 重新加载 SysUserDO 信息
         SysUserDO user = userService.getUser(loginUser.getId());
         if (user == null || CommonStatusEnum.DISABLE.getStatus().equals(user.getStatus())) {
-            throw exception(TOKEN_EXPIRED); // 校验 token 时,用户被禁用的情况下,也认为 token 过期,方便前端跳转到登界面
+            throw exception(TOKEN_EXPIRED); // 校验 token 时,用户被禁用的情况下,也认为 token 过期,方便前端跳转到登界面
         }
 
         // 刷新 LoginUser 缓存

+ 6 - 6
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysLoginLogService.java

@@ -9,30 +9,30 @@ import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysLogi
 import java.util.List;
 
 /**
- * 登日志 Service 接口
+ * 登日志 Service 接口
  */
 public interface SysLoginLogService {
 
     /**
-     * 创建登日志
+     * 创建登日志
      *
      * @param reqVO 日志信息
      */
     void createLoginLog(SysLoginLogCreateReqVO reqVO);
 
     /**
-     * 获得登日志分页
+     * 获得登日志分页
      *
      * @param reqVO 分页条件
-     * @return 登日志分页
+     * @return 登日志分页
      */
     PageResult<SysLoginLogDO> getLoginLogPage(SysLoginLogPageReqVO reqVO);
 
     /**
-     * 获得登日志列表
+     * 获得登日志列表
      *
      * @param reqVO 列表条件
-     * @return 登日志列表
+     * @return 登日志列表
      */
     List<SysLoginLogDO> getLoginLogList(SysLoginLogExportReqVO reqVO);
 

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/impl/SysLoginLogServiceImpl.java

@@ -17,7 +17,7 @@ import javax.annotation.Resource;
 import java.util.List;
 
 /**
- * 登日志 Service 实现
+ * 登日志 Service 实现
  */
 @Service
 public class SysLoginLogServiceImpl implements SysLoginLogService {

+ 2 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysPermissionServiceImpl.java

@@ -280,7 +280,7 @@ public class SysPermissionServiceImpl implements SysPermissionService {
             return true;
         }
 
-        // 获得当前登的角色。如果为空,说明没有权限
+        // 获得当前登的角色。如果为空,说明没有权限
         Set<Long> roleIds = SecurityFrameworkUtils.getLoginUserRoleIds();
         if (CollUtil.isEmpty(roleIds)) {
             return false;
@@ -315,7 +315,7 @@ public class SysPermissionServiceImpl implements SysPermissionService {
             return true;
         }
 
-        // 获得当前登的角色。如果为空,说明没有权限
+        // 获得当前登的角色。如果为空,说明没有权限
         Set<Long> roleIds = SecurityFrameworkUtils.getLoginUserRoleIds();
         if (CollUtil.isEmpty(roleIds)) {
             return false;

+ 18 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/social/SysSocialService.java

@@ -4,6 +4,7 @@ import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO;
 import cn.iocoder.yudao.adminserver.modules.system.enums.user.SysSocialTypeEnum;
 import cn.iocoder.yudao.framework.common.exception.ServiceException;
+import io.swagger.models.auth.In;
 import me.zhyd.oauth.model.AuthUser;
 
 import javax.validation.constraints.NotNull;
@@ -51,6 +52,14 @@ public interface SysSocialService {
      */
     List<SysSocialUserDO> getAllSocialUserList(Integer type, String unionId);
 
+    /**
+     * 获得指定用户的社交用户列表
+     *
+     * @param userId 用户编号
+     * @return 社交用户列表
+     */
+    List<SysSocialUserDO> getSocialUserList(Long userId);
+
     /**
      * 绑定社交用户
      *
@@ -60,4 +69,13 @@ public interface SysSocialService {
      */
     void bindSocialUser(Long userId, Integer type, AuthUser authUser);
 
+    /**
+     * 取消绑定社交用户
+     *
+     * @param userId 用户编号
+     * @param type 社交平台的类型 {@link SysSocialTypeEnum}
+     * @param unionId 社交平台的 unionId
+     */
+    void unbindSocialUser(Long userId, Integer type, String unionId);
+
 }

+ 53 - 24
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/social/impl/SysSocialServiceImpl.java

@@ -9,7 +9,6 @@ import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialServi
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
-import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import com.xkcoding.justauth.AuthRequestFactory;
 import lombok.extern.slf4j.Slf4j;
 import me.zhyd.oauth.model.AuthCallback;
@@ -18,15 +17,17 @@ import me.zhyd.oauth.model.AuthUser;
 import me.zhyd.oauth.request.AuthRequest;
 import me.zhyd.oauth.utils.AuthStateUtils;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
-
 import java.util.List;
 import java.util.Objects;
 
 import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.SOCIAL_AUTH_FAILURE;
+import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.SOCIAL_UNBIND_NOT_SELF;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
 
 /**
  * 社交 Service 实现类
@@ -67,7 +68,7 @@ public class SysSocialServiceImpl implements SysSocialService {
 
         // 请求获取
         authUser = this.getAuthUser0(type, authCallback);
-        // 缓存。原因是 code 有且可以使用一次。在社交登录时,当未绑定 User 时,需要绑定登,此时需要 code 使用两次
+        // 缓存。原因是 code 有且可以使用一次。在社交登录时,当未绑定 User 时,需要绑定登,此时需要 code 使用两次
         authSocialUserRedisDAO.set(type, authCallback, authUser);
         return authUser;
     }
@@ -79,18 +80,19 @@ public class SysSocialServiceImpl implements SysSocialService {
     }
 
     @Override
+    public List<SysSocialUserDO> getSocialUserList(Long userId) {
+        return socialUserMapper.selectListByUserId(UserTypeEnum.ADMIN.getValue(), userId);
+    }
+
+    @Override
+    @Transactional
     public void bindSocialUser(Long userId, Integer type, AuthUser authUser) {
         // 获得 unionId 对应的 SysSocialUserDO 列表
         String unionId = getAuthUserUnionId(authUser);
         List<SysSocialUserDO> socialUsers = this.getAllSocialUserList(type, unionId);
 
         // 逻辑一:如果 userId 之前绑定过该 type 的其它账号,需要进行解绑
-        List<Integer> types = SysSocialTypeEnum.getRelationTypes(type);
-        List<SysSocialUserDO> oldSocialUsers = socialUserMapper.selectListByTypeAndUserId(UserTypeEnum.ADMIN.getValue(),
-                types, userId);
-        if (CollUtil.isNotEmpty(oldSocialUsers) && !Objects.equals(unionId, oldSocialUsers.get(0).getUnionId())) {
-            socialUserMapper.deleteBatchIds(CollectionUtils.convertSet(oldSocialUsers, SysSocialUserDO::getId));
-        }
+        this.unbindOldSocialUser(userId, type, unionId);
 
         // 逻辑二:如果 socialUsers 指定的 userId 改变,需要进行更新
         // 例如说,一个微信 unionId 对应了多个社交账号,结果其中有个关联了新的 userId,则其它也要跟着修改
@@ -103,25 +105,52 @@ public class SysSocialServiceImpl implements SysSocialService {
         });
 
         // 逻辑三:如果 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(unionId).setRawTokenInfo(JsonUtils.toJsonString(authUser.getToken()));
-            saveSocialUser.setNickname(authUser.getNickname()).setAvatar(authUser.getAvatar())
-                    .setRawUserInfo(JsonUtils.toJsonString(authUser.getRawUserInfo()));
+        SysSocialUserDO socialUser = CollUtil.findOneByField(socialUsers, "openid", authUser.getUuid());
+        SysSocialUserDO saveSocialUser = SysSocialUserDO.builder() // 新增和更新的通用属性
+                .token(authUser.getToken().getAccessToken()).rawUserInfo(toJsonString(authUser.getToken()))
+                .nickname(authUser.getNickname()).avatar(authUser.getAvatar()).rawUserInfo(toJsonString(authUser.getRawUserInfo()))
+                .build();
+        if (socialUser == null) {
+            saveSocialUser.setUserId(userId).setUserType(UserTypeEnum.ADMIN.getValue())
+                    .setType(type).setOpenid(authUser.getUuid()).setUnionId(unionId);
             socialUserMapper.insert(saveSocialUser);
         } else {
-            saveSocialUser = new SysSocialUserDO().setId(saveSocialUser.getId());
-            saveSocialUser.setToken(authUser.getToken().getAccessToken())
-                    .setRawTokenInfo(JsonUtils.toJsonString(authUser.getToken()));
-            saveSocialUser.setNickname(authUser.getNickname()).setAvatar(authUser.getAvatar())
-                    .setRawUserInfo(JsonUtils.toJsonString(authUser.getRawUserInfo()));
+            saveSocialUser.setId(socialUser.getId());
             socialUserMapper.updateById(saveSocialUser);
         }
     }
 
+    @Override
+    public void unbindSocialUser(Long userId, Integer type, String unionId) {
+        // 获得 unionId 对应的所有 SysSocialUserDO 社交用户
+        List<SysSocialUserDO> socialUsers = this.getAllSocialUserList(type, unionId);
+        if (CollUtil.isEmpty(socialUsers)) {
+            return;
+        }
+        // 校验,是否解绑的是非自己的
+        socialUsers.forEach(socialUser -> {
+            if (Objects.equals(socialUser.getUserId(), userId)) {
+                throw exception(SOCIAL_UNBIND_NOT_SELF);
+            }
+        });
+
+        // 解绑
+        socialUserMapper.deleteBatchIds(CollectionUtils.convertSet(socialUsers, SysSocialUserDO::getId));
+    }
+
+    private void unbindOldSocialUser(Long userId, Integer type, String newUnionId) {
+        List<Integer> types = SysSocialTypeEnum.getRelationTypes(type);
+        List<SysSocialUserDO> oldSocialUsers = socialUserMapper.selectListByTypeAndUserId(UserTypeEnum.ADMIN.getValue(),
+                types, userId);
+        // 如果新老的 unionId 是一致的,说明无需解绑
+        if (CollUtil.isEmpty(oldSocialUsers) || Objects.equals(newUnionId, oldSocialUsers.get(0).getUnionId())) {
+            return;
+        }
+
+        // 解绑
+        socialUserMapper.deleteBatchIds(CollectionUtils.convertSet(oldSocialUsers, SysSocialUserDO::getId));
+    }
+
     /**
      * 请求社交平台,获得授权的用户
      *
@@ -132,8 +161,8 @@ public class SysSocialServiceImpl implements SysSocialService {
     private AuthUser getAuthUser0(Integer type, AuthCallback authCallback) {
         AuthRequest authRequest = authRequestFactory.get(SysSocialTypeEnum.valueOfType(type).getSource());
         AuthResponse<?> authResponse = authRequest.login(authCallback);
-        log.info("[getAuthUser0][请求社交平台 type({}) request({}) response({})]", type, JsonUtils.toJsonString(authCallback),
-                JsonUtils.toJsonString(authResponse));
+        log.info("[getAuthUser0][请求社交平台 type({}) request({}) response({})]", type, toJsonString(authCallback),
+                toJsonString(authResponse));
         if (!authResponse.ok()) {
             throw exception(SOCIAL_AUTH_FAILURE, authResponse.getMsg());
         }

+ 1 - 1
yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsServiceIntegrationTest.java

@@ -41,7 +41,7 @@ public class SysSmsServiceIntegrationTest extends BaseDbAndRedisIntegrationTest
         Integer userType = UserTypeEnum.ADMIN.getValue();
         String templateCode = "test_01";
         Map<String, Object> templateParams = MapUtil.<String, Object>builder()
-                .put("operation", "登").put("code", "1234").build();
+                .put("operation", "登").put("code", "1234").build();
         // 调用
         smsService.sendSingleSms(mobile, userId, userType, templateCode, templateParams);
 

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

@@ -236,7 +236,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
         when(authentication.getPrincipal()).thenReturn(loginUser);
         // mock 获得 User 拥有的角色编号数组
         when(permissionService.getUserRoleIds(userId, singleton(CommonStatusEnum.ENABLE.getStatus()))).thenReturn(userRoleIds);
-        // mock 缓存登用户到 Redis
+        // mock 缓存登用户到 Redis
         when(userSessionService.createUserSession(loginUser, userIp, userAgent)).thenReturn(sessionId);
         // 调用, 并断言异常
         String login = authService.login(reqVO, userIp, userAgent);

+ 5 - 5
yudao-admin-ui/src/api/login.js

@@ -39,15 +39,15 @@ export function getCodeImg() {
   })
 }
 
-// 社交登陆的跳转
-export function socialLoginRedirect(type, redirectUri) {
+// 社交授权的跳转
+export function socialAuthRedirect(type, redirectUri) {
   return request({
-    url: '/social-login-redirect?type=' + type + '&redirectUri=' + redirectUri,
+    url: '/social-auth-redirect?type=' + type + '&redirectUri=' + redirectUri,
     method: 'get'
   })
 }
 
-// 社交登,使用 code 授权码
+// 社交登,使用 code 授权码
 export function socialLogin(type, code, state) {
   return request({
     url: '/social-login',
@@ -60,7 +60,7 @@ export function socialLogin(type, code, state) {
   })
 }
 
-// 社交登,使用 code 授权码 + + 账号密码
+// 社交登,使用 code 授权码 + + 账号密码
 export function socialLogin2(type, code, state, username, password) {
   return request({
     url: '/social-login2',

+ 2 - 2
yudao-admin-ui/src/store/modules/user.js

@@ -47,7 +47,7 @@ const user = {
       })
     },
 
-    // 社交登
+    // 社交登
     SocialLogin({ commit }, userInfo) {
       const code = userInfo.code
       const state = userInfo.state
@@ -64,7 +64,7 @@ const user = {
       })
     },
 
-    // 社交登
+    // 社交登
     SocialLogin2({ commit }, userInfo) {
       const code = userInfo.code
       const state = userInfo.state

+ 1 - 1
yudao-admin-ui/src/views/index_old.vue

@@ -419,7 +419,7 @@
                 <li>修复表格时间为空出现的异常</li>
                 <li>添加Jackson日期反序列化时区配置</li>
                 <li>调整根据用户权限加载菜单数据树形结构</li>
-                <li>调整成功登不恢复按钮,防止多次点击</li>
+                <li>调整成功登不恢复按钮,防止多次点击</li>
                 <li>修改用户个人资料同步缓存信息</li>
                 <li>修复页面同时出现el-upload和Editor不显示处理</li>
                 <li>修复在角色管理页修改菜单权限偶尔未选中问题</li>

+ 3 - 3
yudao-admin-ui/src/views/login.vue

@@ -45,7 +45,7 @@
 </template>
 
 <script>
-import { getCodeImg,socialLoginRedirect } from "@/api/login";
+import { getCodeImg,socialAuthRedirect } from "@/api/login";
 import Cookies from "js-cookie";
 import { encrypt, decrypt } from '@/utils/jsencrypt'
 import {InfApiErrorLogProcessStatusEnum, SysUserSocialTypeEnum} from "@/utils/constants";
@@ -133,14 +133,14 @@ export default {
     },
     doSocialLogin(socialTypeEnum) {
       // console.log("开始Oauth登录...%o", socialTypeEnum.code);
-      // 设置登
+      // 设置登
       this.loading = true;
       // 计算 redirectUri
       const redirectUri = location.origin + '/social-login?type=' + socialTypeEnum.type + '&redirect=' + (this.redirect || "/"); // 重定向不能丢
       // const redirectUri = 'http://127.0.0.1:48080/api/gitee/callback';
       // const redirectUri = 'http://127.0.0.1:48080/api/dingtalk/callback';
       // 进行跳转
-      socialLoginRedirect(socialTypeEnum.type, encodeURIComponent(redirectUri)).then((res) => {
+      socialAuthRedirect(socialTypeEnum.type, encodeURIComponent(redirectUri)).then((res) => {
         // console.log(res.url);
         window.location.href = res.data;
       });

+ 2 - 2
yudao-admin-ui/src/views/socialLogin.vue

@@ -51,7 +51,7 @@ export default {
       },
       loading: false,
       redirect: undefined,
-      // 社交登相关
+      // 社交登相关
       type: undefined,
       code: undefined,
       state: undefined,
@@ -70,7 +70,7 @@ export default {
     // 重定向地址
     this.redirect = this.$route.query.redirect;
     debugger
-    // 社交登相关
+    // 社交登相关
     this.type = this.$route.query.type;
     this.code = this.$route.query.code;
     this.state = this.$route.query.state;

+ 1 - 1
yudao-admin-ui/src/views/system/loginlog/index.vue

@@ -132,7 +132,7 @@ export default {
         }).then(function() {
           return exportLoginLog(queryParams);
         }).then(response => {
-          this.downloadExcel(response, '登日志.xls');
+          this.downloadExcel(response, '登日志.xls');
         })
     }
   }

+ 1 - 1
yudao-admin-ui/src/views/system/session/index.vue

@@ -17,7 +17,7 @@
       <el-table-column label="会话编号" align="center" prop="id" width="300" />
       <el-table-column label="登录名称" align="center" prop="username" width="100" />
       <el-table-column label="部门名称" align="center" prop="deptName" width="100" />
-      <el-table-column label="登地址" align="center" prop="userIp" width="100" />
+      <el-table-column label="登地址" align="center" prop="userIp" width="100" />
       <el-table-column label="userAgent" align="center" prop="userAgent" :show-overflow-tooltip="true" />
       <el-table-column label="登录时间" align="center" prop="createTime" width="180">
         <template slot-scope="scope">

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java

@@ -34,7 +34,7 @@ public class YudaoSecurityAutoConfiguration {
     private SecurityProperties securityProperties;
 
     /**
-     * 处理用户未登拦截的切面的 Bean
+     * 处理用户未登拦截的切面的 Bean
      */
     @Bean
     public PreAuthenticatedAspect preAuthenticatedAspect() {

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java

@@ -131,7 +131,7 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
 
         // 设置每个请求的权限 ①:全局共享规则
         httpSecurity.authorizeRequests()
-                    // 登的接口,可匿名访问
+                    // 登的接口,可匿名访问
                     .antMatchers(api("/login")).anonymous()
                     // 静态资源,可匿名访问
                     .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java

@@ -12,7 +12,7 @@ import java.util.HashSet;
 import java.util.Set;
 
 /**
- * 登用户信息
+ * 登用户信息
  *
  * @author 芋道源码
  */

+ 2 - 2
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/annotations/PreAuthenticated.java

@@ -3,9 +3,9 @@ package cn.iocoder.yudao.framework.security.core.annotations;
 import java.lang.annotation.*;
 
 /**
- * 声明用户需要登
+ * 声明用户需要登
  *
- * 为什么不使用 {@link org.springframework.security.access.prepost.PreAuthorize} 注解,原因是不通过时,抛出的是认证不通过,而不是未登
+ * 为什么不使用 {@link org.springframework.security.access.prepost.PreAuthorize} 注解,原因是不通过时,抛出的是认证不通过,而不是未登
  *
  * @author 芋道源码
  */

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JwtAuthenticationTokenFilter.java

@@ -63,7 +63,7 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
     }
 
     /**
-     * 模拟登用户,方便日常开发调试
+     * 模拟登用户,方便日常开发调试
      *
      * 注意,在线上环境下,一定要关闭该功能!!!
      *

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java

@@ -84,7 +84,7 @@ public class SecurityFrameworkUtils {
     /**
      * 设置当前用户
      *
-     * @param loginUser 登用户
+     * @param loginUser 登用户
      * @param request 请求
      */
     public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) {

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java

@@ -23,7 +23,7 @@ public class DemoFilter extends OncePerRequestFilter {
     protected boolean shouldNotFilter(HttpServletRequest request) {
         String method = request.getMethod();
         return !StrUtil.equalsAnyIgnoreCase(method, "POST", "PUT", "DELETE")  // 写操作时,不进行过滤率
-                || WebFrameworkUtils.getLoginUserId(request) == null; // 非登用户时,不进行过滤
+                || WebFrameworkUtils.getLoginUserId(request) == null; // 非登用户时,不进行过滤
     }
 
     @Override

+ 1 - 1
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/auth/SysAuthService.java

@@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkSer
 /**
  * 认证 Service 接口
  *
- * 提供用户的账号密码登、token 的校验等认证相关的功能
+ * 提供用户的账号密码登、token 的校验等认证相关的功能
  *
  * @author 芋道源码
  */