refactor: 优化认证及客户端相关代码

This commit is contained in:
2024-12-27 20:29:36 +08:00
parent c870014730
commit 438615f87c
27 changed files with 160 additions and 226 deletions

View File

@@ -23,7 +23,7 @@ import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import top.continew.admin.auth.model.req.AuthReq; import top.continew.admin.auth.model.req.LoginReq;
import top.continew.admin.common.context.RoleContext; import top.continew.admin.common.context.RoleContext;
import top.continew.admin.common.context.UserContext; import top.continew.admin.common.context.UserContext;
import top.continew.admin.common.context.UserContextHolder; import top.continew.admin.common.context.UserContextHolder;
@@ -37,7 +37,7 @@ import top.continew.admin.system.service.OptionService;
import top.continew.admin.system.service.RoleService; import top.continew.admin.system.service.RoleService;
import top.continew.admin.system.service.UserService; import top.continew.admin.system.service.UserService;
import top.continew.starter.core.validation.CheckUtils; import top.continew.starter.core.validation.CheckUtils;
import top.continew.starter.core.validation.ValidationUtils; import top.continew.starter.core.validation.Validator;
import top.continew.starter.web.util.SpringWebUtils; import top.continew.starter.web.util.SpringWebUtils;
import java.util.Set; import java.util.Set;
@@ -46,14 +46,14 @@ import java.util.concurrent.CompletableFuture;
import static top.continew.admin.system.enums.PasswordPolicyEnum.PASSWORD_EXPIRATION_DAYS; import static top.continew.admin.system.enums.PasswordPolicyEnum.PASSWORD_EXPIRATION_DAYS;
/** /**
* 认证处理器基类 * 登录处理器基类
* *
* @author KAI * @author KAI
* @author Charles7c * @author Charles7c
* @since 2024/12/22 14:52 * @since 2024/12/22 14:52
*/ */
@Component @Component
public abstract class AbstractAuthHandler<T extends AuthReq> implements AuthHandler<T> { public abstract class AbstractLoginHandler<T extends LoginReq> implements LoginHandler<T> {
@Resource @Resource
protected OptionService optionService; protected OptionService optionService;
@@ -73,7 +73,7 @@ public abstract class AbstractAuthHandler<T extends AuthReq> implements AuthHand
@Override @Override
public void preLogin(T req, ClientResp client, HttpServletRequest request) { public void preLogin(T req, ClientResp client, HttpServletRequest request) {
// 参数校验 // 参数校验
ValidationUtils.validate(req); Validator.validate(req);
} }
@Override @Override
@@ -100,18 +100,15 @@ public abstract class AbstractAuthHandler<T extends AuthReq> implements AuthHand
UserContext userContext = new UserContext(permissionFuture.join(), roleFuture UserContext userContext = new UserContext(permissionFuture.join(), roleFuture
.join(), passwordExpirationDaysFuture.join()); .join(), passwordExpirationDaysFuture.join());
BeanUtil.copyProperties(user, userContext); BeanUtil.copyProperties(user, userContext);
// 登录并缓存用户信息 // 设置登录配置参数
SaLoginModel model = new SaLoginModel(); SaLoginModel model = new SaLoginModel();
// 指定此次登录 token 最低活跃频率单位如未指定则使用全局配置的 activeTimeout
model.setActiveTimeout(client.getActiveTimeout()); model.setActiveTimeout(client.getActiveTimeout());
// 指定此次登录 token 有效期单位 如未指定自动取全局配置的 timeout
model.setTimeout(client.getTimeout()); model.setTimeout(client.getTimeout());
// 客户端类型
model.setDevice(client.getClientType()); model.setDevice(client.getClientType());
userContext.setClientType(client.getClientType()); userContext.setClientType(client.getClientType());
// 客户端 ID
model.setExtra(CLIENT_ID, client.getClientId()); model.setExtra(CLIENT_ID, client.getClientId());
userContext.setClientId(client.getClientId()); userContext.setClientId(client.getClientId());
// 登录并缓存用户信息
StpUtil.login(userContext.getId(), model.setExtraData(BeanUtil.beanToMap(new UserExtraContext(SpringWebUtils StpUtil.login(userContext.getId(), model.setExtraData(BeanUtil.beanToMap(new UserExtraContext(SpringWebUtils
.getRequest())))); .getRequest()))));
UserContextHolder.setContext(userContext); UserContextHolder.setContext(userContext);

View File

@@ -18,18 +18,18 @@ package top.continew.admin.auth;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import top.continew.admin.auth.enums.AuthTypeEnum; import top.continew.admin.auth.enums.AuthTypeEnum;
import top.continew.admin.auth.model.req.AuthReq; import top.continew.admin.auth.model.req.LoginReq;
import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.auth.model.resp.LoginResp;
import top.continew.admin.system.model.resp.ClientResp; import top.continew.admin.system.model.resp.ClientResp;
/** /**
* 认证处理器 * 登录处理器
* *
* @author KAI * @author KAI
* @author Charles7c * @author Charles7c
* @since 2024/12/22 14:52 * @since 2024/12/22 14:52
*/ */
public interface AuthHandler<T extends AuthReq> { public interface LoginHandler<T extends LoginReq> {
/** /**
* 登录 * 登录

View File

@@ -19,27 +19,27 @@ package top.continew.admin.auth;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import top.continew.admin.auth.enums.AuthTypeEnum; import top.continew.admin.auth.enums.AuthTypeEnum;
import top.continew.admin.auth.model.req.AuthReq; import top.continew.admin.auth.model.req.LoginReq;
import java.util.HashMap; import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* 认证策略 * 登录处理器工厂
* *
* @author KAI * @author KAI
* @author Charles7c * @author Charles7c
* @since 2024/12/20 15:16 * @since 2024/12/20 15:16
*/ */
@Component @Component
public class AuthStrategy { public class LoginHandlerFactory {
private final Map<AuthTypeEnum, AuthHandler<? extends AuthReq>> handlerMap = new HashMap<>(); private final Map<AuthTypeEnum, LoginHandler<? extends LoginReq>> handlerMap = new EnumMap<>(AuthTypeEnum.class);
@Autowired @Autowired
public AuthStrategy(List<AuthHandler<? extends AuthReq>> handlers) { public LoginHandlerFactory(List<LoginHandler<? extends LoginReq>> handlers) {
for (AuthHandler<? extends AuthReq> handler : handlers) { for (LoginHandler<? extends LoginReq> handler : handlers) {
handlerMap.put(handler.getAuthType(), handler); handlerMap.put(handler.getAuthType(), handler);
} }
} }
@@ -50,7 +50,7 @@ public class AuthStrategy {
* @param authType 认证类型 * @param authType 认证类型
* @return 认证处理器 * @return 认证处理器
*/ */
public AuthHandler<AuthReq> getHandler(AuthTypeEnum authType) { public LoginHandler<LoginReq> getHandler(AuthTypeEnum authType) {
return (AuthHandler<AuthReq>)handlerMap.get(authType); return (LoginHandler<LoginReq>)handlerMap.get(authType);
} }
} }

View File

@@ -22,9 +22,9 @@ import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import top.continew.admin.auth.AbstractAuthHandler; import top.continew.admin.auth.AbstractLoginHandler;
import top.continew.admin.auth.enums.AuthTypeEnum; import top.continew.admin.auth.enums.AuthTypeEnum;
import top.continew.admin.auth.model.req.AccountAuthReq; import top.continew.admin.auth.model.req.AccountLoginReq;
import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.auth.model.resp.LoginResp;
import top.continew.admin.common.constant.CacheConstants; import top.continew.admin.common.constant.CacheConstants;
import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.constant.SysConstants;
@@ -40,7 +40,7 @@ import top.continew.starter.core.validation.ValidationUtils;
import java.time.Duration; import java.time.Duration;
/** /**
* 账号认证处理器 * 账号登录处理器
* *
* @author KAI * @author KAI
* @author Charles7c * @author Charles7c
@@ -48,12 +48,12 @@ import java.time.Duration;
*/ */
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class AccountAuthHandler extends AbstractAuthHandler<AccountAuthReq> { public class AccountLoginHandler extends AbstractLoginHandler<AccountLoginReq> {
private final PasswordEncoder passwordEncoder; private final PasswordEncoder passwordEncoder;
@Override @Override
public LoginResp login(AccountAuthReq req, ClientResp client, HttpServletRequest request) { public LoginResp login(AccountLoginReq req, ClientResp client, HttpServletRequest request) {
// 解密密码 // 解密密码
String rawPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(req.getPassword())); String rawPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(req.getPassword()));
ValidationUtils.throwIfBlank(rawPassword, "密码解密失败"); ValidationUtils.throwIfBlank(rawPassword, "密码解密失败");
@@ -72,7 +72,7 @@ public class AccountAuthHandler extends AbstractAuthHandler<AccountAuthReq> {
} }
@Override @Override
public void preLogin(AccountAuthReq req, ClientResp client, HttpServletRequest request) { public void preLogin(AccountLoginReq req, ClientResp client, HttpServletRequest request) {
super.preLogin(req, client, request); super.preLogin(req, client, request);
// 校验验证码 // 校验验证码
int loginCaptchaEnabled = optionService.getValueByCode2Int("LOGIN_CAPTCHA_ENABLED"); int loginCaptchaEnabled = optionService.getValueByCode2Int("LOGIN_CAPTCHA_ENABLED");

View File

@@ -18,9 +18,9 @@ package top.continew.admin.auth.handler;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import top.continew.admin.auth.AbstractAuthHandler; import top.continew.admin.auth.AbstractLoginHandler;
import top.continew.admin.auth.enums.AuthTypeEnum; import top.continew.admin.auth.enums.AuthTypeEnum;
import top.continew.admin.auth.model.req.EmailAuthReq; import top.continew.admin.auth.model.req.EmailLoginReq;
import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.auth.model.resp.LoginResp;
import top.continew.admin.common.constant.CacheConstants; import top.continew.admin.common.constant.CacheConstants;
import top.continew.admin.system.model.entity.UserDO; import top.continew.admin.system.model.entity.UserDO;
@@ -29,17 +29,17 @@ import top.continew.starter.cache.redisson.util.RedisUtils;
import top.continew.starter.core.validation.ValidationUtils; import top.continew.starter.core.validation.ValidationUtils;
/** /**
* 邮箱认证处理器 * 邮箱登录处理器
* *
* @author KAI * @author KAI
* @author Charles7c * @author Charles7c
* @since 2024/12/22 14:58 * @since 2024/12/22 14:58
*/ */
@Component @Component
public class EmailAuthHandler extends AbstractAuthHandler<EmailAuthReq> { public class EmailLoginHandler extends AbstractLoginHandler<EmailLoginReq> {
@Override @Override
public LoginResp login(EmailAuthReq req, ClientResp client, HttpServletRequest request) { public LoginResp login(EmailLoginReq req, ClientResp client, HttpServletRequest request) {
// 验证邮箱 // 验证邮箱
UserDO user = userService.getByEmail(req.getEmail()); UserDO user = userService.getByEmail(req.getEmail());
ValidationUtils.throwIfNull(user, "此邮箱未绑定本系统账号"); ValidationUtils.throwIfNull(user, "此邮箱未绑定本系统账号");
@@ -51,7 +51,7 @@ public class EmailAuthHandler extends AbstractAuthHandler<EmailAuthReq> {
} }
@Override @Override
public void preLogin(EmailAuthReq req, ClientResp client, HttpServletRequest request) { public void preLogin(EmailLoginReq req, ClientResp client, HttpServletRequest request) {
String email = req.getEmail(); String email = req.getEmail();
String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + email; String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + email;
String captcha = RedisUtils.get(captchaKey); String captcha = RedisUtils.get(captchaKey);

View File

@@ -18,9 +18,9 @@ package top.continew.admin.auth.handler;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import top.continew.admin.auth.AbstractAuthHandler; import top.continew.admin.auth.AbstractLoginHandler;
import top.continew.admin.auth.enums.AuthTypeEnum; import top.continew.admin.auth.enums.AuthTypeEnum;
import top.continew.admin.auth.model.req.PhoneAuthReq; import top.continew.admin.auth.model.req.PhoneLoginReq;
import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.auth.model.resp.LoginResp;
import top.continew.admin.common.constant.CacheConstants; import top.continew.admin.common.constant.CacheConstants;
import top.continew.admin.system.model.entity.UserDO; import top.continew.admin.system.model.entity.UserDO;
@@ -29,17 +29,17 @@ import top.continew.starter.cache.redisson.util.RedisUtils;
import top.continew.starter.core.validation.ValidationUtils; import top.continew.starter.core.validation.ValidationUtils;
/** /**
* 手机号认证处理器 * 手机号登录处理器
* *
* @author KAI * @author KAI
* @author Charles7c * @author Charles7c
* @since 2024/12/22 14:59 * @since 2024/12/22 14:59
*/ */
@Component @Component
public class PhoneAuthHandler extends AbstractAuthHandler<PhoneAuthReq> { public class PhoneLoginHandler extends AbstractLoginHandler<PhoneLoginReq> {
@Override @Override
public LoginResp login(PhoneAuthReq req, ClientResp client, HttpServletRequest request) { public LoginResp login(PhoneLoginReq req, ClientResp client, HttpServletRequest request) {
// 验证手机号 // 验证手机号
UserDO user = userService.getByPhone(req.getPhone()); UserDO user = userService.getByPhone(req.getPhone());
ValidationUtils.throwIfNull(user, "此手机号未绑定本系统账号"); ValidationUtils.throwIfNull(user, "此手机号未绑定本系统账号");
@@ -51,7 +51,7 @@ public class PhoneAuthHandler extends AbstractAuthHandler<PhoneAuthReq> {
} }
@Override @Override
public void preLogin(PhoneAuthReq req, ClientResp client, HttpServletRequest request) { public void preLogin(PhoneLoginReq req, ClientResp client, HttpServletRequest request) {
String phone = req.getPhone(); String phone = req.getPhone();
String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + phone; String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + phone;
String captcha = RedisUtils.get(captchaKey); String captcha = RedisUtils.get(captchaKey);

View File

@@ -31,12 +31,13 @@ import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest; import me.zhyd.oauth.request.AuthRequest;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import top.continew.admin.auth.AbstractAuthHandler; import top.continew.admin.auth.AbstractLoginHandler;
import top.continew.admin.auth.enums.AuthTypeEnum; import top.continew.admin.auth.enums.AuthTypeEnum;
import top.continew.admin.auth.model.req.SocialAuthReq; import top.continew.admin.auth.model.req.SocialLoginReq;
import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.auth.model.resp.LoginResp;
import top.continew.admin.common.constant.RegexConstants; import top.continew.admin.common.constant.RegexConstants;
import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.constant.SysConstants;
import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.admin.common.enums.GenderEnum; import top.continew.admin.common.enums.GenderEnum;
import top.continew.admin.system.enums.MessageTemplateEnum; import top.continew.admin.system.enums.MessageTemplateEnum;
import top.continew.admin.system.enums.MessageTypeEnum; import top.continew.admin.system.enums.MessageTypeEnum;
@@ -58,14 +59,15 @@ import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
* 第三方账号认证处理器 * 第三方账号登录处理器
* *
* @author KAI * @author KAI
* @author Charles7c
* @since 2024/12/25 14:21 * @since 2024/12/25 14:21
*/ */
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class SocialAuthHandler extends AbstractAuthHandler<SocialAuthReq> { public class SocialLoginHandler extends AbstractLoginHandler<SocialLoginReq> {
private final AuthRequestFactory authRequestFactory; private final AuthRequestFactory authRequestFactory;
private final UserSocialService userSocialService; private final UserSocialService userSocialService;
@@ -74,7 +76,7 @@ public class SocialAuthHandler extends AbstractAuthHandler<SocialAuthReq> {
private final ProjectProperties projectProperties; private final ProjectProperties projectProperties;
@Override @Override
public LoginResp login(SocialAuthReq req, ClientResp client, HttpServletRequest request) { public LoginResp login(SocialLoginReq req, ClientResp client, HttpServletRequest request) {
// 获取第三方登录信息 // 获取第三方登录信息
AuthRequest authRequest = this.getAuthRequest(req.getSource()); AuthRequest authRequest = this.getAuthRequest(req.getSource());
AuthCallback callback = new AuthCallback(); AuthCallback callback = new AuthCallback();
@@ -105,7 +107,9 @@ public class SocialAuthHandler extends AbstractAuthHandler<SocialAuthReq> {
user.setGender(GenderEnum.valueOf(authUser.getGender().name())); user.setGender(GenderEnum.valueOf(authUser.getGender().name()));
user.setAvatar(authUser.getAvatar()); user.setAvatar(authUser.getAvatar());
user.setDeptId(SysConstants.SUPER_DEPT_ID); user.setDeptId(SysConstants.SUPER_DEPT_ID);
Long userId = userService.add(user); user.setStatus(DisEnableStatusEnum.ENABLE);
userService.save(user);
Long userId = user.getId();
RoleDO role = roleService.getByCode(SysConstants.SUPER_ROLE_CODE); RoleDO role = roleService.getByCode(SysConstants.SUPER_ROLE_CODE);
userRoleService.assignRolesToUser(Collections.singletonList(role.getId()), userId); userRoleService.assignRolesToUser(Collections.singletonList(role.getId()), userId);
userSocial = new UserSocialDO(); userSocial = new UserSocialDO();
@@ -127,7 +131,7 @@ public class SocialAuthHandler extends AbstractAuthHandler<SocialAuthReq> {
} }
@Override @Override
public void preLogin(SocialAuthReq req, ClientResp client, HttpServletRequest request) { public void preLogin(SocialLoginReq req, ClientResp client, HttpServletRequest request) {
super.preLogin(req, client, request); super.preLogin(req, client, request);
if (StpUtil.isLogin()) { if (StpUtil.isLogin()) {
StpUtil.logout(); StpUtil.logout();

View File

@@ -23,14 +23,14 @@ import lombok.Data;
import java.io.Serial; import java.io.Serial;
/** /**
* 账号认证参数 * 账号登录参数
* *
* @author Charles7c * @author Charles7c
* @since 2022/12/21 20:43 * @since 2022/12/21 20:43
*/ */
@Data @Data
@Schema(description = "账号认证参数") @Schema(description = "账号登录参数")
public class AccountAuthReq extends AuthReq { public class AccountLoginReq extends LoginReq {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -26,14 +26,14 @@ import org.hibernate.validator.constraints.Length;
import java.io.Serial; import java.io.Serial;
/** /**
* 邮箱认证参数 * 邮箱登录参数
* *
* @author Charles7c * @author Charles7c
* @since 2023/10/23 20:15 * @since 2023/10/23 20:15
*/ */
@Data @Data
@Schema(description = "邮箱认证参数") @Schema(description = "邮箱登录参数")
public class EmailAuthReq extends AuthReq { public class EmailLoginReq extends LoginReq {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -28,7 +28,7 @@ import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
/** /**
* 认证参数基类 * 登录参数基类
* *
* @author KAI * @author KAI
* @author Charles7c * @author Charles7c
@@ -36,11 +36,12 @@ import java.io.Serializable;
*/ */
@Data @Data
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "authType", visible = true) @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "authType", visible = true)
@JsonSubTypes({@JsonSubTypes.Type(value = AccountAuthReq.class, name = "ACCOUNT"), @JsonSubTypes({@JsonSubTypes.Type(value = AccountLoginReq.class, name = "ACCOUNT"),
@JsonSubTypes.Type(value = EmailAuthReq.class, name = "EMAIL"), @JsonSubTypes.Type(value = EmailLoginReq.class, name = "EMAIL"),
@JsonSubTypes.Type(value = PhoneAuthReq.class, name = "PHONE"), @JsonSubTypes.Type(value = PhoneLoginReq.class, name = "PHONE"),
@JsonSubTypes.Type(value = SocialAuthReq.class, name = "SOCIAL")}) @JsonSubTypes.Type(value = SocialLoginReq.class, name = "SOCIAL")})
public class AuthReq implements Serializable { @Schema(description = "基础登录参数")
public class LoginReq implements Serializable {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@@ -48,14 +49,14 @@ public class AuthReq implements Serializable {
/** /**
* 客户端 ID * 客户端 ID
*/ */
@Schema(description = "客户端 ID") @Schema(description = "客户端 ID", example = "ef51c9a3e9046c4f2ea45142c8a8344a")
@NotBlank(message = "客户端ID不能为空") @NotBlank(message = "客户端ID不能为空")
private String clientId; private String clientId;
/** /**
* 认证类型 * 认证类型
*/ */
@Schema(description = "认证类型") @Schema(description = "认证类型", example = "ACCOUNT")
@NotNull(message = "认证类型非法") @NotNull(message = "认证类型非法")
private AuthTypeEnum authType; private AuthTypeEnum authType;
} }

View File

@@ -26,14 +26,14 @@ import org.hibernate.validator.constraints.Length;
import java.io.Serial; import java.io.Serial;
/** /**
* 手机号认证参数 * 手机号登录参数
* *
* @author Charles7c * @author Charles7c
* @since 2023/10/26 22:37 * @since 2023/10/26 22:37
*/ */
@Data @Data
@Schema(description = "手机号认证参数") @Schema(description = "手机号登录参数")
public class PhoneAuthReq extends AuthReq { public class PhoneLoginReq extends LoginReq {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -23,15 +23,15 @@ import lombok.Data;
import java.io.Serial; import java.io.Serial;
/** /**
* 第三方账号认证参数 * 第三方账号登录参数
* *
* @author KAI * @author KAI
* @author Charles7c * @author Charles7c
* @since 2024/12/25 15:43 * @since 2024/12/25 15:43
*/ */
@Data @Data
@Schema(description = "第三方账号认证参数") @Schema(description = "第三方账号登录参数")
public class SocialAuthReq extends AuthReq { public class SocialLoginReq extends LoginReq {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -17,7 +17,7 @@
package top.continew.admin.auth.service; package top.continew.admin.auth.service;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import top.continew.admin.auth.model.req.AuthReq; import top.continew.admin.auth.model.req.LoginReq;
import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.auth.model.resp.LoginResp;
import top.continew.admin.auth.model.resp.RouteResp; import top.continew.admin.auth.model.resp.RouteResp;
@@ -38,7 +38,7 @@ public interface AuthService {
* @param request 请求对象 * @param request 请求对象
* @return 登录响应参数 * @return 登录响应参数
*/ */
LoginResp login(AuthReq req, HttpServletRequest request); LoginResp login(LoginReq req, HttpServletRequest request);
/** /**
* 构建路由树 * 构建路由树

View File

@@ -24,10 +24,10 @@ import cn.hutool.core.lang.tree.TreeUtil;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import top.continew.admin.auth.AuthHandler; import top.continew.admin.auth.LoginHandler;
import top.continew.admin.auth.AuthStrategy; import top.continew.admin.auth.LoginHandlerFactory;
import top.continew.admin.auth.enums.AuthTypeEnum; import top.continew.admin.auth.enums.AuthTypeEnum;
import top.continew.admin.auth.model.req.AuthReq; import top.continew.admin.auth.model.req.LoginReq;
import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.auth.model.resp.LoginResp;
import top.continew.admin.auth.model.resp.RouteResp; import top.continew.admin.auth.model.resp.RouteResp;
import top.continew.admin.auth.service.AuthService; import top.continew.admin.auth.service.AuthService;
@@ -58,14 +58,14 @@ import java.util.Set;
@RequiredArgsConstructor @RequiredArgsConstructor
public class AuthServiceImpl implements AuthService { public class AuthServiceImpl implements AuthService {
private final AuthStrategy authStrategy; private final LoginHandlerFactory loginHandlerFactory;
private final ClientService clientService; private final ClientService clientService;
private final RoleService roleService; private final RoleService roleService;
private final MenuService menuService; private final MenuService menuService;
private final CrudProperties crudProperties; private final CrudProperties crudProperties;
@Override @Override
public LoginResp login(AuthReq req, HttpServletRequest request) { public LoginResp login(LoginReq req, HttpServletRequest request) {
AuthTypeEnum authType = req.getAuthType(); AuthTypeEnum authType = req.getAuthType();
// 校验客户端 // 校验客户端
ClientResp client = clientService.getByClientId(req.getClientId()); ClientResp client = clientService.getByClientId(req.getClientId());
@@ -74,13 +74,13 @@ public class AuthServiceImpl implements AuthService {
ValidationUtils.throwIf(!client.getAuthType().contains(authType.getValue()), "该客户端暂未授权 [{}] 认证", authType ValidationUtils.throwIf(!client.getAuthType().contains(authType.getValue()), "该客户端暂未授权 [{}] 认证", authType
.getDescription()); .getDescription());
// 获取处理器 // 获取处理器
AuthHandler<AuthReq> authHandler = authStrategy.getHandler(authType); LoginHandler<LoginReq> loginHandler = loginHandlerFactory.getHandler(authType);
// 登录前置处理 // 登录前置处理
authHandler.preLogin(req, client, request); loginHandler.preLogin(req, client, request);
// 登录 // 登录
LoginResp loginResp = authHandler.login(req, client, request); LoginResp loginResp = loginHandler.login(req, client, request);
// 登录后置处理 // 登录后置处理
authHandler.postLogin(req, client, request); loginHandler.postLogin(req, client, request);
return loginResp; return loginResp;
} }

View File

@@ -30,6 +30,7 @@ import java.util.List;
* 客户端实体 * 客户端实体
* *
* @author KAI * @author KAI
* @author Charles7c
* @since 2024/12/03 16:04 * @since 2024/12/03 16:04
*/ */
@Data @Data
@@ -66,17 +67,17 @@ public class ClientDO extends BaseDO {
private String clientType; private String clientType;
/** /**
* Token最低活跃频率-1不限制) * Token 最低活跃频率(单位:秒,-1不限制,永不冻结
*/ */
private Integer activeTimeout; private Long activeTimeout;
/** /**
* Token有效期默认30天单位:秒) * Token 有效期(单位:秒-1永不过期
*/ */
private Integer timeout; private Long timeout;
/** /**
* 状态1启用2禁用 * 状态
*/ */
private DisEnableStatusEnum status; private DisEnableStatusEnum status;
} }

View File

@@ -30,6 +30,7 @@ import java.util.List;
* 客户端查询条件 * 客户端查询条件
* *
* @author KAI * @author KAI
* @author Charles7c
* @since 2024/12/03 16:04 * @since 2024/12/03 16:04
*/ */
@Data @Data
@@ -40,28 +41,28 @@ public class ClientQuery implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 客户端Key * 客户端 Key
*/ */
@Schema(description = "客户端Key") @Schema(description = "客户端 Key", example = "PC")
private String clientKey; private String clientKey;
/** /**
* 客户端秘钥 * 客户端秘钥
*/ */
@Schema(description = "客户端秘钥") @Schema(description = "客户端秘钥", example = "dd77ab1e353a027e0d60ce3b151e8642")
private String clientSecret; private String clientSecret;
/** /**
* 认证类型 * 认证类型
*/ */
@Schema(description = "认证类型") @Schema(description = "认证类型", example = "ACCOUNT")
@Query(type = QueryType.IN) @Query(type = QueryType.IN)
private List<String> authType; private List<String> authType;
/** /**
* 客户端类型 * 客户端类型
*/ */
@Schema(description = "客户端类型") @Schema(description = "客户端类型", example = "PC")
private String clientType; private String clientType;
/** /**

View File

@@ -18,7 +18,7 @@ package top.continew.admin.system.model.req;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotEmpty;
import lombok.Data; import lombok.Data;
import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.Length;
import top.continew.admin.common.enums.DisEnableStatusEnum; import top.continew.admin.common.enums.DisEnableStatusEnum;
@@ -31,6 +31,7 @@ import java.util.List;
* 创建或修改客户端参数 * 创建或修改客户端参数
* *
* @author KAI * @author KAI
* @author Charles7c
* @since 2024/12/03 16:04 * @since 2024/12/03 16:04
*/ */
@Data @Data
@@ -41,15 +42,9 @@ public class ClientReq extends BaseReq {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 客户端ID * 客户端 Key
*/ */
@Schema(description = "客户端ID") @Schema(description = "客户端 Key", example = "PC")
private String clientId;
/**
* 客户端Key
*/
@Schema(description = "客户端Key")
@NotBlank(message = "客户端Key不能为空") @NotBlank(message = "客户端Key不能为空")
@Length(max = 32, message = "客户端Key长度不能超过 {max} 个字符") @Length(max = 32, message = "客户端Key长度不能超过 {max} 个字符")
private String clientKey; private String clientKey;
@@ -57,7 +52,7 @@ public class ClientReq extends BaseReq {
/** /**
* 客户端秘钥 * 客户端秘钥
*/ */
@Schema(description = "客户端秘钥") @Schema(description = "客户端秘钥", example = "dd77ab1e353a027e0d60ce3b151e8642")
@NotBlank(message = "客户端秘钥不能为空") @NotBlank(message = "客户端秘钥不能为空")
@Length(max = 255, message = "客户端秘钥长度不能超过 {max} 个字符") @Length(max = 255, message = "客户端秘钥长度不能超过 {max} 个字符")
private String clientSecret; private String clientSecret;
@@ -65,33 +60,39 @@ public class ClientReq extends BaseReq {
/** /**
* 认证类型 * 认证类型
*/ */
@Schema(description = "认证类型") @Schema(description = "认证类型", example = "ACCOUNT")
@NotNull(message = "认证类型不能为空") @NotEmpty(message = "认证类型不能为空")
private List<String> authType; private List<String> authType;
/** /**
* 客户端类型 * 客户端类型
*/ */
@Schema(description = "客户端类型") @Schema(description = "客户端类型", example = "PC")
@NotBlank(message = "客户端类型不能为空") @NotBlank(message = "客户端类型不能为空")
@Length(max = 32, message = "客户端类型长度不能超过 {max} 个字符") @Length(max = 32, message = "客户端类型长度不能超过 {max} 个字符")
private String clientType; private String clientType;
/** /**
* Token最低活跃频率-1不限制) * Token 最低活跃频率(单位:秒,-1不限制,永不冻结
*/ */
@Schema(description = "Token最低活跃频率-1不限制") @Schema(description = "Token 最低活跃频率(单位:秒,-1不限制,永不冻结)", example = "1800")
private Integer activeTimeout; private Long activeTimeout;
/** /**
* Token有效期默认30天单位:秒) * Token 有效期(单位:秒-1永不过期
*/ */
@Schema(description = "Token有效期默认30天单位") @Schema(description = "Token 有效期(单位:秒,-1永不过期", example = "86400")
private Integer timeout; private Long timeout;
/** /**
* 状态 * 状态
*/ */
@Schema(description = "状态", example = "1") @Schema(description = "状态", example = "1")
private DisEnableStatusEnum status; private DisEnableStatusEnum status;
/**
* 客户端 ID
*/
@Schema(hidden = true)
private String clientId;
} }

View File

@@ -19,7 +19,6 @@ package top.continew.admin.system.model.req.user;
import cn.hutool.core.lang.RegexPool; import cn.hutool.core.lang.RegexPool;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Pattern;
import lombok.Data; import lombok.Data;
import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.Length;

View File

@@ -16,13 +16,10 @@
package top.continew.admin.system.model.resp; package top.continew.admin.system.model.resp;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import top.continew.admin.common.enums.DisEnableStatusEnum; import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.starter.extension.crud.model.resp.BaseDetailResp; import top.continew.starter.extension.crud.model.resp.BaseDetailResp;
import top.continew.starter.file.excel.converter.ExcelBaseEnumConverter;
import java.io.Serial; import java.io.Serial;
import java.util.List; import java.util.List;
@@ -34,7 +31,6 @@ import java.util.List;
* @since 2024/12/03 16:04 * @since 2024/12/03 16:04
*/ */
@Data @Data
@ExcelIgnoreUnannotated
@Schema(description = "客户端详情信息") @Schema(description = "客户端详情信息")
public class ClientDetailResp extends BaseDetailResp { public class ClientDetailResp extends BaseDetailResp {
@@ -45,55 +41,47 @@ public class ClientDetailResp extends BaseDetailResp {
* 客户端ID * 客户端ID
*/ */
@Schema(description = "客户端ID") @Schema(description = "客户端ID")
@ExcelProperty(value = "客户端ID", order = 2)
private String clientId; private String clientId;
/** /**
* 客户端Key * 客户端Key
*/ */
@Schema(description = "客户端Key") @Schema(description = "客户端Key")
@ExcelProperty(value = "客户端Key", order = 3)
private String clientKey; private String clientKey;
/** /**
* 客户端秘钥 * 客户端秘钥
*/ */
@Schema(description = "客户端秘钥") @Schema(description = "客户端秘钥")
@ExcelProperty(value = "客户端秘钥", order = 4)
private String clientSecret; private String clientSecret;
/** /**
* 登录类型 * 登录类型
*/ */
@Schema(description = "登录类型") @Schema(description = "登录类型")
@ExcelProperty(value = "登录类型", order = 5)
private List<String> authType; private List<String> authType;
/** /**
* 客户端类型 * 客户端类型
*/ */
@Schema(description = "客户端类型") @Schema(description = "客户端类型")
@ExcelProperty(value = "客户端类型", order = 6)
private String clientType; private String clientType;
/** /**
* Token最低活跃频率-1为不限制 * Token最低活跃频率-1为不限制
*/ */
@Schema(description = "Token最低活跃频率-1为不限制") @Schema(description = "Token最低活跃频率-1为不限制")
@ExcelProperty(value = "Token最低活跃频率-1为不限制", order = 7)
private Integer activeTimeout; private Integer activeTimeout;
/** /**
* Token有效期默认30天单位 * Token有效期默认30天单位
*/ */
@Schema(description = "Token有效期默认30天单位") @Schema(description = "Token有效期默认30天单位")
@ExcelProperty(value = "Token有效期默认30天单位", order = 8)
private Integer timeout; private Integer timeout;
/** /**
* 状态 * 状态
*/ */
@Schema(description = "状态", example = "1") @Schema(description = "状态", example = "1")
@ExcelProperty(value = "状态", converter = ExcelBaseEnumConverter.class, order = 9)
private DisEnableStatusEnum status; private DisEnableStatusEnum status;
} }

View File

@@ -28,6 +28,7 @@ import java.util.List;
* 客户端信息 * 客户端信息
* *
* @author KAI * @author KAI
* @author Charles7c
* @since 2024/12/03 16:04 * @since 2024/12/03 16:04
*/ */
@Data @Data
@@ -38,50 +39,50 @@ public class ClientResp extends BaseResp {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 客户端ID * 客户端 ID
*/ */
@Schema(description = "客户端ID") @Schema(description = "客户端 ID", example = "ef51c9a3e9046c4f2ea45142c8a8344a")
private String clientId; private String clientId;
/** /**
* 客户端Key * 客户端 Key
*/ */
@Schema(description = "客户端Key") @Schema(description = "客户端 Key", example = "PC")
private String clientKey; private String clientKey;
/** /**
* 客户端秘钥 * 客户端秘钥
*/ */
@Schema(description = "客户端秘钥") @Schema(description = "客户端秘钥", example = "dd77ab1e353a027e0d60ce3b151e8642")
private String clientSecret; private String clientSecret;
/** /**
* 认证类型 * 认证类型
*/ */
@Schema(description = "认证类型") @Schema(description = "认证类型", example = "ACCOUNT")
private List<String> authType; private List<String> authType;
/** /**
* 客户端类型 * 客户端类型
*/ */
@Schema(description = "客户端类型") @Schema(description = "客户端类型", example = "PC")
private String clientType; private String clientType;
/** /**
* Token最低活跃频率-1不限制) * Token 最低活跃频率(单位:秒,-1不限制,永不冻结
*/ */
@Schema(description = "Token最低活跃频率-1不限制") @Schema(description = "Token 最低活跃频率(单位:秒,-1不限制,永不冻结)", example = "1800")
private Integer activeTimeout; private Integer activeTimeout;
/** /**
* Token有效期默认30天单位:秒) * Token 有效期(单位:秒-1永不过期
*/ */
@Schema(description = "Token有效期默认30天单位") @Schema(description = "Token 有效期(单位:秒,-1永不过期", example = "86400")
private Integer timeout; private Integer timeout;
/** /**
* 状态1启用2禁用 * 状态
*/ */
@Schema(description = "状态") @Schema(description = "状态", example = "1")
private DisEnableStatusEnum status; private DisEnableStatusEnum status;
} }

View File

@@ -124,14 +124,6 @@ public interface UserService extends BaseService<UserResp, UserDetailResp, UserQ
*/ */
void updateEmail(String newEmail, String oldPassword, Long id); void updateEmail(String newEmail, String oldPassword, Long id);
/**
* 新增
*
* @param user 用户信息
* @return ID
*/
Long add(UserDO user);
/** /**
* 根据用户名查询 * 根据用户名查询
* *

View File

@@ -439,13 +439,6 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
baseMapper.lambdaUpdate().set(UserDO::getEmail, newEmail).eq(UserDO::getId, id).update(); baseMapper.lambdaUpdate().set(UserDO::getEmail, newEmail).eq(UserDO::getId, id).update();
} }
@Override
public Long add(UserDO user) {
user.setStatus(DisEnableStatusEnum.ENABLE);
baseMapper.insert(user);
return user.getId();
}
@Override @Override
public UserDO getByUsername(String username) { public UserDO getByUsername(String username) {
return baseMapper.selectByUsername(username); return baseMapper.selectByUsername(username);

View File

@@ -29,7 +29,7 @@ import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import top.continew.admin.auth.enums.AuthTypeEnum; import top.continew.admin.auth.enums.AuthTypeEnum;
import top.continew.admin.auth.model.req.AccountAuthReq; import top.continew.admin.auth.model.req.AccountLoginReq;
import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.constant.SysConstants;
import top.continew.admin.system.enums.LogStatusEnum; import top.continew.admin.system.enums.LogStatusEnum;
import top.continew.admin.system.mapper.LogMapper; import top.continew.admin.system.mapper.LogMapper;
@@ -148,7 +148,7 @@ public class LogDaoLocalImpl implements LogDao {
String requestBody = logRequest.getBody(); String requestBody = logRequest.getBody();
// 解析账号登录用户为操作人 // 解析账号登录用户为操作人
if (requestBody.contains(AuthTypeEnum.ACCOUNT.getValue())) { if (requestBody.contains(AuthTypeEnum.ACCOUNT.getValue())) {
AccountAuthReq authReq = JSONUtil.toBean(requestBody, AccountAuthReq.class); AccountLoginReq authReq = JSONUtil.toBean(requestBody, AccountLoginReq.class);
logDO.setCreateUser(ExceptionUtils.exToNull(() -> userService.getByUsername(authReq.getUsername()) logDO.setCreateUser(ExceptionUtils.exToNull(() -> userService.getByUsername(authReq.getUsername())
.getId())); .getId()));
return; return;

View File

@@ -19,23 +19,28 @@ package top.continew.admin.controller.auth;
import cn.dev33.satoken.annotation.SaIgnore; import cn.dev33.satoken.annotation.SaIgnore;
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 com.xkcoding.justauth.AuthRequestFactory;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import top.continew.admin.auth.model.req.AuthReq; import top.continew.admin.auth.model.req.LoginReq;
import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.auth.model.resp.LoginResp;
import top.continew.admin.auth.model.resp.RouteResp; import top.continew.admin.auth.model.resp.RouteResp;
import top.continew.admin.auth.model.resp.SocialAuthAuthorizeResp;
import top.continew.admin.auth.model.resp.UserInfoResp; import top.continew.admin.auth.model.resp.UserInfoResp;
import top.continew.admin.auth.service.AuthService; import top.continew.admin.auth.service.AuthService;
import top.continew.admin.common.context.UserContext; import top.continew.admin.common.context.UserContext;
import top.continew.admin.common.context.UserContextHolder; import top.continew.admin.common.context.UserContextHolder;
import top.continew.admin.system.model.resp.user.UserDetailResp; import top.continew.admin.system.model.resp.user.UserDetailResp;
import top.continew.admin.system.service.UserService; import top.continew.admin.system.service.UserService;
import top.continew.starter.core.exception.BadRequestException;
import top.continew.starter.log.annotation.Log; import top.continew.starter.log.annotation.Log;
import java.util.List; import java.util.List;
@@ -56,11 +61,12 @@ public class AuthController {
private final AuthService authService; private final AuthService authService;
private final UserService userService; private final UserService userService;
private final AuthRequestFactory authRequestFactory;
@SaIgnore @SaIgnore
@Operation(summary = "登录", description = "用户登录") @Operation(summary = "登录", description = "用户登录")
@PostMapping("/login") @PostMapping("/login")
public LoginResp login(@Validated @RequestBody AuthReq req, HttpServletRequest request) { public LoginResp login(@Validated @RequestBody LoginReq req, HttpServletRequest request) {
return authService.login(req, request); return authService.login(req, request);
} }
@@ -73,6 +79,17 @@ public class AuthController {
return loginId; return loginId;
} }
@SaIgnore
@Operation(summary = "三方账号登录授权", description = "三方账号登录授权")
@Parameter(name = "source", description = "来源", example = "gitee", in = ParameterIn.PATH)
@GetMapping("/{source}")
public SocialAuthAuthorizeResp authorize(@PathVariable String source) {
AuthRequest authRequest = this.getAuthRequest(source);
return SocialAuthAuthorizeResp.builder()
.authorizeUrl(authRequest.authorize(AuthStateUtils.createState()))
.build();
}
@Log(ignore = true) @Log(ignore = true)
@Operation(summary = "获取用户信息", description = "获取登录用户信息") @Operation(summary = "获取用户信息", description = "获取登录用户信息")
@GetMapping("/user/info") @GetMapping("/user/info")
@@ -92,4 +109,12 @@ public class AuthController {
public List<RouteResp> listRoute() { public List<RouteResp> listRoute() {
return authService.buildRouteTree(UserContextHolder.getUserId()); return authService.buildRouteTree(UserContextHolder.getUserId());
} }
private AuthRequest getAuthRequest(String source) {
try {
return authRequestFactory.get(source);
} catch (Exception e) {
throw new BadRequestException("暂不支持 [%s] 平台账号登录".formatted(source));
}
}
} }

View File

@@ -1,69 +0,0 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.controller.auth;
import cn.dev33.satoken.annotation.SaIgnore;
import com.xkcoding.justauth.AuthRequestFactory;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
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 top.continew.admin.auth.model.resp.SocialAuthAuthorizeResp;
import top.continew.starter.core.exception.BadRequestException;
import top.continew.starter.log.annotation.Log;
/**
* 三方账号认证 API
*
* @author Charles7c
* @since 2023/10/8 22:52
*/
@Log(module = "登录")
@Tag(name = "三方账号认证 API")
@SaIgnore
@RestController
@RequiredArgsConstructor
@RequestMapping("/oauth")
public class SocialAuthController {
private final AuthRequestFactory authRequestFactory;
@Operation(summary = "三方账号登录授权", description = "三方账号登录授权")
@Parameter(name = "source", description = "来源", example = "gitee", in = ParameterIn.PATH)
@GetMapping("/{source}")
public SocialAuthAuthorizeResp authorize(@PathVariable String source) {
AuthRequest authRequest = this.getAuthRequest(source);
return SocialAuthAuthorizeResp.builder()
.authorizeUrl(authRequest.authorize(AuthStateUtils.createState()))
.build();
}
private AuthRequest getAuthRequest(String source) {
try {
return authRequestFactory.get(source);
} catch (Exception e) {
throw new BadRequestException("暂不支持 [%s] 平台账号登录".formatted(source));
}
}
}

View File

@@ -35,6 +35,6 @@ import top.continew.starter.extension.crud.enums.Api;
*/ */
@Tag(name = "客户端管理 API") @Tag(name = "客户端管理 API")
@RestController @RestController
@CrudRequestMapping(value = "/system/client", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT}) @CrudRequestMapping(value = "/system/client", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE})
public class ClientController extends BaseController<ClientService, ClientResp, ClientDetailResp, ClientQuery, ClientReq> { public class ClientController extends BaseController<ClientService, ClientResp, ClientDetailResp, ClientQuery, ClientReq> {
} }

View File

@@ -127,17 +127,17 @@ knife4j:
--- ### Sa-Token 配置 --- ### Sa-Token 配置
sa-token: sa-token:
# token 名称(同时也是 cookie 名称) # Token 名称(同时也是 cookie 名称)
token-name: Authorization token-name: Authorization
# token 有效期(单位:秒,默认 30 天,-1 代表永不过期) # Token 有效期(单位:秒,默认 30 天,-1 代表永不过期)
timeout: 86400 timeout: 86400
# token 最低活跃频率(单位:秒,默认 -1代表不限制永不冻结。如果 token 超过此时间没有访问系统就会被冻结) # Token 最低活跃频率(单位:秒,默认 -1代表不限制永不冻结。如果 token 超过此时间没有访问系统就会被冻结)
active-timeout: 1800 active-timeout: 1800
# 是否打开自动续签(如果此值为 true框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作) # 是否打开自动续签(如果此值为 true框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作)
auto-renew: true auto-renew: true
# 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录) # 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
is-concurrent: true is-concurrent: true
# 在多人登录同一账号时,是否共用一个 token为 true 时所有登录共用一个 token为 false 时每次登录新建一个 token # 在多人登录同一账号时,是否共用一个 Token为 true 时所有登录共用一个 Token为 false 时每次登录新建一个 Token
is-share: false is-share: false
# 是否输出操作日志 # 是否输出操作日志
is-log: false is-log: false