接口名改成绑定,和登录区分,适配客户端授权,支持选择租户切换授权平台登录

This commit is contained in:
thiszhc 2023-07-01 02:30:09 +08:00
parent 7bde8054d9
commit ff1f3bdc16
4 changed files with 70 additions and 25 deletions

View File

@ -1,8 +1,10 @@
package org.dromara.web.controller; package org.dromara.web.controller;
import cn.dev33.satoken.annotation.SaIgnore; import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -115,19 +117,36 @@ public class AuthController {
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@GetMapping("/social-login") @GetMapping("/social-login")
public R<String> socialLogin(String source, AuthCallback callback) { public R<String> socialLogin(String source,
String loginType,
String tenantId,
String clientId,
String grantType,
AuthCallback callback) {
SocialLoginConfigProperties obj = socialProperties.getType().get(source); SocialLoginConfigProperties obj = socialProperties.getType().get(source);
if (ObjectUtil.isNull(obj)) { if (ObjectUtil.isNull(obj)) {
return R.fail(source + "平台账号暂不支持"); return R.fail(source + "平台账号暂不支持");
} }
SysClient client = clientService.queryByClientId(clientId);
// 查询不到 client client 内不包含 grantType
if (ObjectUtil.isNull(client) || !StringUtils.contains(client.getGrantType(), grantType)) {
log.info("客户端id: {} 认证类型:{} 异常!.", clientId, grantType);
return R.fail(MessageUtils.message("auth.grant.type.error"));
}
AuthRequest authRequest = SocialUtils.getAuthRequest(source, AuthRequest authRequest = SocialUtils.getAuthRequest(source,
obj.getClientId(), obj.getClientId(),
obj.getClientSecret(), obj.getClientSecret(),
obj.getRedirectUri()); obj.getRedirectUri());
AuthResponse<AuthUser> response = authRequest.login(callback); AuthResponse<AuthUser> response = authRequest.login(callback);
return loginService.socialLogin(source, response); //判断loginType是否为login,如果是login则为登录否则为绑定
if (StrUtil.equals(loginType, "login")) {
return loginService.socialLogin(tenantId , response);
} else {
return loginService.sociaRegister(response);
}
} }
/** /**
* 取消授权 * 取消授权
* *

View File

@ -5,6 +5,7 @@ import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -66,47 +67,65 @@ public class SysLoginService {
private final ISysSocialService sysSocialService; private final ISysSocialService sysSocialService;
private final SysUserMapper userMapper; private final SysUserMapper userMapper;
/** /**
* 社交登录 * 社交登录
* *
* @param source 登录来源 * @param tenantId 租户id
* @param authUser 授权响应实体 * @param authUser 授权响应实体
* @return 统一响应实体 * @return 统一响应实体
*/ */
public R<String> socialLogin(String source, AuthResponse<AuthUser> authUser) { public R<String> socialLogin(String tenantId, AuthResponse<AuthUser> authUser) {
// 判断授权响应是否成功 // 判断授权响应是否成功
if (!authUser.ok()) { if (!authUser.ok()) {
return R.fail("对不起,授权信息验证不通过,请退出重试!"); return R.fail("对不起,授权信息验证不通过,请退出重试!");
} }
AuthUser authUserData = authUser.getData(); AuthUser authUserData = authUser.getData();
SysSocialVo social = sysSocialService.selectByAuthId(authUserData.getSource() + authUserData.getUuid()); SysSocialVo social = sysSocialService.selectByAuthId(authUserData.getSource() + authUserData.getUuid());
//验证授权表里面的租户id是否包含当前租户id
if (ObjectUtil.isNotNull(social) && StrUtil.isNotBlank(social.getTenantId())
&& !social.getTenantId().contains(tenantId)) {
return R.fail("对不起,你没有权限登录当前租户!");
}
if (ObjectUtil.isNotNull(social)) { if (ObjectUtil.isNotNull(social)) {
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>() SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getUserId, social.getUserId())); .eq(SysUser::getUserId, social.getUserId()));
// 执行登录和记录登录信息操作 // 执行登录
return loginAndRecord(user.getTenantId(), user.getUserName(), authUserData); return loginAndRecord(user.getTenantId(), user.getUserName(), authUserData);
} else { } else {
// 判断是否已登录 return R.fail("你还没有绑定第三方账号,绑定后才可以登录!");
if (!StpUtil.isLogin()) {
return R.fail("授权失败,请先登录才能绑定");
}
SysSocialBo bo = new SysSocialBo();
bo.setUserId(LoginHelper.getUserId());
bo.setAuthId(authUserData.getSource() + authUserData.getUuid());
bo.setSource(authUserData.getSource());
bo.setUserName(authUserData.getUsername());
bo.setNickName(authUserData.getNickname());
bo.setAvatar(authUserData.getAvatar());
bo.setOpenId(authUserData.getUuid());
BeanUtils.copyProperties(authUserData.getToken(), bo);
sysSocialService.insertByBo(bo);
SysUserVo sysUser = loadUserByUsername(LoginHelper.getTenantId(), LoginHelper.getUsername());
// 执行登录和记录登录信息操作
return loginAndRecord(sysUser.getTenantId(), sysUser.getUserName(), authUserData);
} }
} }
/**
* 绑定第三方用户
* @param authUser 授权响应实体
* @return 统一响应实体
*/
public R<String> sociaRegister(AuthResponse<AuthUser> authUser){
if (!authUser.ok()) {
return R.fail("对不起,授权信息验证不通过,请退出重试!");
}
// 判断是否已登录
if (!StpUtil.isLogin()) {
return R.fail("授权失败,登录状态异常!");
}
AuthUser authUserData = authUser.getData();
SysSocialBo bo = new SysSocialBo();
bo.setUserId(LoginHelper.getUserId());
bo.setAuthId(authUserData.getSource() + authUserData.getUuid());
bo.setSource(authUserData.getSource());
bo.setUserName(authUserData.getUsername());
bo.setNickName(authUserData.getNickname());
bo.setAvatar(authUserData.getAvatar());
bo.setOpenId(authUserData.getUuid());
BeanUtils.copyProperties(authUserData.getToken(), bo);
return sysSocialService.insertByBo(bo) ? R.ok("绑定成功!"):R.fail("绑定失败!");
}
/** /**
* 执行登录和记录登录信息操作 * 执行登录和记录登录信息操作
* *
@ -124,7 +143,7 @@ public class SysLoginService {
LoginHelper.login(buildLoginUser(user), model); LoginHelper.login(buildLoginUser(user), model);
recordLogininfor(user.getTenantId(), userName, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")); recordLogininfor(user.getTenantId(), userName, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
recordLoginInfo(user.getUserId()); recordLoginInfo(user.getUserId());
return R.ok(StpUtil.getTokenValue()); return R.ok( "登录成功", StpUtil.getTokenValue());
} }
/** /**

View File

@ -103,4 +103,9 @@ public class LoginBody {
@NotBlank(message = "{xcx.code.not.blank}", groups = {WechatGroup.class}) @NotBlank(message = "{xcx.code.not.blank}", groups = {WechatGroup.class})
private String xcxCode; private String xcxCode;
/**
* 第三方登录平台
*/
private String source;
} }

