Просмотр исходного кода

优化管理后台的社交登录

YunaiV 3 лет назад
Родитель
Сommit
8751471aa1

+ 5 - 12
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java

@@ -141,23 +141,16 @@ public class AuthController {
             @ApiImplicitParam(name = "type", value = "社交类型", required = true, dataTypeClass = Integer.class),
             @ApiImplicitParam(name = "redirectUri", value = "回调路径", dataTypeClass = String.class)
     })
-    public CommonResult<String> socialAuthRedirect(@RequestParam("type") Integer type,
+    public CommonResult<String> socialLogin(@RequestParam("type") Integer type,
                                                     @RequestParam("redirectUri") String redirectUri) {
         return CommonResult.success(socialUserService.getAuthorizeUrl(type, redirectUri));
     }
 
-    @PostMapping("/social-quick-login")
-    @ApiOperation("社交快捷登录,使用 code 授权码")
+    @PostMapping("/social-login")
+    @ApiOperation(value = "社交快捷登录,使用 code 授权码", notes = "适合未登录的用户,但是社交账号已绑定用户")
     @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
-    public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialQuickLoginReqVO reqVO) {
-        return success(authService.socialQuickLogin(reqVO));
-    }
-
-    @PostMapping("/social-bind-login")
-    @ApiOperation("社交绑定登录,使用 code 授权码 + 账号密码")
-    @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
-    public CommonResult<AuthLoginRespVO> socialBindLogin(@RequestBody @Valid AuthSocialBindLoginReqVO reqVO) {
-        return success(authService.socialBindLogin(reqVO));
+    public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialLoginReqVO reqVO) {
+        return success(authService.socialLogin(reqVO));
     }
 
 }

+ 29 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthLoginReqVO.java

@@ -1,5 +1,8 @@
 package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
 
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
@@ -8,10 +11,11 @@ import lombok.Data;
 import lombok.NoArgsConstructor;
 import org.hibernate.validator.constraints.Length;
 
+import javax.validation.constraints.AssertTrue;
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.Pattern;
 
-@ApiModel("管理后台 - 账号密码登录 Request VO")
+@ApiModel(value = "管理后台 - 账号密码登录 Request VO", description = "如果登录并绑定社交用户,需要传递 social 开头的参数")
 @Data
 @NoArgsConstructor
 @AllArgsConstructor
@@ -29,6 +33,8 @@ public class AuthLoginReqVO {
     @Length(min = 4, max = 16, message = "密码长度为 4-16 位")
     private String password;
 
+    // ========== 图片验证码相关 ==========
+
     @ApiModelProperty(value = "验证码", required = true, example = "1024", notes = "验证码开启时,需要传递")
     @NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class)
     private String code;
