diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java index e42a5dfa5..ce44d2153 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java +++ b/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 socialAuthRedirect(@RequestParam("type") Integer type, + public CommonResult 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 socialQuickLogin(@RequestBody @Valid AuthSocialQuickLoginReqVO reqVO) { - return success(authService.socialQuickLogin(reqVO)); - } - - @PostMapping("/social-bind-login") - @ApiOperation("社交绑定登录,使用 code 授权码 + 账号密码") - @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 - public CommonResult socialBindLogin(@RequestBody @Valid AuthSocialBindLoginReqVO reqVO) { - return success(authService.socialBindLogin(reqVO)); + public CommonResult socialQuickLogin(@RequestBody @Valid AuthSocialLoginReqVO reqVO) { + return success(authService.socialLogin(reqVO)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthLoginReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthLoginReqVO.java index 0ecd3d670..67e80d24a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthLoginReqVO.java +++ b/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); + } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSocialBindLoginReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSocialBindLoginReqVO.java deleted file mode 100644 index cefe40d14..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSocialBindLoginReqVO.java +++ /dev/null @@ -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; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSocialQuickLoginReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSocialLoginReqVO.java similarity index 89% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSocialQuickLoginReqVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSocialLoginReqVO.java index 4b7ebb175..e52a49288 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSocialQuickLoginReqVO.java +++ b/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) diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java index 62784defa..38e84ea1d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java +++ b/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); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java index c81809b2e..5b1114fb7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java +++ b/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(); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java index 3a53c1aa3..52796ec2f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java +++ b/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); /** * 刷新访问令牌 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java index 517e058f1..99e0ff1e6 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java +++ b/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); diff --git a/yudao-ui-admin/src/api/login.js b/yudao-ui-admin/src/api/login.js index a76decf17..390f66900 100644 --- a/yudao-ui-admin/src/api/login.js +++ b/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({ diff --git a/yudao-ui-admin/src/store/modules/user.js b/yudao-ui-admin/src/store/modules/user.js index 7c3df753b..10deeeebc 100644 --- a/yudao-ui-admin/src/store/modules/user.js +++ b/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 diff --git a/yudao-ui-admin/src/views/socialLogin.vue b/yudao-ui-admin/src/views/socialLogin.vue index 1d18e6011..1ae4a58f3 100644 --- a/yudao-ui-admin/src/views/socialLogin.vue +++ b/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() }); } });