!370 扩展第三方登录授权功能
* add 查看授权列表 * 优化第三方授权登录 * 第三方授权登录,加上配置 * 优化,第三方授权登录 * 新增加第三方登录授权功能
This commit is contained in:
commit
50fbfe2cb4
8
pom.xml
8
pom.xml
@ -39,6 +39,7 @@
|
||||
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
|
||||
<lombok.version>1.18.26</lombok.version>
|
||||
<bouncycastle.version>1.72</bouncycastle.version>
|
||||
<justauth.version>1.16.5</justauth.version>
|
||||
<!-- 离线IP地址定位库 -->
|
||||
<ip2region.version>2.7.0</ip2region.version>
|
||||
|
||||
@ -110,6 +111,13 @@
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- JustAuth 的依赖配置-->
|
||||
<dependency>
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>${justauth.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- common 的依赖配置-->
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
|
@ -43,6 +43,12 @@
|
||||
<artifactId>ruoyi-common-doc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-social</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-system</artifactId>
|
||||
@ -76,6 +82,12 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- skywalking 整合 logback -->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.apache.skywalking</groupId>-->
|
||||
|
@ -2,9 +2,15 @@ package org.dromara.web.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.request.AuthRequest;
|
||||
import me.zhyd.oauth.utils.AuthStateUtils;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.domain.model.EmailLoginBody;
|
||||
import org.dromara.common.core.domain.model.LoginBody;
|
||||
@ -13,9 +19,13 @@ import org.dromara.common.core.domain.model.SmsLoginBody;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.social.config.properties.SocialLoginConfigProperties;
|
||||
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.bo.SysTenantBo;
|
||||
import org.dromara.system.domain.vo.SysTenantVo;
|
||||
import org.dromara.system.service.ISocialUserService;
|
||||
import org.dromara.system.service.ISysConfigService;
|
||||
import org.dromara.system.service.ISysTenantService;
|
||||
import org.dromara.web.domain.vo.LoginTenantVo;
|
||||
@ -26,6 +36,7 @@ import org.dromara.web.service.SysRegisterService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
@ -41,10 +52,14 @@ import java.util.List;
|
||||
@RequestMapping("/auth")
|
||||
public class AuthController {
|
||||
|
||||
private final SocialProperties socialProperties;
|
||||
private final SysLoginService loginService;
|
||||
private final SysRegisterService registerService;
|
||||
private final ISysConfigService configService;
|
||||
private final ISysTenantService tenantService;
|
||||
private final ISocialUserService socialUserService;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 登录方法
|
||||
@ -115,6 +130,60 @@ public class AuthController {
|
||||
return R.ok(loginVo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 认证授权
|
||||
* @param source
|
||||
*/
|
||||
@GetMapping("/binding/{source}")
|
||||
@ResponseBody
|
||||
public R<LoginVo> authBinding(@PathVariable("source") String source, HttpServletRequest request){
|
||||
SocialLoginConfigProperties obj = socialProperties.getType().get(source);
|
||||
if (ObjectUtil.isNull(obj)){
|
||||
return R.fail(source + "平台账号暂不支持");
|
||||
}
|
||||
AuthRequest authRequest = SocialUtils.getAuthRequest(source,
|
||||
obj.getClientId(),
|
||||
obj.getClientSecret(),
|
||||
obj.getRedirectUri());
|
||||
String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
|
||||
return R.ok(authorizeUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 第三方登录回调业务处理
|
||||
* @param source
|
||||
* @param callback
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@GetMapping("/social-login/{source}")
|
||||
public R<String> socialLogin(@PathVariable("source") String source, AuthCallback callback, HttpServletRequest request) throws IOException {
|
||||
SocialLoginConfigProperties obj = socialProperties.getType().get(source);
|
||||
if (ObjectUtil.isNull(obj)){
|
||||
return R.fail(source + "平台账号暂不支持");
|
||||
}
|
||||
AuthRequest authRequest = SocialUtils.getAuthRequest(source,
|
||||
obj.getClientId(),
|
||||
obj.getClientSecret(),
|
||||
obj.getRedirectUri());
|
||||
AuthResponse<AuthUser> response = authRequest.login(callback);
|
||||
return loginService.socialLogin(source, response, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消授权
|
||||
* @param socialId
|
||||
*/
|
||||
@DeleteMapping(value = "/unlock/{socialId}")
|
||||
public R<Void> unlockSocial(@PathVariable Long socialId)
|
||||
{
|
||||
Boolean rows = socialUserService.deleteWithValidById(socialId);
|
||||
return rows ? R.ok() : R.fail("取消授权失败");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
|
@ -6,11 +6,15 @@ import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import org.dromara.common.core.constant.Constants;
|
||||
import org.dromara.common.core.constant.GlobalConstants;
|
||||
import org.dromara.common.core.constant.TenantConstants;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.domain.dto.RoleDTO;
|
||||
import org.dromara.common.core.domain.model.LoginUser;
|
||||
import org.dromara.common.core.domain.model.XcxLoginUser;
|
||||
@ -29,14 +33,20 @@ import org.dromara.common.tenant.exception.TenantException;
|
||||
import org.dromara.common.tenant.helper.TenantHelper;
|
||||
import org.dromara.common.web.config.properties.CaptchaProperties;
|
||||
import org.dromara.system.domain.SysUser;
|
||||
import org.dromara.system.domain.bo.SocialUserBo;
|
||||
import org.dromara.system.domain.vo.SocialUserVo;
|
||||
import org.dromara.system.domain.vo.SysTenantVo;
|
||||
import org.dromara.system.domain.vo.SysUserVo;
|
||||
import org.dromara.system.mapper.SysUserMapper;
|
||||
import org.dromara.system.service.ISocialUserService;
|
||||
import org.dromara.system.service.ISysPermissionService;
|
||||
import org.dromara.system.service.ISysTenantService;
|
||||
import org.dromara.system.service.ISysUserService;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@ -53,6 +63,7 @@ import java.util.function.Supplier;
|
||||
public class SysLoginService {
|
||||
|
||||
private final SysUserMapper userMapper;
|
||||
private final ISocialUserService socialUserService;
|
||||
private final CaptchaProperties captchaProperties;
|
||||
private final ISysPermissionService permissionService;
|
||||
private final ISysTenantService tenantService;
|
||||
@ -154,6 +165,63 @@ public class SysLoginService {
|
||||
return StpUtil.getTokenValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 社交登录
|
||||
*
|
||||
* @param source 登录来源
|
||||
* @param authUser 授权响应实体
|
||||
* @param request Http请求对象
|
||||
* @return 统一响应实体
|
||||
*/
|
||||
public R<String> socialLogin(String source, AuthResponse<AuthUser> authUser, HttpServletRequest request) {
|
||||
// 判断授权响应是否成功
|
||||
if (!authUser.ok()) {
|
||||
return R.fail("对不起,授权信息验证不通过,请退出重试!");
|
||||
}
|
||||
AuthUser authUserData = authUser.getData();
|
||||
SocialUserVo user = socialUserService.selectSocialUserByAuthId(authUserData.getSource() + authUserData.getUuid());
|
||||
if (ObjectUtil.isNotNull(user)) {
|
||||
//执行登录和记录登录信息操作
|
||||
return loginAndRecord(user.getTenantId(), user.getUserName(), authUserData);
|
||||
} else {
|
||||
// 判断是否已登录
|
||||
if (LoginHelper.getUserId() == null) {
|
||||
return R.fail("授权失败,请先登录才能绑定");
|
||||
}
|
||||
SocialUserBo socialUserBo = new SocialUserBo();
|
||||
socialUserBo.setUserId(LoginHelper.getUserId());
|
||||
socialUserBo.setAuthId(authUserData.getSource() + authUserData.getUuid());
|
||||
socialUserBo.setSource(authUserData.getSource());
|
||||
socialUserBo.setUserName(authUserData.getUsername());
|
||||
socialUserBo.setNickName(authUserData.getNickname());
|
||||
socialUserBo.setAvatar(authUserData.getAvatar());
|
||||
socialUserBo.setOpenId(authUserData.getUuid());
|
||||
BeanUtils.copyProperties(authUserData.getToken(), socialUserBo);
|
||||
|
||||
socialUserService.insertByBo(socialUserBo);
|
||||
SysUserVo lodingData = loadUserByUsername(LoginHelper.getTenantId(), LoginHelper.getUsername());
|
||||
//执行登录和记录登录信息操作
|
||||
return loginAndRecord(lodingData.getTenantId(), socialUserBo.getUserName(), authUserData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行登录和记录登录信息操作
|
||||
*
|
||||
* @param tenantId 租户ID
|
||||
* @param userName 用户名
|
||||
* @param authUser 授权用户信息
|
||||
* @return 统一响应实体
|
||||
*/
|
||||
private R<String> loginAndRecord(String tenantId, String userName, AuthUser authUser) {
|
||||
checkTenant(tenantId);
|
||||
SysUserVo dbUser = loadUserByUsername(tenantId, userName);
|
||||
LoginHelper.loginByDevice(buildLoginUser(dbUser), DeviceType.SOCIAL);
|
||||
recordLogininfor(dbUser.getTenantId(), userName, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
|
||||
recordLoginInfo(dbUser.getUserId());
|
||||
return R.ok(StpUtil.getTokenValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
@ -235,9 +303,9 @@ public class SysLoginService {
|
||||
|
||||
private SysUserVo loadUserByUsername(String tenantId, String username) {
|
||||
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
|
||||
.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);
|
||||
@ -253,9 +321,9 @@ public class SysLoginService {
|
||||
|
||||
private SysUserVo loadUserByPhonenumber(String tenantId, String phonenumber) {
|
||||
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
|
||||
.select(SysUser::getPhonenumber, SysUser::getStatus)
|
||||
.eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId)
|
||||
.eq(SysUser::getPhonenumber, phonenumber));
|
||||
.select(SysUser::getPhonenumber, SysUser::getStatus)
|
||||
.eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId)
|
||||
.eq(SysUser::getPhonenumber, phonenumber));
|
||||
if (ObjectUtil.isNull(user)) {
|
||||
log.info("登录用户:{} 不存在.", phonenumber);
|
||||
throw new UserException("user.not.exists", phonenumber);
|
||||
@ -382,7 +450,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");
|
||||
}
|
||||
|
@ -177,3 +177,152 @@ sms:
|
||||
sdkAppId: appid
|
||||
#地域信息默认为 ap-guangzhou 如无特殊改变可不用设置
|
||||
territory: ap-guangzhou
|
||||
|
||||
|
||||
|
||||
justauth:
|
||||
enabled: true
|
||||
type:
|
||||
QQ:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/qq/callback
|
||||
union-id: false
|
||||
WEIBO:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/weibo/callback
|
||||
gitee:
|
||||
client-id: 38eaaa1b77b5e064313057a2f5745ce3a9f3e7686d9bd302c7df2f308ef6db81
|
||||
client-secret: 2e633af8780cb9fe002c4c7291b722db944402e271efb99b062811f52d7da1ff
|
||||
redirect-uri: http://localhost:80/social-login?source=gitee
|
||||
DINGTALK:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/dingtalk/callback
|
||||
BAIDU:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/baidu/callback
|
||||
CSDN:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/csdn/callback
|
||||
CODING:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/coding/callback
|
||||
coding-group-name: xx
|
||||
OSCHINA:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/oschina/callback
|
||||
ALIPAY:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/alipay/callback
|
||||
alipay-public-key: MIIB**************DAQAB
|
||||
WECHAT_OPEN:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/wechat_open/callback
|
||||
WECHAT_MP:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/wechat_mp/callback
|
||||
WECHAT_ENTERPRISE:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/wechat_enterprise/callback
|
||||
agent-id: 1000002
|
||||
TAOBAO:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/taobao/callback
|
||||
GOOGLE:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/google/callback
|
||||
FACEBOOK:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/facebook/callback
|
||||
DOUYIN:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/douyin/callback
|
||||
LINKEDIN:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/linkedin/callback
|
||||
MICROSOFT:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/microsoft/callback
|
||||
MI:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/mi/callback
|
||||
TOUTIAO:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/toutiao/callback
|
||||
TEAMBITION:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/teambition/callback
|
||||
RENREN:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/renren/callback
|
||||
PINTEREST:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/pinterest/callback
|
||||
STACK_OVERFLOW:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/stack_overflow/callback
|
||||
stack-overflow-key: asd*********asd
|
||||
HUAWEI:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/huawei/callback
|
||||
KUJIALE:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/kujiale/callback
|
||||
GITLAB:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/gitlab/callback
|
||||
MEITUAN:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/meituan/callback
|
||||
ELEME:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/eleme/callback
|
||||
TWITTER:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/twitter/callback
|
||||
XMLY:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/xmly/callback
|
||||
# 设备唯一标识ID
|
||||
device-id: xxxxxxxxxxxxxx
|
||||
# 客户端操作系统类型,1-iOS系统,2-Android系统,3-Web
|
||||
client-os-type: 3
|
||||
# 客户端包名,如果 clientOsType 为1或2时必填。对Android客户端是包名,对IOS客户端是Bundle ID
|
||||
#pack-id: xxxx
|
||||
FEISHU:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/feishu/callback
|
||||
JD:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: http://oauth.xkcoding.com/demo/oauth/jd/callback
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
<modules>
|
||||
<module>ruoyi-common-bom</module>
|
||||
<module>ruoyi-common-social</module>
|
||||
<module>ruoyi-common-core</module>
|
||||
<module>ruoyi-common-doc</module>
|
||||
<module>ruoyi-common-excel</module>
|
||||
|
@ -117,6 +117,12 @@
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-social</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- web服务 -->
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
|
@ -26,7 +26,12 @@ public enum DeviceType {
|
||||
/**
|
||||
* 小程序端
|
||||
*/
|
||||
XCX("xcx");
|
||||
XCX("xcx"),
|
||||
|
||||
/**
|
||||
* social第三方端
|
||||
*/
|
||||
SOCIAL("social");
|
||||
|
||||
private final String device;
|
||||
}
|
||||
|
29
ruoyi-common/ruoyi-common-social/pom.xml
Normal file
29
ruoyi-common/ruoyi-common-social/pom.xml
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-common-social</artifactId>
|
||||
|
||||
<description>
|
||||
ruoyi-common-social 授权认证
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-redis</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,24 @@
|
||||
package org.dromara.common.social.config;
|
||||
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import org.dromara.common.social.config.properties.SocialProperties;
|
||||
import org.dromara.common.social.utils.AuthRedisStateCache;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
/**
|
||||
* Social 配置属性
|
||||
* @author thiszhc
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@EnableConfigurationProperties(SocialProperties.class)
|
||||
public class SocialConfig {
|
||||
|
||||
@Bean
|
||||
public AuthStateCache authStateCache() {
|
||||
return new AuthRedisStateCache();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package org.dromara.common.social.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SocialLoginConfigProperties {
|
||||
|
||||
/**
|
||||
* 应用 ID
|
||||
*/
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
* 应用密钥
|
||||
*/
|
||||
private String clientSecret;
|
||||
|
||||
/**
|
||||
* 回调地址
|
||||
*/
|
||||
private String redirectUri;
|
||||
|
||||
/**
|
||||
* 是否获取unionId
|
||||
*/
|
||||
private boolean unionId;
|
||||
|
||||
/**
|
||||
* Coding 企业名称
|
||||
*/
|
||||
private String codingGroupName;
|
||||
|
||||
/**
|
||||
* 支付宝公钥
|
||||
*/
|
||||
private String alipayPublicKey;
|
||||
|
||||
/**
|
||||
* 企业微信应用ID
|
||||
*/
|
||||
private String agentId;
|
||||
|
||||
/**
|
||||
* stackoverflow api key
|
||||
*/
|
||||
private String stackOverflowKey;
|
||||
|
||||
/**
|
||||
* 设备ID
|
||||
*/
|
||||
private String deviceId;
|
||||
|
||||
/**
|
||||
* 客户端系统类型
|
||||
*/
|
||||
private String clientOsType;
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
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;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Social 配置属性
|
||||
* @author thiszhc
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "justauth")
|
||||
public class SocialProperties {
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
private boolean enabled;
|
||||
|
||||
/**
|
||||
* 授权类型
|
||||
*/
|
||||
private Map<String, SocialLoginConfigProperties> type;
|
||||
|
||||
/**
|
||||
* 授权过期时间
|
||||
*/
|
||||
private long timeout;
|
||||
|
||||
/**
|
||||
* 授权缓存配置
|
||||
*/
|
||||
private CacheProperties cache = new CacheProperties();
|
||||
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package org.dromara.common.social.utils;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import org.dromara.common.redis.utils.RedisUtils;
|
||||
import org.dromara.common.social.config.properties.SocialProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ValueOperations;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
public class AuthRedisStateCache implements AuthStateCache {
|
||||
|
||||
private SocialProperties socialProperties;
|
||||
|
||||
/**
|
||||
* 存入缓存
|
||||
*
|
||||
* @param key 缓存key
|
||||
* @param value 缓存内容
|
||||
*/
|
||||
@Override
|
||||
public void cache(String key, String value) {
|
||||
// TODO: 自定义存入缓存
|
||||
RedisUtils.setCacheObject(key, value, Duration.ofMillis(socialProperties.getTimeout()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 存入缓存
|
||||
*
|
||||
* @param key 缓存key
|
||||
* @param value 缓存内容
|
||||
* @param timeout 指定缓存过期时间(毫秒)
|
||||
*/
|
||||
@Override
|
||||
public void cache(String key, String value, long timeout) {
|
||||
// TODO: 自定义存入缓存
|
||||
RedisUtils.setCacheObject(key, value, Duration.ofMillis(timeout));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存内容
|
||||
*
|
||||
* @param key 缓存key
|
||||
* @return 缓存内容
|
||||
*/
|
||||
@Override
|
||||
public String get(String key) {
|
||||
// TODO: 自定义获取缓存内容
|
||||
return RedisUtils.getCacheObject(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否存在key,如果对应key的value值已过期,也返回false
|
||||
*
|
||||
* @param key 缓存key
|
||||
* @return true:存在key,并且value没过期;false:key不存在或者已过期
|
||||
*/
|
||||
@Override
|
||||
public boolean containsKey(String key) {
|
||||
// TODO: 自定义判断key是否存在
|
||||
return RedisUtils.hasKey(key);
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
package org.dromara.common.social.utils;
|
||||
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.request.*;
|
||||
|
||||
/**
|
||||
* 认证授权工具类
|
||||
*
|
||||
* @author thiszhc
|
||||
*/
|
||||
public class SocialUtils {
|
||||
|
||||
public static AuthRequest getAuthRequest(String source,
|
||||
String clientId,
|
||||
String clientSecret,
|
||||
String redirectUri) throws AuthException {
|
||||
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)
|
||||
.alipayPublicKey("").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" ->
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,57 @@
|
||||
package org.dromara.system.controller.system;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.system.domain.vo.SocialUserVo;
|
||||
import org.dromara.system.service.ISocialUserService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 社会化关系
|
||||
*
|
||||
* @author thiszhc
|
||||
* @date 2023-06-16
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/system/social")
|
||||
public class SocialUserController extends BaseController {
|
||||
|
||||
private final ISocialUserService socialUserService;
|
||||
|
||||
/**
|
||||
* 查询社会化关系列表
|
||||
*/
|
||||
// 这里改成用户默认的。只能查看自己的权限更好哦
|
||||
// @SaCheckPermission("system:user:list")
|
||||
@GetMapping("/list")
|
||||
public R<List<SocialUserVo>> list() {
|
||||
return R.ok(socialUserService.queryList());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取社会化关系详细信息
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
// 这里改成用户默认的。只能查看自己的权限更好哦
|
||||
// @SaCheckPermission("system:user:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<SocialUserVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable String id) {
|
||||
return R.ok(socialUserService.queryById(id));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
package org.dromara.system.domain;
|
||||
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 社会化关系对象 social_user
|
||||
*
|
||||
* @author thiszhc
|
||||
* @date 2023-06-12
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("social_user")
|
||||
public class SocialUser extends BaseEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 的唯一ID
|
||||
*/
|
||||
private String authId;
|
||||
|
||||
/**
|
||||
* 用户来源
|
||||
*/
|
||||
private String source;
|
||||
|
||||
/**
|
||||
* 用户的授权令牌
|
||||
*/
|
||||
private String accessToken;
|
||||
|
||||
/**
|
||||
* 用户的授权令牌的有效期,部分平台可能没有
|
||||
*/
|
||||
private int expireIn;
|
||||
|
||||
/**
|
||||
* 刷新令牌,部分平台可能没有
|
||||
*/
|
||||
private String refreshToken;
|
||||
|
||||
/**
|
||||
* 用户的 open id
|
||||
*/
|
||||
private String openId;
|
||||
|
||||
/**
|
||||
* 用户的 ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 授权的第三方账号
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 授权的第三方昵称
|
||||
*/
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 授权的第三方邮箱
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 授权的第三方头像地址
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 平台的授权信息,部分平台可能没有
|
||||
*/
|
||||
private String accessCode;
|
||||
|
||||
/**
|
||||
* 用户的 unionid
|
||||
*/
|
||||
private String unionId;
|
||||
|
||||
/**
|
||||
* 授予的权限,部分平台可能没有
|
||||
*/
|
||||
private String scope;
|
||||
|
||||
/**
|
||||
* 个别平台的授权信息,部分平台可能没有
|
||||
*/
|
||||
private String tokenType;
|
||||
|
||||
/**
|
||||
* id token,部分平台可能没有
|
||||
*/
|
||||
private String idToken;
|
||||
|
||||
/**
|
||||
* 小米平台用户的附带属性,部分平台可能没有
|
||||
*/
|
||||
private String macAlgorithm;
|
||||
|
||||
/**
|
||||
* 小米平台用户的附带属性,部分平台可能没有
|
||||
*/
|
||||
private String macKey;
|
||||
|
||||
/**
|
||||
* 用户的授权code,部分平台可能没有
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* Twitter平台用户的附带属性,部分平台可能没有
|
||||
*/
|
||||
private String oauthToken;
|
||||
|
||||
/**
|
||||
* Twitter平台用户的附带属性,部分平台可能没有
|
||||
*/
|
||||
private String oauthTokenSecret;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
package org.dromara.system.domain.bo;
|
||||
|
||||
import org.dromara.common.tenant.core.TenantEntity;
|
||||
import org.dromara.system.domain.SocialUser;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import jakarta.validation.constraints.*;
|
||||
|
||||
/**
|
||||
* 社会化关系业务对象 social_user
|
||||
*
|
||||
* @author Lion Li
|
||||
* @date 2023-06-12
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = SocialUser.class, reverseConvertGenerate = false)
|
||||
public class SocialUserBo extends TenantEntity {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@NotNull(message = "主键不能为空", groups = { EditGroup.class })
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 的唯一ID
|
||||
*/
|
||||
@NotBlank(message = "的唯一ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String authId;
|
||||
|
||||
/**
|
||||
* 用户来源
|
||||
*/
|
||||
@NotBlank(message = "用户来源不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String source;
|
||||
|
||||
/**
|
||||
* 用户的授权令牌
|
||||
*/
|
||||
@NotBlank(message = "用户的授权令牌不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String accessToken;
|
||||
|
||||
/**
|
||||
* 用户的授权令牌的有效期,部分平台可能没有
|
||||
*/
|
||||
private int expireIn;
|
||||
|
||||
/**
|
||||
* 刷新令牌,部分平台可能没有
|
||||
*/
|
||||
private String refreshToken;
|
||||
|
||||
/**
|
||||
* 用户的 open id
|
||||
*/
|
||||
@NotBlank(message = "用户的 open id不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String openId;
|
||||
|
||||
/**
|
||||
* 用户的 ID
|
||||
*/
|
||||
@NotBlank(message = "用户的 ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 平台的授权信息,部分平台可能没有
|
||||
*/
|
||||
private String accessCode;
|
||||
|
||||
/**
|
||||
* 用户的 unionid
|
||||
*/
|
||||
private String unionId;
|
||||
|
||||
/**
|
||||
* 授予的权限,部分平台可能没有
|
||||
*/
|
||||
private String scope;
|
||||
|
||||
/**
|
||||
* 授权的第三方账号
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 授权的第三方昵称
|
||||
*/
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 授权的第三方邮箱
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 授权的第三方头像地址
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 个别平台的授权信息,部分平台可能没有
|
||||
*/
|
||||
private String tokenType;
|
||||
|
||||
/**
|
||||
* id token,部分平台可能没有
|
||||
*/
|
||||
private String idToken;
|
||||
|
||||
/**
|
||||
* 小米平台用户的附带属性,部分平台可能没有
|
||||
*/
|
||||
private String macAlgorithm;
|
||||
|
||||
/**
|
||||
* 小米平台用户的附带属性,部分平台可能没有
|
||||
*/
|
||||
private String macKey;
|
||||
|
||||
/**
|
||||
* 用户的授权code,部分平台可能没有
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* Twitter平台用户的附带属性,部分平台可能没有
|
||||
*/
|
||||
private String oauthToken;
|
||||
|
||||
/**
|
||||
* Twitter平台用户的附带属性,部分平台可能没有
|
||||
*/
|
||||
private String oauthTokenSecret;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,162 @@
|
||||
package org.dromara.system.domain.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.tenant.core.TenantEntity;
|
||||
import org.dromara.system.domain.SocialUser;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 社会化关系视图对象 social_user
|
||||
*
|
||||
* @author thiszhc
|
||||
* @date 2023-06-12
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = SocialUser.class)
|
||||
public class SocialUserVo extends TenantEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@ExcelProperty(value = "主键")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 的唯一ID
|
||||
*/
|
||||
@ExcelProperty(value = "授权UUID")
|
||||
private String authId;
|
||||
|
||||
/**
|
||||
* 用户来源
|
||||
*/
|
||||
@ExcelProperty(value = "用户来源")
|
||||
private String source;
|
||||
|
||||
/**
|
||||
* 用户的授权令牌
|
||||
*/
|
||||
@ExcelProperty(value = "用户的授权令牌")
|
||||
private String accessToken;
|
||||
|
||||
/**
|
||||
* 用户的授权令牌的有效期,部分平台可能没有
|
||||
*/
|
||||
@ExcelProperty(value = "用户的授权令牌的有效期,部分平台可能没有")
|
||||
private int expireIn;
|
||||
|
||||
/**
|
||||
* 刷新令牌,部分平台可能没有
|
||||
*/
|
||||
@ExcelProperty(value = "刷新令牌,部分平台可能没有")
|
||||
private String refreshToken;
|
||||
|
||||
/**
|
||||
* 用户的 open id
|
||||
*/
|
||||
@ExcelProperty(value = "用户的 open id")
|
||||
private String openId;
|
||||
|
||||
/**
|
||||
* 用户的 ID
|
||||
*/
|
||||
@ExcelProperty(value = "用户的 ID")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 授权的第三方账号
|
||||
*/
|
||||
@ExcelProperty(value = "授权的第三方账号")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 授权的第三方昵称
|
||||
*/
|
||||
@ExcelProperty(value = "授权的第三方昵称")
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 授权的第三方邮箱
|
||||
*/
|
||||
@ExcelProperty(value = "授权的第三方邮箱")
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 授权的第三方头像地址
|
||||
*/
|
||||
@ExcelProperty(value = "授权的第三方头像地址")
|
||||
private String avatar;
|
||||
|
||||
|
||||
/**
|
||||
* 平台的授权信息,部分平台可能没有
|
||||
*/
|
||||
@ExcelProperty(value = "平台的授权信息,部分平台可能没有")
|
||||
private String accessCode;
|
||||
|
||||
/**
|
||||
* 用户的 unionid
|
||||
*/
|
||||
@ExcelProperty(value = "用户的 unionid")
|
||||
private String unionId;
|
||||
|
||||
/**
|
||||
* 授予的权限,部分平台可能没有
|
||||
*/
|
||||
@ExcelProperty(value = "授予的权限,部分平台可能没有")
|
||||
private String scope;
|
||||
|
||||
/**
|
||||
* 个别平台的授权信息,部分平台可能没有
|
||||
*/
|
||||
@ExcelProperty(value = "个别平台的授权信息,部分平台可能没有")
|
||||
private String tokenType;
|
||||
|
||||
/**
|
||||
* id token,部分平台可能没有
|
||||
*/
|
||||
@ExcelProperty(value = "id token,部分平台可能没有")
|
||||
private String idToken;
|
||||
|
||||
/**
|
||||
* 小米平台用户的附带属性,部分平台可能没有
|
||||
*/
|
||||
@ExcelProperty(value = "小米平台用户的附带属性,部分平台可能没有")
|
||||
private String macAlgorithm;
|
||||
|
||||
/**
|
||||
* 小米平台用户的附带属性,部分平台可能没有
|
||||
*/
|
||||
@ExcelProperty(value = "小米平台用户的附带属性,部分平台可能没有")
|
||||
private String macKey;
|
||||
|
||||
/**
|
||||
* 用户的授权code,部分平台可能没有
|
||||
*/
|
||||
@ExcelProperty(value = "用户的授权code,部分平台可能没有")
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* Twitter平台用户的附带属性,部分平台可能没有
|
||||
*/
|
||||
@ExcelProperty(value = "Twitter平台用户的附带属性,部分平台可能没有")
|
||||
private String oauthToken;
|
||||
|
||||
/**
|
||||
* Twitter平台用户的附带属性,部分平台可能没有
|
||||
*/
|
||||
@ExcelProperty(value = "Twitter平台用户的附带属性,部分平台可能没有")
|
||||
private String oauthTokenSecret;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package org.dromara.system.mapper;
|
||||
|
||||
import org.dromara.system.domain.SocialUser;
|
||||
import org.dromara.system.domain.bo.SysUserBo;
|
||||
import org.dromara.system.domain.vo.SocialUserVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 社会化关系Mapper接口
|
||||
*
|
||||
* @author thiszhc
|
||||
* @date 2023-06-12
|
||||
*/
|
||||
public interface SocialUserMapper extends BaseMapperPlus<SocialUser, SocialUserVo> {
|
||||
|
||||
/**
|
||||
* 根据authId查询SocialUser表和SysUser表,返回SocialUserAuthResult映射的对象
|
||||
* @param authId 认证ID
|
||||
* @return SocialUser
|
||||
*/
|
||||
SocialUserVo selectSocialUserByAuthId(String authId);
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package org.dromara.system.service;
|
||||
|
||||
import org.dromara.system.domain.bo.SocialUserBo;
|
||||
import org.dromara.system.domain.vo.SocialUserVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 社会化关系Service接口
|
||||
*
|
||||
* @author thiszhc
|
||||
* @date 2023-06-12
|
||||
*/
|
||||
public interface ISocialUserService {
|
||||
|
||||
|
||||
/**
|
||||
* 查询社会化关系
|
||||
*/
|
||||
SocialUserVo queryById(String id);
|
||||
|
||||
/**
|
||||
* 查询社会化关系列表
|
||||
*/
|
||||
List<SocialUserVo> queryList();
|
||||
|
||||
/**
|
||||
* 新增授权关系
|
||||
*/
|
||||
Boolean insertByBo(SocialUserBo bo);
|
||||
|
||||
|
||||
/**
|
||||
* 删除社会化关系信息
|
||||
*/
|
||||
Boolean deleteWithValidById(Long id);
|
||||
|
||||
|
||||
/**
|
||||
* 根据authId查询SocialUser表和SysUser表,返回SocialUserAuthResult映射的对象
|
||||
* @param authId 认证ID
|
||||
* @return SocialUser
|
||||
*/
|
||||
SocialUserVo selectSocialUserByAuthId(String authId);
|
||||
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package org.dromara.system.service.impl;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.system.domain.SocialUser;
|
||||
import org.dromara.system.domain.bo.SocialUserBo;
|
||||
import org.dromara.system.domain.vo.SocialUserVo;
|
||||
import org.dromara.system.mapper.SocialUserMapper;
|
||||
import org.dromara.system.service.ISocialUserService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 社会化关系Service业务层处理
|
||||
*
|
||||
* @author thiszhc
|
||||
* @date 2023-06-12
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class SocialUserServiceImpl implements ISocialUserService {
|
||||
|
||||
private final SocialUserMapper baseMapper;
|
||||
|
||||
|
||||
/**
|
||||
* 查询社会化关系
|
||||
*/
|
||||
@Override
|
||||
public SocialUserVo queryById(String id){
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权列表
|
||||
*/
|
||||
@Override
|
||||
public List<SocialUserVo> queryList() {
|
||||
return baseMapper.selectVoList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 新增社会化关系
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(SocialUserBo bo) {
|
||||
SocialUser add = MapstructUtils.convert(bo, SocialUser.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
if (add != null) {
|
||||
bo.setId(add.getId());
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(SocialUser entity) {
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除社会化关系
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidById(Long id) {
|
||||
return baseMapper.deleteById(id) > 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据authId查询用户信息
|
||||
*
|
||||
* @param authId 用户id
|
||||
* @return 用户信息
|
||||
*/
|
||||
@Override
|
||||
public SocialUserVo selectSocialUserByAuthId(String authId) {
|
||||
return baseMapper.selectSocialUserByAuthId(authId);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.dromara.system.mapper.SocialUserMapper">
|
||||
|
||||
<resultMap type="org.dromara.system.domain.vo.SocialUserVo" id="SocialUserAuthResult">
|
||||
<id property="id" column="id"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 根据authId查询SocialUser表和SysUser表,返回SocialUserAuthResult映射的对象 -->
|
||||
<select id="selectSocialUserByAuthId" parameterType="String" resultMap="SocialUserAuthResult">
|
||||
select b.user_id,
|
||||
b.tenant_id,
|
||||
b.user_name,
|
||||
b.password,
|
||||
a.auth_id,
|
||||
a.source
|
||||
from social_user a
|
||||
left join sys_user b on a.user_id = b.user_id
|
||||
where a.auth_id = #{authId}
|
||||
</select>
|
||||
|
||||
</mapper>
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user