@@ -37,9 +43,31 @@ public class AuthLoginReqVO {
     @NotEmpty(message = "唯一标识不能为空", groups = CodeEnableGroup.class)
     private String uuid;
 
+    // ========== 绑定社交登录时,需要传递如下参数 ==========
+
+    @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值")
+    @InEnum(SocialTypeEnum.class)
+    private Integer socialType;
+
+    @ApiModelProperty(value = "授权码", required = true, example = "1024")
+    private String socialCode;
+
+    @ApiModelProperty(value = "state", required = true, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
+    private String socialState;
+
     /**
      * 开启验证码的 Group
      */
     public interface CodeEnableGroup {}
 
+    @AssertTrue(message = "授权码不能为空")
+    public boolean isSocialCodeValid() {
+        return socialType == null || StrUtil.isNotEmpty(socialCode);
+    }
+
+    @AssertTrue(message = "授权 state 不能为空")
+    public boolean isSocialState() {
+        return socialType == null || StrUtil.isNotEmpty(socialState);
+    }
+
 }

+ 0 - 48
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSocialBindLoginReqVO.java

@@ -1,48 +0,0 @@
-package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
-
-import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
-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 AuthSocialBindLoginReqVO {
-
-    @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 UserSocialTypeEnum 枚举值")
-    @InEnum(SocialTypeEnum.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;
-
-}

+ 3 - 3
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSocialQuickLoginReqVO.java → yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSocialLoginReqVO.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
 
-import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
 import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
@@ -12,12 +12,12 @@ import lombok.NoArgsConstructor;
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
 
-@ApiModel("管理后台 - 社交快捷登录 Request VO,使用 code 授权码")
+@ApiModel("管理后台 - 社交绑定登录 Request VO,使用 code 授权码 + 账号密码")
 @Data
 @NoArgsConstructor
 @AllArgsConstructor
 @Builder
-public class AuthSocialQuickLoginReqVO {
+public class AuthSocialLoginReqVO {
 
     @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 UserSocialTypeEnum 枚举值")
     @InEnum(SocialTypeEnum.class)

+ 1 - 2
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java

@@ -65,8 +65,7 @@ public interface AuthConvert {
         return CollectionUtils.filterList(treeNodeMap.values(), node -> MenuIdEnum.ROOT.getId().equals(node.getParentId()));
     }
 
-    SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialBindLoginReqVO reqVO);
-    SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialQuickLoginReqVO reqVO);
+    SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialLoginReqVO reqVO);
 
     SmsCodeSendReqDTO convert(AuthSmsSendReqVO reqVO);
 

+ 1 - 2
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java

@@ -24,8 +24,7 @@ public class SecurityConfiguration {
                 registry.antMatchers(buildAdminApi("/system/auth/refresh-token")).permitAll();
                 // 社交登陆的接口
                 registry.antMatchers(buildAdminApi("/system/auth/social-auth-redirect")).permitAll();
-                registry.antMatchers(buildAdminApi("/system/auth/social-quick-login")).permitAll();
-                registry.antMatchers(buildAdminApi("/system/auth/social-bind-login")).permitAll();
+                registry.antMatchers(buildAdminApi("/system/auth/social-login")).permitAll();
                 // 登录登录的接口
                 registry.antMatchers(buildAdminApi("/system/auth/sms-login")).permitAll();
                 registry.antMatchers(buildAdminApi("/system/auth/send-sms-code")).permitAll();

+ 1 - 9
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java

@@ -60,15 +60,7 @@ public interface AdminAuthService {
      * @param reqVO 登录信息
      * @return 登录结果
      */
-    AuthLoginRespVO socialQuickLogin(@Valid AuthSocialQuickLoginReqVO reqVO);
-
-    /**
-     * 社交绑定登录,使用 code 授权码 + 账号密码
-     *
-     * @param reqVO 登录信息
-     * @return 登录结果
-     */
-    AuthLoginRespVO socialBindLogin(@Valid AuthSocialBindLoginReqVO reqVO);
+    AuthLoginRespVO socialLogin(@Valid AuthSocialLoginReqVO reqVO);
 
     /**
      * 刷新访问令牌

+ 9 - 14
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java

@@ -8,13 +8,14 @@ import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
 import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
+import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
 import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
 import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
 import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
-import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2ClientConstants;
 import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
 import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
+import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2ClientConstants;
 import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
 import cn.iocoder.yudao.module.system.service.common.CaptchaService;
 import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
@@ -91,6 +92,12 @@ public class AdminAuthServiceImpl implements AdminAuthService {
         // 使用账号密码,进行登录
         AdminUserDO user = authenticate(reqVO.getUsername(), reqVO.getPassword());
 
+        // 如果 socialType 非空,说明需要绑定社交用户
+        if (reqVO.getSocialType() != null) {
+            socialUserService.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
+                    reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState()));
+        }
+
         // 创建 Token 令牌,记录登录日志
         return createTokenAfterLoginSuccess(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
     }
@@ -166,7 +173,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
     }
 
     @Override
-    public AuthLoginRespVO socialQuickLogin(AuthSocialQuickLoginReqVO reqVO) {
+    public AuthLoginRespVO socialLogin(AuthSocialLoginReqVO reqVO) {
         // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号
         Long userId = socialUserService.getBindUserId(UserTypeEnum.ADMIN.getValue(), reqVO.getType(),
                 reqVO.getCode(), reqVO.getState());
@@ -184,18 +191,6 @@ public class AdminAuthServiceImpl implements AdminAuthService {
         return createTokenAfterLoginSuccess(user.getId(), user.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL);
     }
 
-    @Override
-    public AuthLoginRespVO socialBindLogin(AuthSocialBindLoginReqVO reqVO) {
-        // 使用账号密码,进行登录。
-        AdminUserDO user = authenticate(reqVO.getUsername(), reqVO.getPassword());
-
-        // 绑定社交用户
-        socialUserService.bindSocialUser(AuthConvert.INSTANCE.convert(user.getId(), getUserType().getValue(), reqVO));
-
-        // 创建 Token 令牌,记录登录日志
-        return createTokenAfterLoginSuccess(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL);
-    }
-
     @Override
     public AuthLoginRespVO refreshToken(String refreshToken) {
         OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, OAuth2ClientConstants.CLIENT_ID_DEFAULT);

+ 7 - 19
yudao-ui-admin/src/api/login.js

@@ -3,12 +3,15 @@ import {getRefreshToken} from "@/utils/auth";
 import service from "@/utils/request";
 
 // 登录方法
-export function login(username, password, code, uuid) {
+export function login(username, password, code, uuid,
+                      socialType, socialCode, socialState) {
   const data = {
     username,
     password,
     code,
-    uuid
+    uuid,
+    // 社交相关
+    socialType, socialCode, socialState
   }
   return request({
     url: '/system/auth/login',
@@ -51,9 +54,9 @@ export function socialAuthRedirect(type, redirectUri) {
 }
 
 // 社交快捷登录,使用 code 授权码
-export function socialQuickLogin(type, code, state) {
+export function socialLogin(type, code, state) {
   return request({
-    url: '/system/auth/social-quick-login',
+    url: '/system/auth/social-login',
     method: 'post',
     data: {
       type,
@@ -63,21 +66,6 @@ export function socialQuickLogin(type, code, state) {
   })
 }
 
-// 社交绑定登录,使用 code 授权码 + + 账号密码
-export function socialBindLogin(type, code, state, username, password) {
-  return request({
-    url: '/system/auth/social-bind-login',
-    method: 'post',
-    data: {
-      type,
-      code,
-      state,
-      username,
-      password
-    }
-  })
-}
-
 // 获取登录验证码
 export function sendSmsCode(mobile, scene) {
   return request({

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

@@ -1,4 +1,4 @@
-import {login, logout, getInfo, socialQuickLogin, socialBindLogin, smsLogin} from '@/api/login'
+import {login, logout, getInfo, socialLogin, socialBindLogin, smsLogin} from '@/api/login'
 import {getAccessToken, setToken, removeToken, getRefreshToken} from '@/utils/auth'
 
 const user = {
@@ -38,8 +38,12 @@ const user = {
       const password = userInfo.password
       const code = userInfo.code
       const uuid = userInfo.uuid
+      const socialCode = userInfo.socialCode
+      const socialState = userInfo.socialState
+      const socialType = userInfo.socialType
       return new Promise((resolve, reject) => {
-        login(username, password, code, uuid).then(res => {
+        login(username, password, code, uuid,
+          socialType, socialCode, socialState).then(res => {
           res = res.data;
           // 设置 token
           setToken(res)
@@ -56,7 +60,7 @@ const user = {
       const state = userInfo.state
       const type = userInfo.type
       return new Promise((resolve, reject) => {
-        socialQuickLogin(type, code, state).then(res => {
+        socialLogin(type, code, state).then(res => {
           res = res.data;
           // 设置 token
           setToken(res)
@@ -67,25 +71,7 @@ const user = {
       })
     },
 
-    // 社交登录
-    SocialLogin2({ commit }, userInfo) {
-      const code = userInfo.code
-      const state = userInfo.state
-      const type = userInfo.type
-      const username = userInfo.username.trim()
-      const password = userInfo.password
-      return new Promise((resolve, reject) => {
-        socialBindLogin(type, code, state, username, password).then(res => {
-          res = res.data;
-          // 设置 token
-          setToken(res)
-          resolve()
-        }).catch(error => {
-          reject(error)
-        })
-      })
-    },
-    // 登录
+    // 短信登录
     SmsLogin({ commit }, userInfo) {
       const mobile = userInfo.mobile.trim()
       const mobileCode = userInfo.mobileCode

+ 11 - 5
yudao-ui-admin/src/views/socialLogin.vue

@@ -87,6 +87,8 @@ export default {
         username: "admin",
         password: "admin123",
         rememberMe: false,
+        code: "",
+        uuid: "",
       },
       loginRules: {
         username: [
@@ -170,16 +172,20 @@ export default {
             removeUsername()
             removePassword()
           }
-          this.$store.dispatch("SocialLogin2", {
-            code: this.code,
-            state: this.state,
-            type: this.type,
+          this.$store.dispatch("Login", {
+            socialCode: this.code,
+            socialState: this.state,
+            socialType: this.type,
+            // 账号密码登录
             username: this.loginForm.username,
-            password: this.loginForm.password
+            password: this.loginForm.password,
+            code: this.loginForm.code,
+            uuid: this.loginForm.uuid,
           }).then(() => {
             this.$router.push({ path: this.redirect || "/" }).catch(()=>{});
           }).catch(() => {
             this.loading = false;
+            this.getCode()
           });
         }
       });