View File

@ -45,13 +45,15 @@ public class SocialUtils {
case "alipay" -> case "alipay" ->
// 支付宝在创建回调地址时不允许使用localhost或者127.0.0.1所以这儿的回调地址使用的局域网内的ip // 支付宝在创建回调地址时不允许使用localhost或者127.0.0.1所以这儿的回调地址使用的局域网内的ip
authRequest = new AuthAlipayRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) authRequest = new AuthAlipayRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret)
.alipayPublicKey("").redirectUri(redirectUri).build()); .redirectUri(redirectUri).build());
case "qq" -> case "qq" ->
authRequest = new AuthQqRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) authRequest = new AuthQqRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret)
.redirectUri(redirectUri).build()); .redirectUri(redirectUri).build());
case "wechat_open" -> authRequest = new AuthWeChatOpenRequest(AuthConfig.builder().clientId(clientId) case "wechat_open" -> authRequest = new AuthWeChatOpenRequest(AuthConfig.builder().clientId(clientId)
.clientSecret(clientSecret).redirectUri(redirectUri).build()); .clientSecret(clientSecret).redirectUri(redirectUri).build());
case "csdn" -> case "csdn" ->
//注意,经咨询CSDN官方客服得知CSDN的授权开放平台已经下线如果以前申请过的应用可以继续使用但是不再支持申请新的应用
// so, 本项目中的CSDN登录只能针对少部分用户使用了
authRequest = new AuthCsdnRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret) authRequest = new AuthCsdnRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret)
.redirectUri(redirectUri).build()); .redirectUri(redirectUri).build());
case "taobao" -> case "taobao" ->