diff --git a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java index 2ed4ed49..abbfae5d 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java @@ -103,22 +103,21 @@ public class AuthController { } /** - * 第三方登录回调业务处理 - * 绑定授权 - * @param loginBody + * 第三方登录回调业务处理 绑定授权 + * + * @param loginBody 请求体 * @return 结果 */ - @SuppressWarnings("unchecked") @PostMapping("/social/callback") - public R socialLogin(@RequestBody LoginBody loginBody) { - // 获取第三方登录信息 - AuthResponse response = SocialUtils.loginAuth(loginBody, socialProperties); - AuthUser authUserData = response.getData(); - // 判断授权响应是否成功 - if (!response.ok()) { - return R.fail(response.getMsg()); - } - return loginService.sociaRegister(authUserData); + public R socialCallback(@RequestBody LoginBody loginBody) { + // 获取第三方登录信息 + AuthResponse response = SocialUtils.loginAuth(loginBody, socialProperties); + AuthUser authUserData = response.getData(); + // 判断授权响应是否成功 + if (!response.ok()) { + return R.fail(response.getMsg()); + } + return loginService.sociaRegister(authUserData); } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java index 4da2bb02..5aa1f335 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java @@ -67,13 +67,13 @@ public class SysLoginService { private final SysUserMapper userMapper; - /** * 绑定第三方用户 + * * @param authUserData 授权响应实体 * @return 统一响应实体 */ - public R sociaRegister(AuthUser authUserData ){ + public R sociaRegister(AuthUser authUserData) { SysSocialBo bo = new SysSocialBo(); bo.setUserId(LoginHelper.getUserId()); bo.setAuthId(authUserData.getSource() + authUserData.getUuid()); @@ -123,9 +123,9 @@ public class SysLoginService { private SysUserVo loadUserByUsername(String tenantId, String username) { SysUser user = userMapper.selectOne(new LambdaQueryWrapper() - .select(SysUser::getUserName, SysUser::getStatus) - .eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId) - .eq(SysUser::getUserName, username)); + .select(SysUser::getUserName, SysUser::getStatus) + .eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId) + .eq(SysUser::getUserName, username)); if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", username); throw new UserException("user.not.exists", username); @@ -225,7 +225,7 @@ public class SysLoginService { log.info("登录租户:{} 已被停用.", tenantId); throw new TenantException("tenant.blocked"); } else if (ObjectUtil.isNotNull(tenant.getExpireTime()) - && new Date().after(tenant.getExpireTime())) { + && new Date().after(tenant.getExpireTime())) { log.info("登录租户:{} 已超过有效期.", tenantId); throw new TenantException("tenant.expired"); } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/socialAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java similarity index 66% rename from ruoyi-admin/src/main/java/org/dromara/web/service/impl/socialAuthStrategy.java rename to ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java index c7599eb0..f71bc9fc 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/socialAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java @@ -11,17 +11,21 @@ import me.zhyd.oauth.model.AuthResponse; import me.zhyd.oauth.model.AuthUser; import org.dromara.common.core.constant.Constants; import org.dromara.common.core.domain.model.LoginBody; -import org.dromara.common.core.domain.model.SocialLogin; +import org.dromara.common.core.domain.model.LoginUser; +import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.exception.user.UserException; import org.dromara.common.core.utils.MessageUtils; import org.dromara.common.core.utils.ValidatorUtils; import org.dromara.common.core.validate.auth.SocialGroup; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.social.config.properties.SocialProperties; import org.dromara.common.social.utils.SocialUtils; +import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.system.domain.SysClient; import org.dromara.system.domain.SysUser; import org.dromara.system.domain.vo.SysSocialVo; +import org.dromara.system.domain.vo.SysUserVo; import org.dromara.system.mapper.SysUserMapper; import org.dromara.system.service.ISysSocialService; import org.dromara.web.domain.vo.LoginVo; @@ -37,7 +41,7 @@ import org.springframework.stereotype.Service; @Slf4j @Service("social" + IAuthStrategy.BASE_NAME) @RequiredArgsConstructor -public class socialAuthStrategy implements IAuthStrategy { +public class SocialAuthStrategy implements IAuthStrategy { private final SocialProperties socialProperties; private final ISysSocialService sysSocialService; @@ -52,13 +56,14 @@ public class socialAuthStrategy implements IAuthStrategy { /** * 登录-第三方授权登录 - * @param clientId 客户端id + * + * @param clientId 客户端id * @param loginBody 登录信息 - * @param client 客户端信息 + * @param client 客户端信息 */ @Override public LoginVo login(String clientId, LoginBody loginBody, SysClient client) { - AuthResponse response = SocialUtils.loginAuth(loginBody,socialProperties); + AuthResponse response = SocialUtils.loginAuth(loginBody, socialProperties); if (!response.ok()) { throw new ServiceException(response.getMsg()); } @@ -66,30 +71,19 @@ public class socialAuthStrategy implements IAuthStrategy { SysSocialVo social = sysSocialService.selectByAuthId(authUserData.getSource() + authUserData.getUuid()); if (!ObjectUtil.isNotNull(social)) { throw new ServiceException("你还没有绑定第三方账号,绑定后才可以登录!"); - }//验证授权表里面的租户id是否包含当前租户id - if (ObjectUtil.isNotNull(social) && StrUtil.isNotBlank(social.getTenantId()) - && !social.getTenantId().contains(loginBody.getTenantId())) { + } + // 验证授权表里面的租户id是否包含当前租户id + String tenantId = social.getTenantId(); + if (ObjectUtil.isNotNull(social) && StrUtil.isNotBlank(tenantId) + && !tenantId.contains(loginBody.getTenantId())) { throw new ServiceException("对不起,你没有权限登录当前租户!"); } - return loadinUser(social, client); - } - /** - * 登录用户信息 - * - * @param social - * @param client - * @return - */ - private LoginVo loadinUser(SysSocialVo social, SysClient client) { - SysUser user = userMapper.selectOne(new LambdaQueryWrapper() - .eq(SysUser::getUserId, social.getUserId())); - SocialLogin loginUser = new SocialLogin(); - loginUser.setUserId(user.getUserId()); - loginUser.setTenantId(user.getTenantId()); - loginUser.setUsername(user.getUserName()); - loginUser.setUserType(user.getUserType()); - // 执行登录 + // 查找用户 + SysUserVo user = loadUser(tenantId, social.getUserId()); + + // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了 + LoginUser loginUser = loginService.buildLoginUser(user); SaLoginModel model = new SaLoginModel(); model.setDevice(client.getDeviceType()); // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置 @@ -106,4 +100,22 @@ public class socialAuthStrategy implements IAuthStrategy { return loginVo; } + private SysUserVo loadUser(String tenantId, Long userId) { + SysUser user = userMapper.selectOne(new LambdaQueryWrapper() + .select(SysUser::getUserName, SysUser::getStatus) + .eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId) + .eq(SysUser::getUserId, userId)); + if (ObjectUtil.isNull(user)) { + log.info("登录用户:{} 不存在.", ""); + throw new UserException("user.not.exists", ""); + } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + log.info("登录用户:{} 已被停用.", ""); + throw new UserException("user.blocked", ""); + } + if (TenantHelper.isEnable()) { + return userMapper.selectTenantUserByUserName(user.getUserName(), tenantId); + } + return userMapper.selectUserByUserName(user.getUserName()); + } + } diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialProperties.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialProperties.java index 273fe7b7..cb8337b1 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialProperties.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialProperties.java @@ -1,7 +1,6 @@ package org.dromara.common.social.config.properties; import lombok.Data; -import org.springframework.boot.autoconfigure.cache.CacheProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @@ -20,7 +19,7 @@ public class SocialProperties { /** * 是否启用 */ - private boolean enabled; + private Boolean enabled; /** * 授权类型 @@ -30,11 +29,6 @@ public class SocialProperties { /** * 授权过期时间 */ - private long timeout; - - /** - * 授权缓存配置 - */ - private CacheProperties cache = new CacheProperties(); + private Long timeout; } diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/AuthRedisStateCache.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/AuthRedisStateCache.java index d2a48431..ae58348e 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/AuthRedisStateCache.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/AuthRedisStateCache.java @@ -7,6 +7,9 @@ import org.dromara.common.social.config.properties.SocialProperties; import java.time.Duration; +/** + * 授权状态缓存 + */ @AllArgsConstructor public class AuthRedisStateCache implements AuthStateCache { diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java index f24ea04c..5ca2a5e5 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java @@ -17,6 +17,8 @@ import org.dromara.common.social.config.properties.SocialProperties; * @author thiszhc */ public class SocialUtils { + + @SuppressWarnings("unchecked") public static AuthResponse loginAuth(LoginBody loginBody, SocialProperties socialProperties) throws AuthException { AuthRequest authRequest = getAuthRequest(loginBody.getSource(), socialProperties); AuthCallback callback = new AuthCallback(); @@ -25,7 +27,7 @@ public class SocialUtils { return authRequest.login(callback); } - public static AuthRequest getAuthRequest(String source,SocialProperties socialProperties) throws AuthException { + public static AuthRequest getAuthRequest(String source, SocialProperties socialProperties) throws AuthException { SocialLoginConfigProperties obj = socialProperties.getType().get(source); if (ObjectUtil.isNull(obj)) { throw new AuthException("不支持的第三方登录类型"); @@ -33,106 +35,32 @@ public class SocialUtils { String clientId = obj.getClientId(); String clientSecret = obj.getClientSecret(); String redirectUri = obj.getRedirectUri(); - AuthRequest authRequest = null; - switch (source.toLowerCase()) { - case "dingtalk" -> - authRequest = new AuthDingTalkRequest(AuthConfig.builder() - .clientId(clientId) - .clientSecret(clientSecret) - .redirectUri(redirectUri) - .build()); - case "baidu" -> - authRequest = new AuthBaiduRequest(AuthConfig.builder() - .clientId(clientId) - .clientSecret(clientSecret) - .redirectUri(redirectUri) - .build()); - case "github" -> - authRequest = new AuthGithubRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "gitee" -> - authRequest = new AuthGiteeRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "weibo" -> - authRequest = new AuthWeiboRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "coding" -> - authRequest = new AuthCodingRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "oschina" -> - authRequest = new AuthOschinaRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "alipay" -> - // 支付宝在创建回调地址时,不允许使用localhost或者127.0.0.1,所以这儿的回调地址使用的局域网内的ip - authRequest = new AuthAlipayRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "qq" -> - authRequest = new AuthQqRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "wechat_open" -> authRequest = new AuthWeChatOpenRequest(AuthConfig.builder().clientId(clientId) - .clientSecret(clientSecret).redirectUri(redirectUri).build()); - case "csdn" -> - //注意,经咨询CSDN官方客服得知,CSDN的授权开放平台已经下线。如果以前申请过的应用,可以继续使用,但是不再支持申请新的应用。 - // so, 本项目中的CSDN登录只能针对少部分用户使用了 - authRequest = new AuthCsdnRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "taobao" -> - authRequest = new AuthTaobaoRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "douyin" -> - authRequest = new AuthDouyinRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "linkedin" -> - authRequest = new AuthLinkedinRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "microsoft" -> authRequest = new AuthMicrosoftRequest(AuthConfig.builder().clientId(clientId) - .clientSecret(clientSecret).redirectUri(redirectUri).build()); - case "mi" -> - authRequest = new AuthMiRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "toutiao" -> - authRequest = new AuthToutiaoRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "teambition" -> authRequest = new AuthTeambitionRequest(AuthConfig.builder().clientId(clientId) - .clientSecret(clientSecret).redirectUri(redirectUri).build()); - case "pinterest" -> authRequest = new AuthPinterestRequest(AuthConfig.builder().clientId(clientId) - .clientSecret(clientSecret).redirectUri(redirectUri).build()); - case "renren" -> - authRequest = new AuthRenrenRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "stack_overflow" -> authRequest = new AuthStackOverflowRequest(AuthConfig.builder().clientId(clientId) - .clientSecret(clientSecret).redirectUri(redirectUri).stackOverflowKey("").build()); - case "huawei" -> - authRequest = new AuthHuaweiRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "wechat_enterprise" -> - authRequest = new AuthWeChatEnterpriseQrcodeRequest(AuthConfig.builder().clientId(clientId) - .clientSecret(clientSecret).redirectUri(redirectUri).agentId("").build()); - case "kujiale" -> - authRequest = new AuthKujialeRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "gitlab" -> - authRequest = new AuthGitlabRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "meituan" -> - authRequest = new AuthMeituanRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "eleme" -> - authRequest = new AuthElemeRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "wechat_mp" -> - authRequest = new AuthWeChatMpRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - case "aliyun" -> - authRequest = new AuthAliyunRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) - .redirectUri(redirectUri).build()); - default -> { - } - } - if (null == authRequest) { - throw new AuthException("未获取到有效的Auth配置"); - } - return authRequest; + return switch (source.toLowerCase()) { + case "dingtalk" -> new AuthDingTalkRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "baidu" -> new AuthBaiduRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "github" -> new AuthGithubRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "gitee" -> new AuthGiteeRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "weibo" -> new AuthWeiboRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "coding" -> new AuthCodingRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "oschina" -> new AuthOschinaRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + // 支付宝在创建回调地址时,不允许使用localhost或者127.0.0.1,所以这儿的回调地址使用的局域网内的ip + // 使用支付宝需要提供alipay公钥 + // case "alipay" -> new AuthAlipayRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build(), alipayPublicKey); + case "qq" -> new AuthQqRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "wechat_open" -> new AuthWeChatOpenRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "taobao" -> new AuthTaobaoRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "douyin" -> new AuthDouyinRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "linkedin" -> new AuthLinkedinRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "microsoft" -> new AuthMicrosoftRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "renren" -> new AuthRenrenRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "stack_overflow" -> new AuthStackOverflowRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).stackOverflowKey("").build()); + case "huawei" -> new AuthHuaweiRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "wechat_enterprise" -> new AuthWeChatEnterpriseQrcodeRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).agentId("").build()); + case "gitlab" -> new AuthGitlabRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "wechat_mp" -> new AuthWeChatMpRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + case "aliyun" -> new AuthAliyunRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build()); + default -> throw new AuthException("未获取到有效的Auth配置"); + }; } }