From 9eafb332c8081d6194ee19c4c9f4e3dfd8b1613d Mon Sep 17 00:00:00 2001 From: KAI <1373639299@qq.com> Date: Mon, 23 Dec 2024 12:07:02 +0800 Subject: [PATCH 01/12] =?UTF-8?q?fix(system/notice):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E5=85=AC=E5=91=8A=E5=88=86=E9=A1=B5=20?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E8=8C=83=E5=9B=B4=E5=AD=97=E6=AE=B5=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=9B=9E=E6=98=BE=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/top/continew/admin/system/model/resp/NoticeResp.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/continew-module-system/src/main/java/top/continew/admin/system/model/resp/NoticeResp.java b/continew-module-system/src/main/java/top/continew/admin/system/model/resp/NoticeResp.java index e477af70..27e022b1 100644 --- a/continew-module-system/src/main/java/top/continew/admin/system/model/resp/NoticeResp.java +++ b/continew-module-system/src/main/java/top/continew/admin/system/model/resp/NoticeResp.java @@ -18,6 +18,7 @@ package top.continew.admin.system.model.resp; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import top.continew.admin.system.enums.NoticeScopeEnum; import top.continew.admin.system.enums.NoticeStatusEnum; import top.continew.starter.extension.crud.model.resp.BaseResp; @@ -76,7 +77,7 @@ public class NoticeResp extends BaseResp { * 通知范围 */ @Schema(description = "通知范围(1.所有人 2.指定用户)", example = "1") - private Integer noticeScope; + private NoticeScopeEnum noticeScope; /** * 指定用户 -- Gitee From aa56bc138f0b92728013b5273b7d5bd6f90a818b Mon Sep 17 00:00:00 2001 From: KAI <1373639299@qq.com> Date: Tue, 24 Dec 2024 15:58:01 +0800 Subject: [PATCH 02/12] =?UTF-8?q?feat:=20=E5=A4=9A=E7=AB=AF=E7=99=BB?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/common/constant/SysConstants.java | 2 +- .../admin/common/context/UserContext.java | 10 ++ .../auth/config/auth/AuthStrategyContext.java | 37 ++++++ .../admin/auth/enums/AuthTypeEnum.java | 42 ++++++ ...countLoginReq.java => AccountAuthReq.java} | 4 +- .../admin/auth/model/req/AuthReq.java | 31 +++++ .../{EmailLoginReq.java => EmailAuthReq.java} | 2 +- .../{PhoneLoginReq.java => PhoneAuthReq.java} | 2 +- .../admin/auth/service/LoginService.java | 27 ++-- .../auth/service/impl/LoginServiceImpl.java | 47 ++----- .../admin/auth/strategy/AuthStrategy.java | 39 ++++++ .../strategy/impl/AbstractAuthStrategy.java | 121 ++++++++++++++++++ .../strategy/impl/AccountLoginStrategy.java | 105 +++++++++++++++ .../auth/strategy/impl/EmailAuthStrategy.java | 91 +++++++++++++ .../auth/strategy/impl/PhoneAuthStrategy.java | 93 ++++++++++++++ .../admin/system/mapper/ClientMapper.java | 12 ++ .../admin/system/model/entity/ClientDO.java | 66 ++++++++++ .../admin/system/model/query/ClientQuery.java | 59 +++++++++ .../admin/system/model/req/ClientReq.java | 81 ++++++++++++ .../system/model/resp/ClientDetailResp.java | 82 ++++++++++++ .../admin/system/model/resp/ClientResp.java | 71 ++++++++++ .../admin/system/service/ClientService.java | 19 +++ .../service/impl/ClientServiceImpl.java | 37 ++++++ .../admin/config/log/LogDaoLocalImpl.java | 24 ++-- .../admin/controller/auth/AuthController.java | 110 +++++----------- .../controller/system/ClientController.java | 24 ++++ 26 files changed, 1098 insertions(+), 140 deletions(-) create mode 100644 continew-module-system/src/main/java/top/continew/admin/auth/config/auth/AuthStrategyContext.java create mode 100644 continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java rename continew-module-system/src/main/java/top/continew/admin/auth/model/req/{AccountLoginReq.java => AccountAuthReq.java} (90%) create mode 100644 continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java rename continew-module-system/src/main/java/top/continew/admin/auth/model/req/{EmailLoginReq.java => EmailAuthReq.java} (96%) rename continew-module-system/src/main/java/top/continew/admin/auth/model/req/{PhoneLoginReq.java => PhoneAuthReq.java} (96%) create mode 100644 continew-module-system/src/main/java/top/continew/admin/auth/strategy/AuthStrategy.java create mode 100644 continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AbstractAuthStrategy.java create mode 100644 continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AccountLoginStrategy.java create mode 100644 continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/EmailAuthStrategy.java create mode 100644 continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/PhoneAuthStrategy.java create mode 100644 continew-module-system/src/main/java/top/continew/admin/system/mapper/ClientMapper.java create mode 100644 continew-module-system/src/main/java/top/continew/admin/system/model/entity/ClientDO.java create mode 100644 continew-module-system/src/main/java/top/continew/admin/system/model/query/ClientQuery.java create mode 100644 continew-module-system/src/main/java/top/continew/admin/system/model/req/ClientReq.java create mode 100644 continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientDetailResp.java create mode 100644 continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientResp.java create mode 100644 continew-module-system/src/main/java/top/continew/admin/system/service/ClientService.java create mode 100644 continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java create mode 100644 continew-webapi/src/main/java/top/continew/admin/controller/system/ClientController.java diff --git a/continew-common/src/main/java/top/continew/admin/common/constant/SysConstants.java b/continew-common/src/main/java/top/continew/admin/common/constant/SysConstants.java index 8d75579c..2e9ad5c3 100644 --- a/continew-common/src/main/java/top/continew/admin/common/constant/SysConstants.java +++ b/continew-common/src/main/java/top/continew/admin/common/constant/SysConstants.java @@ -67,7 +67,7 @@ public class SysConstants { /** * 账号登录 URI */ - public static final String LOGIN_URI = "/auth/account"; + public static final String LOGIN_URI = "/auth/login"; /** * 退出 URI diff --git a/continew-common/src/main/java/top/continew/admin/common/context/UserContext.java b/continew-common/src/main/java/top/continew/admin/common/context/UserContext.java index 6646201c..4495a8c3 100644 --- a/continew-common/src/main/java/top/continew/admin/common/context/UserContext.java +++ b/continew-common/src/main/java/top/continew/admin/common/context/UserContext.java @@ -80,6 +80,16 @@ public class UserContext implements Serializable { */ private Set roles; + /** + * 设备类型 + */ + private String clientType; + + /** + * 客户端ID + */ + private String clientId; + public UserContext(Set permissions, Set roles, Integer passwordExpirationDays) { this.permissions = permissions; this.setRoles(roles); diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/config/auth/AuthStrategyContext.java b/continew-module-system/src/main/java/top/continew/admin/auth/config/auth/AuthStrategyContext.java new file mode 100644 index 00000000..f42338bd --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/auth/config/auth/AuthStrategyContext.java @@ -0,0 +1,37 @@ +package top.continew.admin.auth.config.auth; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import top.continew.admin.auth.model.req.AuthReq; +import top.continew.admin.auth.strategy.AuthStrategy; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 登录类型策略上文 + * + * @author 莫愁 + * @since 2024/12/20 15:16:55 + */ +@Component +public class AuthStrategyContext { + private final Map> strategyMap = new HashMap<>(); + + @Autowired + public AuthStrategyContext(List> strategies) { + for (AuthStrategy strategy : strategies) { + strategyMap.put(strategy.getAuthType().getValue(), strategy); + } + } + + @SuppressWarnings("unchecked") + public AuthStrategy getStrategy(String type) { + AuthStrategy strategy = strategyMap.get(type); + if (strategy == null) { + throw new IllegalArgumentException("No strategy found for type: " + type); + } + return (AuthStrategy) strategy; + } +} diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java b/continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java new file mode 100644 index 00000000..8c9a482d --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java @@ -0,0 +1,42 @@ +package top.continew.admin.auth.enums; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import top.continew.admin.common.constant.UiConstants; +import top.continew.starter.core.enums.BaseEnum; + +/** + * 认证类型 + * + * @author Charles7c + * @since 2023/12/23 13:38 + */ +@Getter +@RequiredArgsConstructor +public enum AuthTypeEnum implements BaseEnum { + + /** + * 账号 + */ + ACCOUNT("account", "账号", UiConstants.COLOR_ERROR), + + /** + * 邮箱 + */ + EMAIL("email", "邮箱", UiConstants.COLOR_PRIMARY), + + /** + * 手机号 + */ + PHONE("phone", "手机号", UiConstants.COLOR_DEFAULT), + + /** + * 第三方授权 + */ + SOCIAL_AUTH("SocialAuth", "第三方授权", UiConstants.COLOR_DEFAULT); + + + private final String value; + private final String description; + private final String color; +} diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AccountLoginReq.java b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AccountAuthReq.java similarity index 90% rename from continew-module-system/src/main/java/top/continew/admin/auth/model/req/AccountLoginReq.java rename to continew-module-system/src/main/java/top/continew/admin/auth/model/req/AccountAuthReq.java index 0ed4148c..1d97b550 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AccountLoginReq.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AccountAuthReq.java @@ -19,6 +19,8 @@ package top.continew.admin.auth.model.req; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; +import top.continew.admin.common.constant.SysConstants; +import top.continew.starter.core.validation.ValidationUtils; import java.io.Serial; import java.io.Serializable; @@ -31,7 +33,7 @@ import java.io.Serializable; */ @Data @Schema(description = "账号登录参数") -public class AccountLoginReq implements Serializable { +public class AccountAuthReq extends AuthReq implements Serializable { @Serial private static final long serialVersionUID = 1L; diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java new file mode 100644 index 00000000..b5a72a75 --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java @@ -0,0 +1,31 @@ +package top.continew.admin.auth.model.req; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * 登录参数基础类 + * + * @author 莫愁 + * @since 2024/12/22 15:16:39 + */ +@Data +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "authType", visible = true) +@JsonSubTypes({ + @JsonSubTypes.Type(value = AccountAuthReq.class, name = "account"), + @JsonSubTypes.Type(value = EmailAuthReq.class, name = "email"), + @JsonSubTypes.Type(value = PhoneAuthReq.class, name = "phone") +}) +public abstract class AuthReq { + + @Schema(description = "ClientId 客户端标识") + @NotBlank(message = "客户端标识不能为空") + private String clientId; + + @Schema(description = "认证类型") + @NotBlank(message = "认证类型不能为空") + private String authType; +} diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/EmailLoginReq.java b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/EmailAuthReq.java similarity index 96% rename from continew-module-system/src/main/java/top/continew/admin/auth/model/req/EmailLoginReq.java rename to continew-module-system/src/main/java/top/continew/admin/auth/model/req/EmailAuthReq.java index 5959a898..f84d0e3d 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/EmailLoginReq.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/EmailAuthReq.java @@ -34,7 +34,7 @@ import java.io.Serializable; */ @Data @Schema(description = "邮箱登录参数") -public class EmailLoginReq implements Serializable { +public class EmailAuthReq extends AuthReq implements Serializable { @Serial private static final long serialVersionUID = 1L; diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/PhoneLoginReq.java b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/PhoneAuthReq.java similarity index 96% rename from continew-module-system/src/main/java/top/continew/admin/auth/model/req/PhoneLoginReq.java rename to continew-module-system/src/main/java/top/continew/admin/auth/model/req/PhoneAuthReq.java index f81cc74f..5072b624 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/PhoneLoginReq.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/PhoneAuthReq.java @@ -34,7 +34,7 @@ import java.io.Serializable; */ @Data @Schema(description = "手机号登录参数") -public class PhoneLoginReq implements Serializable { +public class PhoneAuthReq extends AuthReq implements Serializable { @Serial private static final long serialVersionUID = 1L; diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/service/LoginService.java b/continew-module-system/src/main/java/top/continew/admin/auth/service/LoginService.java index 34a81359..7b8179d1 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/service/LoginService.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/service/LoginService.java @@ -19,6 +19,7 @@ package top.continew.admin.auth.service; import jakarta.servlet.http.HttpServletRequest; import me.zhyd.oauth.model.AuthUser; import top.continew.admin.auth.model.resp.RouteResp; +import top.continew.admin.system.model.entity.UserDO; import java.util.List; @@ -31,30 +32,28 @@ import java.util.List; public interface LoginService { /** - * 账号登录 + * 检查用户状态 * - * @param username 用户名 - * @param password 密码 - * @param request 请求对象 - * @return 令牌 + * @param user 用户信息 */ - String accountLogin(String username, String password, HttpServletRequest request); + void checkUserStatus(UserDO user); /** - * 手机号登录 + * 检查用户是否被锁定 * - * @param phone 手机号 - * @return 令牌 + * @param username 用户名 + * @param request 请求对象 + * @param isError 是否登录错误 */ - String phoneLogin(String phone); + void checkUserLocked(String username, HttpServletRequest request, boolean isError); /** - * 邮箱登录 + * 执行登录操作 * - * @param email 邮箱 - * @return 令牌 + * @param user 用户信息 + * @return token */ - String emailLogin(String email); + String login(UserDO user); /** * 三方账号登录 diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java b/continew-module-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java index 48d0ebbe..e0c6ae47 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java @@ -96,32 +96,6 @@ public class LoginServiceImpl implements LoginService { private final OptionService optionService; private final MessageService messageService; - @Override - public String accountLogin(String username, String password, HttpServletRequest request) { - UserDO user = userService.getByUsername(username); - boolean isError = ObjectUtil.isNull(user) || !passwordEncoder.matches(password, user.getPassword()); - this.checkUserLocked(username, request, isError); - CheckUtils.throwIf(isError, "用户名或密码错误"); - this.checkUserStatus(user); - return this.login(user); - } - - @Override - public String phoneLogin(String phone) { - UserDO user = userService.getByPhone(phone); - CheckUtils.throwIfNull(user, "此手机号未绑定本系统账号"); - this.checkUserStatus(user); - return this.login(user); - } - - @Override - public String emailLogin(String email) { - UserDO user = userService.getByEmail(email); - CheckUtils.throwIfNull(user, "此邮箱未绑定本系统账号"); - this.checkUserStatus(user); - return this.login(user); - } - @Override @Transactional(rollbackFor = Exception.class) public String socialLogin(AuthUser authUser) { @@ -209,21 +183,22 @@ public class LoginServiceImpl implements LoginService { * @param user 用户信息 * @return 令牌 */ - private String login(UserDO user) { + @Override + public String login(UserDO user) { Long userId = user.getId(); CompletableFuture> permissionFuture = CompletableFuture.supplyAsync(() -> roleService - .listPermissionByUserId(userId), threadPoolTaskExecutor); + .listPermissionByUserId(userId), threadPoolTaskExecutor); CompletableFuture> roleFuture = CompletableFuture.supplyAsync(() -> roleService - .listByUserId(userId), threadPoolTaskExecutor); + .listByUserId(userId), threadPoolTaskExecutor); CompletableFuture passwordExpirationDaysFuture = CompletableFuture.supplyAsync(() -> optionService - .getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name())); + .getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name())); CompletableFuture.allOf(permissionFuture, roleFuture, passwordExpirationDaysFuture); UserContext userContext = new UserContext(permissionFuture.join(), roleFuture - .join(), passwordExpirationDaysFuture.join()); + .join(), passwordExpirationDaysFuture.join()); BeanUtil.copyProperties(user, userContext); // 登录并缓存用户信息 StpUtil.login(userContext.getId(), SaLoginConfig.setExtraData(BeanUtil - .beanToMap(new UserExtraContext(SpringWebUtils.getRequest())))); + .beanToMap(new UserExtraContext(SpringWebUtils.getRequest())))); UserContextHolder.setContext(userContext); return StpUtil.getTokenValue(); } @@ -233,7 +208,8 @@ public class LoginServiceImpl implements LoginService { * * @param user 用户信息 */ - private void checkUserStatus(UserDO user) { + @Override + public void checkUserStatus(UserDO user) { CheckUtils.throwIfEqual(DisEnableStatusEnum.DISABLE, user.getStatus(), "此账号已被禁用,如有疑问,请联系管理员"); DeptDO dept = deptService.getById(user.getDeptId()); CheckUtils.throwIfEqual(DisEnableStatusEnum.DISABLE, dept.getStatus(), "此账号所属部门已被禁用,如有疑问,请联系管理员"); @@ -246,7 +222,8 @@ public class LoginServiceImpl implements LoginService { * @param request 请求对象 * @param isError 是否登录错误 */ - private void checkUserLocked(String username, HttpServletRequest request, boolean isError) { + @Override + public void checkUserLocked(String username, HttpServletRequest request, boolean isError) { // 不锁定 int maxErrorCount = optionService.getValueByCode2Int(PasswordPolicyEnum.PASSWORD_ERROR_LOCK_COUNT.name()); if (maxErrorCount <= SysConstants.NO) { @@ -254,7 +231,7 @@ public class LoginServiceImpl implements LoginService { } // 检测是否已被锁定 String key = CacheConstants.USER_PASSWORD_ERROR_KEY_PREFIX + RedisUtils.formatKey(username, JakartaServletUtil - .getClientIP(request)); + .getClientIP(request)); int lockMinutes = optionService.getValueByCode2Int(PasswordPolicyEnum.PASSWORD_ERROR_LOCK_MINUTES.name()); Integer currentErrorCount = ObjectUtil.defaultIfNull(RedisUtils.get(key), 0); CheckUtils.throwIf(currentErrorCount >= maxErrorCount, "账号锁定 {} 分钟,请稍后再试", lockMinutes); diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/AuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/AuthStrategy.java new file mode 100644 index 00000000..39ecef71 --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/AuthStrategy.java @@ -0,0 +1,39 @@ +package top.continew.admin.auth.strategy; + +import jakarta.servlet.http.HttpServletRequest; +import top.continew.admin.auth.enums.AuthTypeEnum; +import top.continew.admin.auth.model.req.AuthReq; +import top.continew.admin.system.model.resp.ClientResp; + +/** + * 登录策略接口 + * + * @author 莫愁 + * @since 2024/12/22 14:52:23 + */ +public interface AuthStrategy { + + /** + * 执行登录 + * + * @param authReq 登录请求参数 + * @param request HTTP请求对象 + * @return 登录响应 + */ + R login(T authReq, ClientResp clientResp, HttpServletRequest request); + + /** + * 获取登录类型 + * + * @return 登录类型Enum + */ + AuthTypeEnum getAuthType(); + + /** + * 校验参数 + * + * @param authReq 登录请求参数 + */ + void validate(T authReq); + +} \ No newline at end of file diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AbstractAuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AbstractAuthStrategy.java new file mode 100644 index 00000000..10504324 --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AbstractAuthStrategy.java @@ -0,0 +1,121 @@ +package top.continew.admin.auth.strategy.impl; + +import cn.dev33.satoken.stp.SaLoginConfig; +import cn.dev33.satoken.stp.SaLoginModel; +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.bean.BeanUtil; +import jakarta.annotation.Resource; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Component; +import top.continew.admin.common.context.RoleContext; +import top.continew.admin.common.context.UserContext; +import top.continew.admin.common.context.UserContextHolder; +import top.continew.admin.common.context.UserExtraContext; +import top.continew.admin.system.model.entity.UserDO; +import top.continew.admin.system.model.resp.ClientResp; +import top.continew.admin.system.service.OptionService; +import top.continew.admin.system.service.RoleService; +import top.continew.starter.web.util.SpringWebUtils; + +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +import static top.continew.admin.system.enums.PasswordPolicyEnum.PASSWORD_EXPIRATION_DAYS; + +/** + * 登录策略 + * + * @author 莫愁 + * @since 2024/12/22 14:52:32 + */ +@Component +@RequiredArgsConstructor +public abstract class AbstractAuthStrategy { + @Resource + private RoleService roleService; + @Resource + private OptionService optionService; + @Resource + private ThreadPoolTaskExecutor threadPoolTaskExecutor; + + public static final String CAPTCHA_EXPIRED = "验证码已失效"; + public static final String CAPTCHA_ERROR = "验证码错误"; + + /** + * 获取登录凭证 + * + * @param user 用户信息 + * @param clientResp 客户端信息 + * @return token 认证信息 + */ + protected String authCertificate(UserDO user, ClientResp clientResp) { + preLogin(user, clientResp); + // 核心登录逻辑 + Long userId = user.getId(); + CompletableFuture> permissionFuture = CompletableFuture.supplyAsync(() -> roleService + .listPermissionByUserId(userId), threadPoolTaskExecutor); + CompletableFuture> roleFuture = CompletableFuture.supplyAsync(() -> roleService + .listByUserId(userId), threadPoolTaskExecutor); + CompletableFuture passwordExpirationDaysFuture = CompletableFuture.supplyAsync(() -> optionService + .getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name())); + CompletableFuture.allOf(permissionFuture, roleFuture, passwordExpirationDaysFuture); + + UserContext userContext = new UserContext(permissionFuture.join(), roleFuture + .join(), passwordExpirationDaysFuture.join()); + + BeanUtil.copyProperties(user, userContext); + SaLoginModel model = new SaLoginModel(); + //设置登录 token 最低活跃频率 如未指定,则使用全局配置的 activeTimeout 值 + model.setActiveTimeout(clientResp.getActiveTimeout()); + //设置登录 token 有效期,单位:秒 (如未指定,自动取全局配置的 timeout 值 + model.setTimeout(clientResp.getTimeout()); + //设置设备类型 + model.setDevice(clientResp.getClientType()); + userContext.setClientType(clientResp.getClientType()); + //设置客户端id + userContext.setClientId(clientResp.getClientId()); + model.setExtra("ClientId", clientResp.getClientId()); + // 自定义用户上下文处理 + customizeUserContext(userContext, user, clientResp); + + // 登录并缓存用户信息 + StpUtil.login(userContext.getId(), model.setExtraData(BeanUtil + .beanToMap(new UserExtraContext(SpringWebUtils.getRequest())))); + UserContextHolder.setContext(userContext); + + // 后置处理 + String token = StpUtil.getTokenValue(); + postLogin(token, user, clientResp); + return token; + } + + /** + * 登录前置处理 + * + * @param user 用户信息 + * @param clientResp 客户端信息 + */ + private void preLogin(UserDO user, ClientResp clientResp) { + } + + /** + * 自定义用户上下文处理 + * + * @param userContext 用户上下文 + * @param user 用户信息 + * @param clientResp 客户端信息 + */ + protected void customizeUserContext(UserContext userContext, UserDO user, ClientResp clientResp) { + } + + /** + * 登录后置处理 + * + * @param token 登录令牌 + * @param user 用户信息 + * @param clientResp 客户端信息 + */ + protected void postLogin(String token, UserDO user, ClientResp clientResp) { + } +} \ No newline at end of file diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AccountLoginStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AccountLoginStrategy.java new file mode 100644 index 00000000..1b51ae20 --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AccountLoginStrategy.java @@ -0,0 +1,105 @@ +package top.continew.admin.auth.strategy.impl; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; +import top.continew.admin.auth.enums.AuthTypeEnum; +import top.continew.admin.auth.model.req.AccountAuthReq; +import top.continew.admin.auth.model.resp.LoginResp; +import top.continew.admin.auth.service.LoginService; +import top.continew.admin.auth.strategy.AuthStrategy; +import top.continew.admin.common.constant.SysConstants; +import top.continew.admin.common.util.SecureUtils; +import top.continew.admin.system.model.entity.UserDO; +import top.continew.admin.system.model.resp.ClientResp; +import top.continew.admin.system.service.OptionService; +import top.continew.admin.system.service.UserService; +import top.continew.starter.core.util.ExceptionUtils; +import top.continew.starter.core.validation.ValidationUtils; + +/** + * 账号登录策略实现 + * + * @author 莫愁 + * @since 2024/12/22 14:58:32 + */ +@Component +@RequiredArgsConstructor +public class AccountLoginStrategy extends AbstractAuthStrategy implements AuthStrategy { + + private final UserService userService; + private final LoginService loginService; + private final PasswordEncoder passwordEncoder; + private final OptionService optionService; + + /** + * 获取认证类型 + * + * @return 账号认证类型 + */ + @Override + public AuthTypeEnum getAuthType() { + return AuthTypeEnum.ACCOUNT; + } + + /** + * 校验账号登录请求对象 + * + * @param authReq 登录请求参数 + */ + @Override + public void validate(AccountAuthReq authReq) { + //获取验证码开关 + int enableCaptcha = optionService.getValueByCode2Int("LOGIN_CAPTCHA_ENABLED"); + + ValidationUtils.validate(authReq); + if (SysConstants.YES.equals(enableCaptcha)) { + ValidationUtils.throwIfEmpty(authReq.getCaptcha(), "验证码不能为空"); + ValidationUtils.throwIfEmpty(authReq.getUuid(), "验证码标识不能为空"); + } + } + + /** + * 账号登录 + * + * @param authReq 账号登录请求对象 + * @param request HTTP请求对象 + * @return 登录响应 + */ + @Override + public LoginResp login(AccountAuthReq authReq, ClientResp clientResp, HttpServletRequest request) { + this.validate(authReq); + // 解密密码 + String rawPassword = ExceptionUtils.exToNull(() -> + SecureUtils.decryptByRsaPrivateKey(authReq.getPassword())); + ValidationUtils.throwIfBlank(rawPassword, "密码解密失败"); + + // 验证用户名密码 + UserDO user = userService.getByUsername(authReq.getUsername()); + boolean isError = user == null || !passwordEncoder.matches(rawPassword, user.getPassword()); + + // 检查账号锁定状态 + loginService.checkUserLocked(authReq.getUsername(), request, isError); + ValidationUtils.throwIf(isError, "用户名或密码错误"); + + // 检查用户状态 + loginService.checkUserStatus(user); + + // 执行登录 + String token = this.authCertificate(user, clientResp); + return LoginResp.builder().token(token).build(); + } + + /** + * 获取认证信息 + * + * @param user 用户信息 + * @param clientResp 客户端信息 + * @return 认证信息 + */ + @Override + public String authCertificate(UserDO user, ClientResp clientResp) { + return super.authCertificate(user, clientResp); + } +} \ No newline at end of file diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/EmailAuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/EmailAuthStrategy.java new file mode 100644 index 00000000..88fb7b18 --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/EmailAuthStrategy.java @@ -0,0 +1,91 @@ +package top.continew.admin.auth.strategy.impl; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import top.continew.admin.auth.enums.AuthTypeEnum; +import top.continew.admin.auth.model.req.EmailAuthReq; +import top.continew.admin.auth.model.resp.LoginResp; +import top.continew.admin.auth.service.LoginService; +import top.continew.admin.auth.strategy.AuthStrategy; +import top.continew.admin.common.constant.CacheConstants; +import top.continew.admin.system.model.entity.UserDO; +import top.continew.admin.system.model.resp.ClientResp; +import top.continew.admin.system.service.UserService; +import top.continew.starter.cache.redisson.util.RedisUtils; +import top.continew.starter.core.validation.ValidationUtils; + +/** + * 邮箱登录策略实现 + * + * @author 莫愁 + * @since 2024/12/22 14:58:48 + */ +@Component +@RequiredArgsConstructor +public class EmailAuthStrategy extends AbstractAuthStrategy implements AuthStrategy { + + private final UserService userService; + private final LoginService loginService; + + /** + * 获取认证类型 + * + * @return 邮箱认证类型 + */ + @Override + public AuthTypeEnum getAuthType() { + return AuthTypeEnum.EMAIL; + } + + /** + * 校验邮箱登录请求对象 + * + * @param authReq 邮箱登录请求参数 + */ + @Override + public void validate(EmailAuthReq authReq) { + ValidationUtils.validate(authReq); + } + + /** + * 邮箱登录 + * + * @param authReq 邮箱登录请求对象 + * @param request HTTP请求对象 + * @return 登录响应 + */ + @Override + public LoginResp login(EmailAuthReq authReq, ClientResp clientResp, HttpServletRequest request) { + this.validate(authReq); + + String email = authReq.getEmail(); + String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + email; + String captcha = RedisUtils.get(captchaKey); + ValidationUtils.throwIfBlank(captcha, AbstractAuthStrategy.CAPTCHA_EXPIRED); + ValidationUtils.throwIfNotEqualIgnoreCase(authReq.getCaptcha(), captcha, CAPTCHA_ERROR); + RedisUtils.delete(captchaKey); + // 验证邮箱 + UserDO user = userService.getByEmail(authReq.getEmail()); + ValidationUtils.throwIfNull(user, "此邮箱未绑定本系统账号"); + + // 检查用户状态 + loginService.checkUserStatus(user); + + // 执行登录 + String token = this.authCertificate(user, clientResp); + return LoginResp.builder().token(token).build(); + } + + /** + * 获取登录凭证 + * + * @param user 用户信息 + * @param clientResp 客户端信息 + * @return token 认证信息 + */ + @Override + public String authCertificate(UserDO user, ClientResp clientResp) { + return super.authCertificate(user, clientResp); + } +} \ No newline at end of file diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/PhoneAuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/PhoneAuthStrategy.java new file mode 100644 index 00000000..b8ce8aad --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/PhoneAuthStrategy.java @@ -0,0 +1,93 @@ +package top.continew.admin.auth.strategy.impl; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import top.continew.admin.auth.enums.AuthTypeEnum; +import top.continew.admin.auth.model.req.PhoneAuthReq; +import top.continew.admin.auth.model.resp.LoginResp; +import top.continew.admin.auth.service.LoginService; +import top.continew.admin.auth.strategy.AuthStrategy; +import top.continew.admin.common.constant.CacheConstants; +import top.continew.admin.system.model.entity.UserDO; +import top.continew.admin.system.model.resp.ClientResp; +import top.continew.admin.system.service.UserService; +import top.continew.starter.cache.redisson.util.RedisUtils; +import top.continew.starter.core.validation.ValidationUtils; + +/** + * 手机号登录策略实现 + * + * @author 莫愁 + * @since 2024/12/22 14:59:11 + */ +@Component +@RequiredArgsConstructor +public class PhoneAuthStrategy extends AbstractAuthStrategy implements AuthStrategy { + + private final UserService userService; + private final LoginService loginService; + + /** + * 获取认证类型 + * + * @return 手机号认证类型 + */ + @Override + public AuthTypeEnum getAuthType() { + return AuthTypeEnum.PHONE; + } + + /** + * 校验手机号登录请求对象 + * + * @param authReq 手机号登录请求参数 + */ + @Override + public void validate(PhoneAuthReq authReq) { + ValidationUtils.validate(authReq); + } + + /** + * 手机号登录 + * + * @param authReq 手机号登录请求对象 + * @param request HTTP请求对象 + * @return 登录响应 + */ + @Override + public LoginResp login(PhoneAuthReq authReq, ClientResp clientResp, HttpServletRequest request) { + //校验参数 + this.validate(authReq); + + String phone = authReq.getPhone(); + String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + phone; + String captcha = RedisUtils.get(captchaKey); + ValidationUtils.throwIfBlank(captcha, AbstractAuthStrategy.CAPTCHA_EXPIRED); + ValidationUtils.throwIfNotEqualIgnoreCase(authReq.getCaptcha(), captcha, AbstractAuthStrategy.CAPTCHA_ERROR); + RedisUtils.delete(captchaKey); + + // 验证手机号 + UserDO user = userService.getByPhone(authReq.getPhone()); + ValidationUtils.throwIfNull(user, "此手机号未绑定本系统账号"); + + // 检查用户状态 + loginService.checkUserStatus(user); + + // 执行登录 + String token = this.authCertificate(user, clientResp); + return LoginResp.builder().token(token).build(); + } + + /** + * 获取登录凭证 + * + * @param user 用户信息 + * @param clientResp 客户端信息 + * @return token 认证信息 + */ + @Override + public String authCertificate(UserDO user, ClientResp clientResp) { + return super.authCertificate(user, clientResp); + } +} \ No newline at end of file diff --git a/continew-module-system/src/main/java/top/continew/admin/system/mapper/ClientMapper.java b/continew-module-system/src/main/java/top/continew/admin/system/mapper/ClientMapper.java new file mode 100644 index 00000000..b7f1d199 --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/system/mapper/ClientMapper.java @@ -0,0 +1,12 @@ +package top.continew.admin.system.mapper; + +import top.continew.starter.data.mp.base.BaseMapper; +import top.continew.admin.system.model.entity.ClientDO; + +/** +* 客户端管理 Mapper +* +* @author MoChou +* @since 2024/12/03 16:04 +*/ +public interface ClientMapper extends BaseMapper {} \ No newline at end of file diff --git a/continew-module-system/src/main/java/top/continew/admin/system/model/entity/ClientDO.java b/continew-module-system/src/main/java/top/continew/admin/system/model/entity/ClientDO.java new file mode 100644 index 00000000..db9b1917 --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/system/model/entity/ClientDO.java @@ -0,0 +1,66 @@ +package top.continew.admin.system.model.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.Data; +import top.continew.admin.common.enums.DisEnableStatusEnum; +import top.continew.starter.extension.crud.model.entity.BaseDO; + +import java.io.Serial; +import java.util.List; + +/** + * 客户端管理实体 + * + * @author MoChou + * @since 2024/12/03 16:04 + */ +@Data +@TableName(value = "sys_client", autoResultMap = true) +public class ClientDO extends BaseDO { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 客户端ID + */ + private String clientId; + + /** + * 客户端Key + */ + private String clientKey; + + /** + * 客户端秘钥 + */ + private String clientSecret; + + /** + * 登录类型 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List authType; + + /** + * 客户端类型 + */ + private String clientType; + + /** + * Token最低活跃频率(-1为不限制) + */ + private Integer activeTimeout; + + /** + * Token有效期(默认30天,单位:秒) + */ + private Integer timeout; + + /** + * 状态(1:启用;2:禁用) + */ + private DisEnableStatusEnum status; +} \ No newline at end of file diff --git a/continew-module-system/src/main/java/top/continew/admin/system/model/query/ClientQuery.java b/continew-module-system/src/main/java/top/continew/admin/system/model/query/ClientQuery.java new file mode 100644 index 00000000..8b1d777a --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/system/model/query/ClientQuery.java @@ -0,0 +1,59 @@ +package top.continew.admin.system.model.query; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import top.continew.admin.common.enums.DisEnableStatusEnum; +import top.continew.starter.data.core.annotation.Query; +import top.continew.starter.data.core.enums.QueryType; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +/** + * 客户端管理查询条件 + * + * @author MoChou + * @since 2024/12/03 16:04 + */ +@Data +@Schema(description = "客户端管理查询条件") +public class ClientQuery implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 客户端Key + */ + @Schema(description = "客户端Key") + @Query(type = QueryType.EQ) + private String clientKey; + + /** + * 客户端秘钥 + */ + @Schema(description = "客户端秘钥") + @Query(type = QueryType.EQ) + private String clientSecret; + + /** + * 登录类型 + */ + @Schema(description = "登录类型") + @Query(type = QueryType.IN) + private List authType; + /** + * 客户端类型 + */ + @Schema(description = "客户端类型") + @Query(type = QueryType.EQ) + private String clientType; + + /** + * 状态(1:启用;2:禁用) + */ + @Schema(description = "状态") + @Query(type = QueryType.EQ) + private DisEnableStatusEnum status; +} \ No newline at end of file diff --git a/continew-module-system/src/main/java/top/continew/admin/system/model/req/ClientReq.java b/continew-module-system/src/main/java/top/continew/admin/system/model/req/ClientReq.java new file mode 100644 index 00000000..d37f6fe8 --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/system/model/req/ClientReq.java @@ -0,0 +1,81 @@ +package top.continew.admin.system.model.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import top.continew.admin.common.enums.DisEnableStatusEnum; +import top.continew.starter.extension.crud.model.req.BaseReq; + +import java.io.Serial; +import java.util.List; + +/** + * 创建或修改客户端管理参数 + * + * @author MoChou + * @since 2024/12/03 16:04 + */ +@Data +@Schema(description = "创建或修改客户端管理参数") +public class ClientReq extends BaseReq { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 客户端ID + */ + @Schema(description = "客户端ID") + private String clientId; + + /** + * 客户端Key + */ + @Schema(description = "客户端Key") + @NotBlank(message = "客户端Key不能为空") + @Length(max = 32, message = "客户端Key长度不能超过 {max} 个字符") + private String clientKey; + + /** + * 客户端秘钥 + */ + @Schema(description = "客户端秘钥") + @NotBlank(message = "客户端秘钥不能为空") + @Length(max = 255, message = "客户端秘钥长度不能超过 {max} 个字符") + private String clientSecret; + + /** + * 登录类型 + */ + @Schema(description = "登录类型") + @NotNull(message = "登录类型不能为空") + private List authType; + /** + * 客户端类型 + */ + @Schema(description = "客户端类型") + @NotBlank(message = "客户端类型不能为空") + @Length(max = 32, message = "客户端类型长度不能超过 {max} 个字符") + private String clientType; + + /** + * Token最低活跃频率(-1为不限制) + */ + @Schema(description = "Token最低活跃频率(-1为不限制)") + private Integer activeTimeout; + + /** + * Token有效期(默认30天,单位:秒) + */ + @Schema(description = "Token有效期(默认30天,单位:秒)") + private Integer timeout; + + /** + * 状态(1:启用;2:禁用) + */ + @Schema(description = "状态(1:启用;2:禁用)") + @NotNull(message = "状态(1:启用;2:禁用)不能为空") + private DisEnableStatusEnum status; +} \ No newline at end of file diff --git a/continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientDetailResp.java b/continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientDetailResp.java new file mode 100644 index 00000000..611c5fd9 --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientDetailResp.java @@ -0,0 +1,82 @@ +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 lombok.Data; +import top.continew.admin.common.enums.DisEnableStatusEnum; +import top.continew.starter.extension.crud.model.resp.BaseDetailResp; + +import java.io.Serial; +import java.util.List; + +/** + * 客户端管理详情信息 + * + * @author MoChou + * @since 2024/12/03 16:04 + */ +@Data +@ExcelIgnoreUnannotated +@Schema(description = "客户端管理详情信息") +public class ClientDetailResp extends BaseDetailResp { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 客户端ID + */ + @Schema(description = "客户端ID") + @ExcelProperty(value = "客户端ID") + private String clientId; + + /** + * 客户端Key + */ + @Schema(description = "客户端Key") + @ExcelProperty(value = "客户端Key") + private String clientKey; + + /** + * 客户端秘钥 + */ + @Schema(description = "客户端秘钥") + @ExcelProperty(value = "客户端秘钥") + private String clientSecret; + + /** + * 登录类型 + */ + @Schema(description = "登录类型") + @ExcelProperty(value = "登录类型") + private List authType; + + /** + * 客户端类型 + */ + @Schema(description = "客户端类型") + @ExcelProperty(value = "客户端类型") + private String clientType; + + /** + * Token最低活跃频率(-1为不限制) + */ + @Schema(description = "Token最低活跃频率(-1为不限制)") + @ExcelProperty(value = "Token最低活跃频率(-1为不限制)") + private Integer activeTimeout; + + /** + * Token有效期(默认30天,单位:秒) + */ + @Schema(description = "Token有效期(默认30天,单位:秒)") + @ExcelProperty(value = "Token有效期(默认30天,单位:秒)") + private Integer timeout; + + /** + * 状态 + */ + @Schema(description = "状态") + @ExcelProperty(value = "状态") + private DisEnableStatusEnum status; +} \ No newline at end of file diff --git a/continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientResp.java b/continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientResp.java new file mode 100644 index 00000000..dcb81879 --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientResp.java @@ -0,0 +1,71 @@ +package top.continew.admin.system.model.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import top.continew.admin.common.enums.DisEnableStatusEnum; +import top.continew.starter.extension.crud.model.resp.BaseResp; + +import java.io.Serial; +import java.util.List; + +/** + * 客户端管理信息 + * + * @author MoChou + * @since 2024/12/03 16:04 + */ +@Data +@Schema(description = "客户端管理信息") +public class ClientResp extends BaseResp { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 客户端ID + */ + @Schema(description = "客户端ID") + private String clientId; + + /** + * 客户端Key + */ + @Schema(description = "客户端Key") + private String clientKey; + + /** + * 客户端秘钥 + */ + @Schema(description = "客户端秘钥") + private String clientSecret; + + /** + * 认证类型 + */ + @Schema(description = "认证类型") + private List authType; + + /** + * 客户端类型 + */ + @Schema(description = "客户端类型") + private String clientType; + + /** + * Token最低活跃频率(-1为不限制) + */ + @Schema(description = "Token最低活跃频率(-1为不限制)") + private Integer activeTimeout; + + /** + * Token有效期(默认30天,单位:秒) + */ + @Schema(description = "Token有效期(默认30天,单位:秒)") + private Integer timeout; + + /** + * 状态(1:启用;2:禁用) + */ + @Schema(description = "状态") + private DisEnableStatusEnum status; +} \ No newline at end of file diff --git a/continew-module-system/src/main/java/top/continew/admin/system/service/ClientService.java b/continew-module-system/src/main/java/top/continew/admin/system/service/ClientService.java new file mode 100644 index 00000000..840a64ca --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/system/service/ClientService.java @@ -0,0 +1,19 @@ +package top.continew.admin.system.service; + +import top.continew.admin.system.model.query.ClientQuery; +import top.continew.admin.system.model.req.ClientReq; +import top.continew.admin.system.model.resp.ClientDetailResp; +import top.continew.admin.system.model.resp.ClientResp; +import top.continew.starter.extension.crud.service.BaseService; + +/** + * 客户端管理业务接口 + * + * @author MoChou + * @since 2024/12/03 16:04 + */ +public interface ClientService extends BaseService { + + ClientResp getClientByClientId(String clientId); + +} \ No newline at end of file diff --git a/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java b/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java new file mode 100644 index 00000000..a8c35dcc --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java @@ -0,0 +1,37 @@ +package top.continew.admin.system.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import top.continew.admin.system.mapper.ClientMapper; +import top.continew.admin.system.model.entity.ClientDO; +import top.continew.admin.system.model.query.ClientQuery; +import top.continew.admin.system.model.req.ClientReq; +import top.continew.admin.system.model.resp.ClientDetailResp; +import top.continew.admin.system.model.resp.ClientResp; +import top.continew.admin.system.service.ClientService; +import top.continew.starter.extension.crud.service.BaseServiceImpl; + +import java.util.UUID; + +/** + * 客户端管理业务实现 + * + * @author MoChou + * @since 2024/12/03 16:04 + */ +@Service +@RequiredArgsConstructor +public class ClientServiceImpl extends BaseServiceImpl implements ClientService { + @Override + protected void beforeAdd(ClientReq req) { + req.setClientId(UUID.randomUUID().toString()); + } + + @Override + public ClientResp getClientByClientId(String clientId) { + ClientDO clientDO = this.baseMapper.selectOne(new LambdaQueryWrapper().eq(ClientDO::getClientId, clientId)); + return BeanUtil.copyProperties(clientDO, ClientResp.class); + } +} \ No newline at end of file diff --git a/continew-webapi/src/main/java/top/continew/admin/config/log/LogDaoLocalImpl.java b/continew-webapi/src/main/java/top/continew/admin/config/log/LogDaoLocalImpl.java index 1788ead1..04ccd7e9 100644 --- a/continew-webapi/src/main/java/top/continew/admin/config/log/LogDaoLocalImpl.java +++ b/continew-webapi/src/main/java/top/continew/admin/config/log/LogDaoLocalImpl.java @@ -28,7 +28,8 @@ import cn.hutool.json.JSONUtil; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpHeaders; import org.springframework.scheduling.annotation.Async; -import top.continew.admin.auth.model.req.AccountLoginReq; +import top.continew.admin.auth.enums.AuthTypeEnum; +import top.continew.admin.auth.model.req.AccountAuthReq; import top.continew.admin.common.constant.SysConstants; import top.continew.admin.system.enums.LogStatusEnum; import top.continew.admin.system.mapper.LogMapper; @@ -75,8 +76,8 @@ public class LogDaoLocalImpl implements LogDao { // 设置基本信息 logDO.setDescription(logRecord.getDescription()); logDO.setModule(StrUtils.blankToDefault(logRecord.getModule(), null, m -> m - .replace("API", StringConstants.EMPTY) - .trim())); + .replace("API", StringConstants.EMPTY) + .trim())); logDO.setTimeTaken(logRecord.getTimeTaken().toMillis()); logDO.setCreateTime(LocalDateTime.ofInstant(logRecord.getTimestamp(), ZoneId.systemDefault())); // 设置操作人 @@ -145,21 +146,20 @@ public class LogDaoLocalImpl implements LogDao { // 解析登录接口信息 if (requestUri.startsWith(SysConstants.LOGIN_URI) && LogStatusEnum.SUCCESS.equals(logDO.getStatus())) { String requestBody = logRequest.getBody(); - AccountLoginReq loginReq = JSONUtil.toBean(requestBody, AccountLoginReq.class); - logDO.setCreateUser(ExceptionUtils.exToNull(() -> userService.getByUsername(loginReq.getUsername()) - .getId())); + //账号登录设置操作人 + if (requestBody.contains(AuthTypeEnum.ACCOUNT.getValue())){ + AccountAuthReq loginReq = JSONUtil.toBean(requestBody, AccountAuthReq.class); + logDO.setCreateUser(ExceptionUtils.exToNull(() -> userService.getByUsername(loginReq.getUsername()).getId())); + } return; } // 解析 Token 信息 Map requestHeaders = logRequest.getHeaders(); String headerName = HttpHeaders.AUTHORIZATION; - boolean isContainsAuthHeader = CollUtil.containsAny(requestHeaders.keySet(), Set.of(headerName, headerName - .toLowerCase())); + boolean isContainsAuthHeader = CollUtil.containsAny(requestHeaders.keySet(), Set.of(headerName, headerName.toLowerCase())); if (MapUtil.isNotEmpty(requestHeaders) && isContainsAuthHeader) { - String authorization = requestHeaders.getOrDefault(headerName, requestHeaders.get(headerName - .toLowerCase())); - String token = authorization.replace(SaManager.getConfig() - .getTokenPrefix() + StringConstants.SPACE, StringConstants.EMPTY); + String authorization = requestHeaders.getOrDefault(headerName, requestHeaders.get(headerName.toLowerCase())); + String token = authorization.replace(SaManager.getConfig().getTokenPrefix() + StringConstants.SPACE, StringConstants.EMPTY); logDO.setCreateUser(Convert.toLong(StpUtil.getLoginIdByToken(token))); } } diff --git a/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java b/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java index ce12d9f1..5cb908f2 100644 --- a/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java +++ b/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java @@ -1,49 +1,31 @@ -/* - * 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 cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; 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 jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import top.continew.admin.auth.model.req.AccountLoginReq; -import top.continew.admin.auth.model.req.EmailLoginReq; -import top.continew.admin.auth.model.req.PhoneLoginReq; +import top.continew.admin.auth.config.auth.AuthStrategyContext; +import top.continew.admin.auth.model.req.AuthReq; import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.auth.model.resp.RouteResp; import top.continew.admin.auth.model.resp.UserInfoResp; import top.continew.admin.auth.service.LoginService; -import top.continew.admin.common.constant.CacheConstants; -import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.context.UserContext; import top.continew.admin.common.context.UserContextHolder; -import top.continew.admin.common.util.SecureUtils; +import top.continew.admin.system.model.resp.ClientResp; import top.continew.admin.system.model.resp.user.UserDetailResp; -import top.continew.admin.system.service.OptionService; +import top.continew.admin.system.service.ClientService; import top.continew.admin.system.service.UserService; -import top.continew.starter.cache.redisson.util.RedisUtils; -import top.continew.starter.core.util.ExceptionUtils; +import top.continew.starter.core.exception.BusinessException; import top.continew.starter.core.validation.ValidationUtils; import top.continew.starter.log.core.annotation.Log; @@ -55,67 +37,45 @@ import java.util.List; * @author Charles7c * @since 2022/12/21 20:37 */ +@Slf4j @Log(module = "登录") @Tag(name = "认证 API") @RestController @RequiredArgsConstructor @RequestMapping("/auth") public class AuthController { + private final ClientService clientService; - private static final String CAPTCHA_EXPIRED = "验证码已失效"; - private static final String CAPTCHA_ERROR = "验证码错误"; - private final OptionService optionService; - private final LoginService loginService; private final UserService userService; - @SaIgnore - @Operation(summary = "账号登录", description = "根据账号和密码进行登录认证") - @PostMapping("/account") - public LoginResp accountLogin(@Validated @RequestBody AccountLoginReq loginReq, HttpServletRequest request) { - // 校验验证码 - int loginCaptchaEnabled = optionService.getValueByCode2Int("LOGIN_CAPTCHA_ENABLED"); - if (SysConstants.YES.equals(loginCaptchaEnabled)) { - ValidationUtils.throwIfBlank(loginReq.getCaptcha(), "验证码不能为空"); - ValidationUtils.throwIfBlank(loginReq.getUuid(), "验证码标识不能为空"); - String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + loginReq.getUuid(); - String captcha = RedisUtils.get(captchaKey); - ValidationUtils.throwIfBlank(captcha, CAPTCHA_EXPIRED); - RedisUtils.delete(captchaKey); - ValidationUtils.throwIfNotEqualIgnoreCase(loginReq.getCaptcha(), captcha, CAPTCHA_ERROR); - } - // 用户登录 - String rawPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(loginReq.getPassword())); - ValidationUtils.throwIfBlank(rawPassword, "密码解密失败"); - String token = loginService.accountLogin(loginReq.getUsername(), rawPassword, request); - return LoginResp.builder().token(token).build(); - } + private final LoginService loginService; + + private final AuthStrategyContext authStrategyContext; - @SaIgnore - @Operation(summary = "手机号登录", description = "根据手机号和验证码进行登录认证") - @PostMapping("/phone") - public LoginResp phoneLogin(@Validated @RequestBody PhoneLoginReq loginReq) { - String phone = loginReq.getPhone(); - String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + phone; - String captcha = RedisUtils.get(captchaKey); - ValidationUtils.throwIfBlank(captcha, CAPTCHA_EXPIRED); - ValidationUtils.throwIfNotEqualIgnoreCase(loginReq.getCaptcha(), captcha, CAPTCHA_ERROR); - RedisUtils.delete(captchaKey); - String token = loginService.phoneLogin(phone); - return LoginResp.builder().token(token).build(); - } @SaIgnore - @Operation(summary = "邮箱登录", description = "根据邮箱和验证码进行登录认证") - @PostMapping("/email") - public LoginResp emailLogin(@Validated @RequestBody EmailLoginReq loginReq) { - String email = loginReq.getEmail(); - String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + email; - String captcha = RedisUtils.get(captchaKey); - ValidationUtils.throwIfBlank(captcha, CAPTCHA_EXPIRED); - ValidationUtils.throwIfNotEqualIgnoreCase(loginReq.getCaptcha(), captcha, CAPTCHA_ERROR); - RedisUtils.delete(captchaKey); - String token = loginService.emailLogin(email); - return LoginResp.builder().token(token).build(); + @Operation(summary = "登录", description = "统一登录入口") + @PostMapping("/login") + public LoginResp login(@Validated @RequestBody AuthReq loginReq, HttpServletRequest request) { + // 客户端标识 + String clientId = loginReq.getClientId(); + // 认证类型 + String authType = loginReq.getAuthType(); + ValidationUtils.throwIfBlank(clientId, "Client ID不能为空"); + + // 获取并验证客户端信息 + ClientResp clientResp = clientService.getClientByClientId(clientId); + ValidationUtils.throwIfNull(clientResp, "客户端信息不存在,请检查客户端标识是否正确!"); + + // 验证认证类型 + ValidationUtils.throwIf(!clientResp.getAuthType().contains(authType), StrUtil.format("暂未授权此类型:{}", authType)); + try { + // 执行登录策略 + return (LoginResp) authStrategyContext.getStrategy(authType).login(loginReq, clientResp, request); + } catch (Exception e) { + log.error("登录失败: {}", e.getMessage(), e); + throw new BusinessException("登录失败: " + e.getMessage()); + } } @Operation(summary = "用户退出", description = "注销用户的当前登录") @@ -146,4 +106,4 @@ public class AuthController { public List listRoute() { return loginService.buildRouteTree(UserContextHolder.getUserId()); } -} \ No newline at end of file +} diff --git a/continew-webapi/src/main/java/top/continew/admin/controller/system/ClientController.java b/continew-webapi/src/main/java/top/continew/admin/controller/system/ClientController.java new file mode 100644 index 00000000..27bb63f8 --- /dev/null +++ b/continew-webapi/src/main/java/top/continew/admin/controller/system/ClientController.java @@ -0,0 +1,24 @@ +package top.continew.admin.controller.system; + +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.RestController; +import top.continew.admin.common.base.BaseController; +import top.continew.admin.system.model.query.ClientQuery; +import top.continew.admin.system.model.req.ClientReq; +import top.continew.admin.system.model.resp.ClientDetailResp; +import top.continew.admin.system.model.resp.ClientResp; +import top.continew.admin.system.service.ClientService; +import top.continew.starter.extension.crud.annotation.CrudRequestMapping; +import top.continew.starter.extension.crud.enums.Api; + +/** + * 客户端管理管理 API + * + * @author MoChou + * @since 2024/12/03 16:04 + */ +@Tag(name = "客户端管理管理 API") +@RestController +@CrudRequestMapping(value = "/system/client", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT}) +public class ClientController extends BaseController { +} \ No newline at end of file -- Gitee From 35ccaa96aefb8c258704e3a4ff7275f9c5e54b3f Mon Sep 17 00:00:00 2001 From: KAI <1373639299@qq.com> Date: Wed, 25 Dec 2024 10:34:34 +0800 Subject: [PATCH 03/12] =?UTF-8?q?style:=20=E4=BB=A3=E7=A0=81=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/{auth => }/AuthStrategyContext.java | 4 ++-- .../top/continew/admin/auth/model/req/AuthReq.java | 4 ++-- .../continew/admin/auth/strategy/AuthStrategy.java | 2 +- .../auth/strategy/impl/AbstractAuthStrategy.java | 14 +++++++------- .../auth/strategy/impl/AccountLoginStrategy.java | 4 ++-- .../auth/strategy/impl/EmailAuthStrategy.java | 2 +- .../auth/strategy/impl/PhoneAuthStrategy.java | 2 +- .../admin/controller/auth/AuthController.java | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) rename continew-module-system/src/main/java/top/continew/admin/auth/config/{auth => }/AuthStrategyContext.java (94%) diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/config/auth/AuthStrategyContext.java b/continew-module-system/src/main/java/top/continew/admin/auth/config/AuthStrategyContext.java similarity index 94% rename from continew-module-system/src/main/java/top/continew/admin/auth/config/auth/AuthStrategyContext.java rename to continew-module-system/src/main/java/top/continew/admin/auth/config/AuthStrategyContext.java index f42338bd..a8cfb21c 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/config/auth/AuthStrategyContext.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/config/AuthStrategyContext.java @@ -1,4 +1,4 @@ -package top.continew.admin.auth.config.auth; +package top.continew.admin.auth.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -12,7 +12,7 @@ import java.util.Map; /** * 登录类型策略上文 * - * @author 莫愁 + * @author KAI * @since 2024/12/20 15:16:55 */ @Component diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java index b5a72a75..af80a79b 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java @@ -9,7 +9,7 @@ import lombok.Data; /** * 登录参数基础类 * - * @author 莫愁 + * @author KAI * @since 2024/12/22 15:16:39 */ @Data @@ -21,7 +21,7 @@ import lombok.Data; }) public abstract class AuthReq { - @Schema(description = "ClientId 客户端标识") + @Schema(description = "clientId 客户端标识") @NotBlank(message = "客户端标识不能为空") private String clientId; diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/AuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/AuthStrategy.java index 39ecef71..41d86ba5 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/AuthStrategy.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/AuthStrategy.java @@ -8,7 +8,7 @@ import top.continew.admin.system.model.resp.ClientResp; /** * 登录策略接口 * - * @author 莫愁 + * @author KAI * @since 2024/12/22 14:52:23 */ public interface AuthStrategy { diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AbstractAuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AbstractAuthStrategy.java index 10504324..dddd8f46 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AbstractAuthStrategy.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AbstractAuthStrategy.java @@ -26,7 +26,7 @@ import static top.continew.admin.system.enums.PasswordPolicyEnum.PASSWORD_EXPIRA /** * 登录策略 * - * @author 莫愁 + * @author KAI * @since 2024/12/22 14:52:32 */ @Component @@ -41,7 +41,7 @@ public abstract class AbstractAuthStrategy { public static final String CAPTCHA_EXPIRED = "验证码已失效"; public static final String CAPTCHA_ERROR = "验证码错误"; - + public static final String CLIENT_ID = "clientId"; /** * 获取登录凭证 * @@ -66,16 +66,16 @@ public abstract class AbstractAuthStrategy { BeanUtil.copyProperties(user, userContext); SaLoginModel model = new SaLoginModel(); - //设置登录 token 最低活跃频率 如未指定,则使用全局配置的 activeTimeout 值 + // 设置登录 token 最低活跃频率 如未指定,则使用全局配置的 activeTimeout 值 model.setActiveTimeout(clientResp.getActiveTimeout()); - //设置登录 token 有效期,单位:秒 (如未指定,自动取全局配置的 timeout 值 + // 设置登录 token 有效期,单位:秒 (如未指定,自动取全局配置的 timeout 值 model.setTimeout(clientResp.getTimeout()); - //设置设备类型 + // 设置设备类型 model.setDevice(clientResp.getClientType()); userContext.setClientType(clientResp.getClientType()); - //设置客户端id + // 设置客户端id userContext.setClientId(clientResp.getClientId()); - model.setExtra("ClientId", clientResp.getClientId()); + model.setExtra(CLIENT_ID, clientResp.getClientId()); // 自定义用户上下文处理 customizeUserContext(userContext, user, clientResp); diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AccountLoginStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AccountLoginStrategy.java index 1b51ae20..c28d2a40 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AccountLoginStrategy.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AccountLoginStrategy.java @@ -21,7 +21,7 @@ import top.continew.starter.core.validation.ValidationUtils; /** * 账号登录策略实现 * - * @author 莫愁 + * @author KAI * @since 2024/12/22 14:58:32 */ @Component @@ -50,7 +50,7 @@ public class AccountLoginStrategy extends AbstractAuthStrategy implements AuthSt */ @Override public void validate(AccountAuthReq authReq) { - //获取验证码开关 + // 获取验证码开关 int enableCaptcha = optionService.getValueByCode2Int("LOGIN_CAPTCHA_ENABLED"); ValidationUtils.validate(authReq); diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/EmailAuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/EmailAuthStrategy.java index 88fb7b18..d05eccd2 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/EmailAuthStrategy.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/EmailAuthStrategy.java @@ -18,7 +18,7 @@ import top.continew.starter.core.validation.ValidationUtils; /** * 邮箱登录策略实现 * - * @author 莫愁 + * @author KAI * @since 2024/12/22 14:58:48 */ @Component diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/PhoneAuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/PhoneAuthStrategy.java index b8ce8aad..c5263cfa 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/PhoneAuthStrategy.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/PhoneAuthStrategy.java @@ -18,7 +18,7 @@ import top.continew.starter.core.validation.ValidationUtils; /** * 手机号登录策略实现 * - * @author 莫愁 + * @author KAI * @since 2024/12/22 14:59:11 */ @Component diff --git a/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java b/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java index 5cb908f2..6b40bfbf 100644 --- a/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java +++ b/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java @@ -13,7 +13,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import top.continew.admin.auth.config.auth.AuthStrategyContext; +import top.continew.admin.auth.config.AuthStrategyContext; import top.continew.admin.auth.model.req.AuthReq; import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.auth.model.resp.RouteResp; -- Gitee From 34095768c0e0b008d99178cf4c64fec197c5d47e Mon Sep 17 00:00:00 2001 From: KAI <1373639299@qq.com> Date: Wed, 25 Dec 2024 10:39:41 +0800 Subject: [PATCH 04/12] =?UTF-8?q?chore:=20md5=E5=8A=A0=E5=AF=86=E7=94=9F?= =?UTF-8?q?=E6=88=90ClientId?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../continew/admin/system/service/impl/ClientServiceImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java b/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java index a8c35dcc..c32098de 100644 --- a/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java +++ b/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java @@ -1,6 +1,7 @@ package top.continew.admin.system.service.impl; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.crypto.digest.DigestUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -26,7 +27,8 @@ import java.util.UUID; public class ClientServiceImpl extends BaseServiceImpl implements ClientService { @Override protected void beforeAdd(ClientReq req) { - req.setClientId(UUID.randomUUID().toString()); + String clientId = DigestUtil.md5Hex(req.getClientKey(), req.getClientSecret()); + req.setClientId(clientId); } @Override -- Gitee From 7581092c45b0e1e823f8d34b38d32169e962c9ab Mon Sep 17 00:00:00 2001 From: KAI <1373639299@qq.com> Date: Wed, 25 Dec 2024 10:50:39 +0800 Subject: [PATCH 05/12] =?UTF-8?q?chore:=20=E5=AE=A2=E6=88=B7=E7=AB=AF?= =?UTF-8?q?=E7=AE=A1=E7=90=86->=E5=A2=9E=E5=8A=A0=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E5=89=8D=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/ClientServiceImpl.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java b/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java index c32098de..970e3c79 100644 --- a/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java +++ b/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java @@ -1,10 +1,12 @@ package top.continew.admin.system.service.impl; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import top.continew.admin.auth.enums.AuthTypeEnum; import top.continew.admin.system.mapper.ClientMapper; import top.continew.admin.system.model.entity.ClientDO; import top.continew.admin.system.model.query.ClientQuery; @@ -12,8 +14,10 @@ import top.continew.admin.system.model.req.ClientReq; import top.continew.admin.system.model.resp.ClientDetailResp; import top.continew.admin.system.model.resp.ClientResp; import top.continew.admin.system.service.ClientService; +import top.continew.starter.core.validation.ValidationUtils; import top.continew.starter.extension.crud.service.BaseServiceImpl; +import java.util.List; import java.util.UUID; /** @@ -31,9 +35,22 @@ public class ClientServiceImpl extends BaseServiceImpl().eq(ClientDO::getClientId, clientId)); + ClientDO clientDO = baseMapper.selectOne(new LambdaQueryWrapper().eq(ClientDO::getClientId, clientId)); return BeanUtil.copyProperties(clientDO, ClientResp.class); } + + @Override + protected void beforeDelete(List ids) { + // 查询如果删除客户端记录以后是否还存在账号认证的方式,不存在则不允许删除 + List clientDOS = baseMapper.selectList(new LambdaQueryWrapper().notIn(ClientDO::getId, ids).like(ClientDO::getAuthType, AuthTypeEnum.ACCOUNT.getValue())); + ValidationUtils.throwIfEmpty(clientDOS, StrUtil.format("请至少保留一条{}认证的方式",AuthTypeEnum.ACCOUNT.getDescription())); + super.beforeDelete(ids); + } } \ No newline at end of file -- Gitee From c75a40303d80651024d3843693b468d35cb15fed Mon Sep 17 00:00:00 2001 From: KAI <1373639299@qq.com> Date: Wed, 25 Dec 2024 11:09:55 +0800 Subject: [PATCH 06/12] =?UTF-8?q?style:=20=E4=BB=A3=E7=A0=81=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8F=98=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/config/AuthStrategyContext.java | 18 ++++++++++- .../admin/auth/enums/AuthTypeEnum.java | 17 ++++++++++- .../admin/auth/model/req/AccountAuthReq.java | 2 -- .../admin/auth/model/req/AuthReq.java | 28 ++++++++++++----- .../admin/auth/service/LoginService.java | 4 +-- .../auth/service/impl/LoginServiceImpl.java | 12 ++++---- .../admin/auth/strategy/AuthStrategy.java | 16 ++++++++++ .../strategy/impl/AbstractAuthStrategy.java | 30 ++++++++++++++----- .../strategy/impl/AccountLoginStrategy.java | 19 ++++++++++-- .../auth/strategy/impl/EmailAuthStrategy.java | 18 ++++++++++- .../auth/strategy/impl/PhoneAuthStrategy.java | 16 ++++++++++ .../admin/system/mapper/ClientMapper.java | 26 ++++++++++++---- .../admin/system/model/entity/ClientDO.java | 16 ++++++++++ .../admin/system/model/query/ClientQuery.java | 16 ++++++++++ .../admin/system/model/req/ClientReq.java | 16 ++++++++++ .../system/model/resp/ClientDetailResp.java | 16 ++++++++++ .../admin/system/model/resp/ClientResp.java | 16 ++++++++++ .../admin/system/service/ClientService.java | 16 ++++++++++ .../service/impl/ClientServiceImpl.java | 27 ++++++++++++++--- .../admin/config/log/LogDaoLocalImpl.java | 18 ++++++----- .../admin/controller/auth/AuthController.java | 24 +++++++++++---- .../controller/system/ClientController.java | 16 ++++++++++ 22 files changed, 336 insertions(+), 51 deletions(-) diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/config/AuthStrategyContext.java b/continew-module-system/src/main/java/top/continew/admin/auth/config/AuthStrategyContext.java index a8cfb21c..6bfbc754 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/config/AuthStrategyContext.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/config/AuthStrategyContext.java @@ -1,3 +1,19 @@ +/* + * 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.auth.config; import org.springframework.beans.factory.annotation.Autowired; @@ -32,6 +48,6 @@ public class AuthStrategyContext { if (strategy == null) { throw new IllegalArgumentException("No strategy found for type: " + type); } - return (AuthStrategy) strategy; + return (AuthStrategy)strategy; } } diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java b/continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java index 8c9a482d..104b9d5c 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java @@ -1,3 +1,19 @@ +/* + * 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.auth.enums; import lombok.Getter; @@ -35,7 +51,6 @@ public enum AuthTypeEnum implements BaseEnum { */ SOCIAL_AUTH("SocialAuth", "第三方授权", UiConstants.COLOR_DEFAULT); - private final String value; private final String description; private final String color; diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AccountAuthReq.java b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AccountAuthReq.java index 1d97b550..d56d1414 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AccountAuthReq.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AccountAuthReq.java @@ -19,8 +19,6 @@ package top.continew.admin.auth.model.req; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; -import top.continew.admin.common.constant.SysConstants; -import top.continew.starter.core.validation.ValidationUtils; import java.io.Serial; import java.io.Serializable; diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java index af80a79b..da023d30 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java @@ -1,3 +1,19 @@ +/* + * 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.auth.model.req; import com.fasterxml.jackson.annotation.JsonSubTypes; @@ -14,15 +30,13 @@ import lombok.Data; */ @Data @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "authType", visible = true) -@JsonSubTypes({ - @JsonSubTypes.Type(value = AccountAuthReq.class, name = "account"), - @JsonSubTypes.Type(value = EmailAuthReq.class, name = "email"), - @JsonSubTypes.Type(value = PhoneAuthReq.class, name = "phone") -}) +@JsonSubTypes({@JsonSubTypes.Type(value = AccountAuthReq.class, name = "account"), + @JsonSubTypes.Type(value = EmailAuthReq.class, name = "email"), + @JsonSubTypes.Type(value = PhoneAuthReq.class, name = "phone")}) public abstract class AuthReq { - @Schema(description = "clientId 客户端标识") - @NotBlank(message = "客户端标识不能为空") + @Schema(description = "客户端id") + @NotBlank(message = "客户端id不能为空") private String clientId; @Schema(description = "认证类型") diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/service/LoginService.java b/continew-module-system/src/main/java/top/continew/admin/auth/service/LoginService.java index 7b8179d1..e3257967 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/service/LoginService.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/service/LoginService.java @@ -42,8 +42,8 @@ public interface LoginService { * 检查用户是否被锁定 * * @param username 用户名 - * @param request 请求对象 - * @param isError 是否登录错误 + * @param request 请求对象 + * @param isError 是否登录错误 */ void checkUserLocked(String username, HttpServletRequest request, boolean isError); diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java b/continew-module-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java index e0c6ae47..00b4dd49 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java @@ -187,18 +187,18 @@ public class LoginServiceImpl implements LoginService { public String login(UserDO user) { Long userId = user.getId(); CompletableFuture> permissionFuture = CompletableFuture.supplyAsync(() -> roleService - .listPermissionByUserId(userId), threadPoolTaskExecutor); + .listPermissionByUserId(userId), threadPoolTaskExecutor); CompletableFuture> roleFuture = CompletableFuture.supplyAsync(() -> roleService - .listByUserId(userId), threadPoolTaskExecutor); + .listByUserId(userId), threadPoolTaskExecutor); CompletableFuture passwordExpirationDaysFuture = CompletableFuture.supplyAsync(() -> optionService - .getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name())); + .getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name())); CompletableFuture.allOf(permissionFuture, roleFuture, passwordExpirationDaysFuture); UserContext userContext = new UserContext(permissionFuture.join(), roleFuture - .join(), passwordExpirationDaysFuture.join()); + .join(), passwordExpirationDaysFuture.join()); BeanUtil.copyProperties(user, userContext); // 登录并缓存用户信息 StpUtil.login(userContext.getId(), SaLoginConfig.setExtraData(BeanUtil - .beanToMap(new UserExtraContext(SpringWebUtils.getRequest())))); + .beanToMap(new UserExtraContext(SpringWebUtils.getRequest())))); UserContextHolder.setContext(userContext); return StpUtil.getTokenValue(); } @@ -231,7 +231,7 @@ public class LoginServiceImpl implements LoginService { } // 检测是否已被锁定 String key = CacheConstants.USER_PASSWORD_ERROR_KEY_PREFIX + RedisUtils.formatKey(username, JakartaServletUtil - .getClientIP(request)); + .getClientIP(request)); int lockMinutes = optionService.getValueByCode2Int(PasswordPolicyEnum.PASSWORD_ERROR_LOCK_MINUTES.name()); Integer currentErrorCount = ObjectUtil.defaultIfNull(RedisUtils.get(key), 0); CheckUtils.throwIf(currentErrorCount >= maxErrorCount, "账号锁定 {} 分钟,请稍后再试", lockMinutes); diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/AuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/AuthStrategy.java index 41d86ba5..3aba5bdc 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/AuthStrategy.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/AuthStrategy.java @@ -1,3 +1,19 @@ +/* + * 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.auth.strategy; import jakarta.servlet.http.HttpServletRequest; diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AbstractAuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AbstractAuthStrategy.java index dddd8f46..7ca147f2 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AbstractAuthStrategy.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AbstractAuthStrategy.java @@ -1,6 +1,21 @@ +/* + * 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.auth.strategy.impl; -import cn.dev33.satoken.stp.SaLoginConfig; import cn.dev33.satoken.stp.SaLoginModel; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.bean.BeanUtil; @@ -42,6 +57,7 @@ public abstract class AbstractAuthStrategy { public static final String CAPTCHA_EXPIRED = "验证码已失效"; public static final String CAPTCHA_ERROR = "验证码错误"; public static final String CLIENT_ID = "clientId"; + /** * 获取登录凭证 * @@ -54,15 +70,15 @@ public abstract class AbstractAuthStrategy { // 核心登录逻辑 Long userId = user.getId(); CompletableFuture> permissionFuture = CompletableFuture.supplyAsync(() -> roleService - .listPermissionByUserId(userId), threadPoolTaskExecutor); + .listPermissionByUserId(userId), threadPoolTaskExecutor); CompletableFuture> roleFuture = CompletableFuture.supplyAsync(() -> roleService - .listByUserId(userId), threadPoolTaskExecutor); + .listByUserId(userId), threadPoolTaskExecutor); CompletableFuture passwordExpirationDaysFuture = CompletableFuture.supplyAsync(() -> optionService - .getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name())); + .getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name())); CompletableFuture.allOf(permissionFuture, roleFuture, passwordExpirationDaysFuture); UserContext userContext = new UserContext(permissionFuture.join(), roleFuture - .join(), passwordExpirationDaysFuture.join()); + .join(), passwordExpirationDaysFuture.join()); BeanUtil.copyProperties(user, userContext); SaLoginModel model = new SaLoginModel(); @@ -80,8 +96,8 @@ public abstract class AbstractAuthStrategy { customizeUserContext(userContext, user, clientResp); // 登录并缓存用户信息 - StpUtil.login(userContext.getId(), model.setExtraData(BeanUtil - .beanToMap(new UserExtraContext(SpringWebUtils.getRequest())))); + StpUtil.login(userContext.getId(), model.setExtraData(BeanUtil.beanToMap(new UserExtraContext(SpringWebUtils + .getRequest())))); UserContextHolder.setContext(userContext); // 后置处理 diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AccountLoginStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AccountLoginStrategy.java index c28d2a40..a8d8871a 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AccountLoginStrategy.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AccountLoginStrategy.java @@ -1,3 +1,19 @@ +/* + * 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.auth.strategy.impl; import jakarta.servlet.http.HttpServletRequest; @@ -71,8 +87,7 @@ public class AccountLoginStrategy extends AbstractAuthStrategy implements AuthSt public LoginResp login(AccountAuthReq authReq, ClientResp clientResp, HttpServletRequest request) { this.validate(authReq); // 解密密码 - String rawPassword = ExceptionUtils.exToNull(() -> - SecureUtils.decryptByRsaPrivateKey(authReq.getPassword())); + String rawPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(authReq.getPassword())); ValidationUtils.throwIfBlank(rawPassword, "密码解密失败"); // 验证用户名密码 diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/EmailAuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/EmailAuthStrategy.java index d05eccd2..ff5c876a 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/EmailAuthStrategy.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/EmailAuthStrategy.java @@ -1,3 +1,19 @@ +/* + * 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.auth.strategy.impl; import jakarta.servlet.http.HttpServletRequest; @@ -88,4 +104,4 @@ public class EmailAuthStrategy extends AbstractAuthStrategy implements AuthStrat public String authCertificate(UserDO user, ClientResp clientResp) { return super.authCertificate(user, clientResp); } -} \ No newline at end of file +} \ No newline at end of file diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/PhoneAuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/PhoneAuthStrategy.java index c5263cfa..f9833972 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/PhoneAuthStrategy.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/PhoneAuthStrategy.java @@ -1,3 +1,19 @@ +/* + * 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.auth.strategy.impl; import jakarta.servlet.http.HttpServletRequest; diff --git a/continew-module-system/src/main/java/top/continew/admin/system/mapper/ClientMapper.java b/continew-module-system/src/main/java/top/continew/admin/system/mapper/ClientMapper.java index b7f1d199..5bc6dee2 100644 --- a/continew-module-system/src/main/java/top/continew/admin/system/mapper/ClientMapper.java +++ b/continew-module-system/src/main/java/top/continew/admin/system/mapper/ClientMapper.java @@ -1,12 +1,28 @@ +/* + * 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.system.mapper; import top.continew.starter.data.mp.base.BaseMapper; import top.continew.admin.system.model.entity.ClientDO; /** -* 客户端管理 Mapper -* -* @author MoChou -* @since 2024/12/03 16:04 -*/ + * 客户端管理 Mapper + * + * @author MoChou + * @since 2024/12/03 16:04 + */ public interface ClientMapper extends BaseMapper {} \ No newline at end of file diff --git a/continew-module-system/src/main/java/top/continew/admin/system/model/entity/ClientDO.java b/continew-module-system/src/main/java/top/continew/admin/system/model/entity/ClientDO.java index db9b1917..80ed66a7 100644 --- a/continew-module-system/src/main/java/top/continew/admin/system/model/entity/ClientDO.java +++ b/continew-module-system/src/main/java/top/continew/admin/system/model/entity/ClientDO.java @@ -1,3 +1,19 @@ +/* + * 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.system.model.entity; import com.baomidou.mybatisplus.annotation.TableField; diff --git a/continew-module-system/src/main/java/top/continew/admin/system/model/query/ClientQuery.java b/continew-module-system/src/main/java/top/continew/admin/system/model/query/ClientQuery.java index 8b1d777a..96cd2a3a 100644 --- a/continew-module-system/src/main/java/top/continew/admin/system/model/query/ClientQuery.java +++ b/continew-module-system/src/main/java/top/continew/admin/system/model/query/ClientQuery.java @@ -1,3 +1,19 @@ +/* + * 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.system.model.query; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/continew-module-system/src/main/java/top/continew/admin/system/model/req/ClientReq.java b/continew-module-system/src/main/java/top/continew/admin/system/model/req/ClientReq.java index d37f6fe8..09b5eb0d 100644 --- a/continew-module-system/src/main/java/top/continew/admin/system/model/req/ClientReq.java +++ b/continew-module-system/src/main/java/top/continew/admin/system/model/req/ClientReq.java @@ -1,3 +1,19 @@ +/* + * 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.system.model.req; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientDetailResp.java b/continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientDetailResp.java index 611c5fd9..8afc05f5 100644 --- a/continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientDetailResp.java +++ b/continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientDetailResp.java @@ -1,3 +1,19 @@ +/* + * 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.system.model.resp; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; diff --git a/continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientResp.java b/continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientResp.java index dcb81879..e45f5f92 100644 --- a/continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientResp.java +++ b/continew-module-system/src/main/java/top/continew/admin/system/model/resp/ClientResp.java @@ -1,3 +1,19 @@ +/* + * 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.system.model.resp; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/continew-module-system/src/main/java/top/continew/admin/system/service/ClientService.java b/continew-module-system/src/main/java/top/continew/admin/system/service/ClientService.java index 840a64ca..4ea45cd8 100644 --- a/continew-module-system/src/main/java/top/continew/admin/system/service/ClientService.java +++ b/continew-module-system/src/main/java/top/continew/admin/system/service/ClientService.java @@ -1,3 +1,19 @@ +/* + * 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.system.service; import top.continew.admin.system.model.query.ClientQuery; diff --git a/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java b/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java index 970e3c79..98bddfdf 100644 --- a/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java +++ b/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java @@ -1,3 +1,19 @@ +/* + * 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.system.service.impl; import cn.hutool.core.bean.BeanUtil; @@ -18,7 +34,6 @@ import top.continew.starter.core.validation.ValidationUtils; import top.continew.starter.extension.crud.service.BaseServiceImpl; import java.util.List; -import java.util.UUID; /** * 客户端管理业务实现 @@ -37,20 +52,24 @@ public class ClientServiceImpl extends BaseServiceImpl().eq(ClientDO::getClientId, clientId)); + ClientDO clientDO = baseMapper.selectOne(new LambdaQueryWrapper() + .eq(ClientDO::getClientId, clientId)); return BeanUtil.copyProperties(clientDO, ClientResp.class); } @Override protected void beforeDelete(List ids) { // 查询如果删除客户端记录以后是否还存在账号认证的方式,不存在则不允许删除 - List clientDOS = baseMapper.selectList(new LambdaQueryWrapper().notIn(ClientDO::getId, ids).like(ClientDO::getAuthType, AuthTypeEnum.ACCOUNT.getValue())); - ValidationUtils.throwIfEmpty(clientDOS, StrUtil.format("请至少保留一条{}认证的方式",AuthTypeEnum.ACCOUNT.getDescription())); + List clientDOS = baseMapper.selectList(new LambdaQueryWrapper().notIn(ClientDO::getId, ids) + .like(ClientDO::getAuthType, AuthTypeEnum.ACCOUNT.getValue())); + ValidationUtils.throwIfEmpty(clientDOS, StrUtil.format("请至少保留一条{}认证的方式", AuthTypeEnum.ACCOUNT + .getDescription())); super.beforeDelete(ids); } } \ No newline at end of file diff --git a/continew-webapi/src/main/java/top/continew/admin/config/log/LogDaoLocalImpl.java b/continew-webapi/src/main/java/top/continew/admin/config/log/LogDaoLocalImpl.java index 04ccd7e9..6700a009 100644 --- a/continew-webapi/src/main/java/top/continew/admin/config/log/LogDaoLocalImpl.java +++ b/continew-webapi/src/main/java/top/continew/admin/config/log/LogDaoLocalImpl.java @@ -76,8 +76,8 @@ public class LogDaoLocalImpl implements LogDao { // 设置基本信息 logDO.setDescription(logRecord.getDescription()); logDO.setModule(StrUtils.blankToDefault(logRecord.getModule(), null, m -> m - .replace("API", StringConstants.EMPTY) - .trim())); + .replace("API", StringConstants.EMPTY) + .trim())); logDO.setTimeTaken(logRecord.getTimeTaken().toMillis()); logDO.setCreateTime(LocalDateTime.ofInstant(logRecord.getTimestamp(), ZoneId.systemDefault())); // 设置操作人 @@ -147,19 +147,23 @@ public class LogDaoLocalImpl implements LogDao { if (requestUri.startsWith(SysConstants.LOGIN_URI) && LogStatusEnum.SUCCESS.equals(logDO.getStatus())) { String requestBody = logRequest.getBody(); //账号登录设置操作人 - if (requestBody.contains(AuthTypeEnum.ACCOUNT.getValue())){ + if (requestBody.contains(AuthTypeEnum.ACCOUNT.getValue())) { AccountAuthReq loginReq = JSONUtil.toBean(requestBody, AccountAuthReq.class); - logDO.setCreateUser(ExceptionUtils.exToNull(() -> userService.getByUsername(loginReq.getUsername()).getId())); + logDO.setCreateUser(ExceptionUtils.exToNull(() -> userService.getByUsername(loginReq.getUsername()) + .getId())); } return; } // 解析 Token 信息 Map requestHeaders = logRequest.getHeaders(); String headerName = HttpHeaders.AUTHORIZATION; - boolean isContainsAuthHeader = CollUtil.containsAny(requestHeaders.keySet(), Set.of(headerName, headerName.toLowerCase())); + boolean isContainsAuthHeader = CollUtil.containsAny(requestHeaders.keySet(), Set.of(headerName, headerName + .toLowerCase())); if (MapUtil.isNotEmpty(requestHeaders) && isContainsAuthHeader) { - String authorization = requestHeaders.getOrDefault(headerName, requestHeaders.get(headerName.toLowerCase())); - String token = authorization.replace(SaManager.getConfig().getTokenPrefix() + StringConstants.SPACE, StringConstants.EMPTY); + String authorization = requestHeaders.getOrDefault(headerName, requestHeaders.get(headerName + .toLowerCase())); + String token = authorization.replace(SaManager.getConfig() + .getTokenPrefix() + StringConstants.SPACE, StringConstants.EMPTY); logDO.setCreateUser(Convert.toLong(StpUtil.getLoginIdByToken(token))); } } diff --git a/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java b/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java index 6b40bfbf..8d83f8cd 100644 --- a/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java +++ b/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java @@ -1,3 +1,19 @@ +/* + * 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; @@ -52,26 +68,22 @@ public class AuthController { private final AuthStrategyContext authStrategyContext; - @SaIgnore @Operation(summary = "登录", description = "统一登录入口") @PostMapping("/login") public LoginResp login(@Validated @RequestBody AuthReq loginReq, HttpServletRequest request) { - // 客户端标识 - String clientId = loginReq.getClientId(); // 认证类型 String authType = loginReq.getAuthType(); - ValidationUtils.throwIfBlank(clientId, "Client ID不能为空"); // 获取并验证客户端信息 - ClientResp clientResp = clientService.getClientByClientId(clientId); + ClientResp clientResp = clientService.getClientByClientId(loginReq.getClientId()); ValidationUtils.throwIfNull(clientResp, "客户端信息不存在,请检查客户端标识是否正确!"); // 验证认证类型 ValidationUtils.throwIf(!clientResp.getAuthType().contains(authType), StrUtil.format("暂未授权此类型:{}", authType)); try { // 执行登录策略 - return (LoginResp) authStrategyContext.getStrategy(authType).login(loginReq, clientResp, request); + return (LoginResp)authStrategyContext.getStrategy(authType).login(loginReq, clientResp, request); } catch (Exception e) { log.error("登录失败: {}", e.getMessage(), e); throw new BusinessException("登录失败: " + e.getMessage()); diff --git a/continew-webapi/src/main/java/top/continew/admin/controller/system/ClientController.java b/continew-webapi/src/main/java/top/continew/admin/controller/system/ClientController.java index 27bb63f8..de468297 100644 --- a/continew-webapi/src/main/java/top/continew/admin/controller/system/ClientController.java +++ b/continew-webapi/src/main/java/top/continew/admin/controller/system/ClientController.java @@ -1,3 +1,19 @@ +/* + * 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.system; import io.swagger.v3.oas.annotations.tags.Tag; -- Gitee From 0d48b525ba8c0882feb2d6cbe4b08723bd8c43f2 Mon Sep 17 00:00:00 2001 From: KAI <1373639299@qq.com> Date: Wed, 25 Dec 2024 12:01:00 +0800 Subject: [PATCH 07/12] =?UTF-8?q?style:=20=E7=9B=AE=E5=BD=95=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuthStrategy.java => AuthHandler.java} | 6 +++--- ...gyContext.java => AuthHandlerContext.java} | 20 +++++++++---------- .../AbstractAuthHandler.java} | 6 +++--- .../AccountAuthHandler.java} | 8 ++++---- .../EmailAuthHandler.java} | 10 +++++----- .../PhoneAuthHandler.java} | 12 +++++------ .../admin/controller/auth/AuthController.java | 6 +++--- 7 files changed, 34 insertions(+), 34 deletions(-) rename continew-module-system/src/main/java/top/continew/admin/auth/{strategy/AuthStrategy.java => AuthHandler.java} (92%) rename continew-module-system/src/main/java/top/continew/admin/auth/config/{AuthStrategyContext.java => AuthHandlerContext.java} (63%) rename continew-module-system/src/main/java/top/continew/admin/auth/{strategy/impl/AbstractAuthStrategy.java => handler/AbstractAuthHandler.java} (97%) rename continew-module-system/src/main/java/top/continew/admin/auth/{strategy/impl/AccountLoginStrategy.java => handler/AccountAuthHandler.java} (94%) rename continew-module-system/src/main/java/top/continew/admin/auth/{strategy/impl/EmailAuthStrategy.java => handler/EmailAuthHandler.java} (90%) rename continew-module-system/src/main/java/top/continew/admin/auth/{strategy/impl/PhoneAuthStrategy.java => handler/PhoneAuthHandler.java} (89%) diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/AuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/AuthHandler.java similarity index 92% rename from continew-module-system/src/main/java/top/continew/admin/auth/strategy/AuthStrategy.java rename to continew-module-system/src/main/java/top/continew/admin/auth/AuthHandler.java index 3aba5bdc..e46e3a50 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/AuthStrategy.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/AuthHandler.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package top.continew.admin.auth.strategy; +package top.continew.admin.auth; import jakarta.servlet.http.HttpServletRequest; import top.continew.admin.auth.enums.AuthTypeEnum; @@ -22,12 +22,12 @@ import top.continew.admin.auth.model.req.AuthReq; import top.continew.admin.system.model.resp.ClientResp; /** - * 登录策略接口 + * 认证接口 * * @author KAI * @since 2024/12/22 14:52:23 */ -public interface AuthStrategy { +public interface AuthHandler { /** * 执行登录 diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/config/AuthStrategyContext.java b/continew-module-system/src/main/java/top/continew/admin/auth/config/AuthHandlerContext.java similarity index 63% rename from continew-module-system/src/main/java/top/continew/admin/auth/config/AuthStrategyContext.java rename to continew-module-system/src/main/java/top/continew/admin/auth/config/AuthHandlerContext.java index 6bfbc754..f958de5f 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/config/AuthStrategyContext.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/config/AuthHandlerContext.java @@ -19,7 +19,7 @@ package top.continew.admin.auth.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import top.continew.admin.auth.model.req.AuthReq; -import top.continew.admin.auth.strategy.AuthStrategy; +import top.continew.admin.auth.AuthHandler; import java.util.HashMap; import java.util.List; @@ -32,22 +32,22 @@ import java.util.Map; * @since 2024/12/20 15:16:55 */ @Component -public class AuthStrategyContext { - private final Map> strategyMap = new HashMap<>(); +public class AuthHandlerContext { + private final Map> handlerMap = new HashMap<>(); @Autowired - public AuthStrategyContext(List> strategies) { - for (AuthStrategy strategy : strategies) { - strategyMap.put(strategy.getAuthType().getValue(), strategy); + public AuthHandlerContext(List> strategies) { + for (AuthHandler strategy : strategies) { + handlerMap.put(strategy.getAuthType().getValue(), strategy); } } @SuppressWarnings("unchecked") - public AuthStrategy getStrategy(String type) { - AuthStrategy strategy = strategyMap.get(type); + public AuthHandler getHandler(String type) { + AuthHandler strategy = handlerMap.get(type); if (strategy == null) { - throw new IllegalArgumentException("No strategy found for type: " + type); + throw new IllegalArgumentException("No handler found for type: " + type); } - return (AuthStrategy)strategy; + return (AuthHandler)strategy; } } diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AbstractAuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/handler/AbstractAuthHandler.java similarity index 97% rename from continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AbstractAuthStrategy.java rename to continew-module-system/src/main/java/top/continew/admin/auth/handler/AbstractAuthHandler.java index 7ca147f2..05480ea4 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AbstractAuthStrategy.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/handler/AbstractAuthHandler.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package top.continew.admin.auth.strategy.impl; +package top.continew.admin.auth.handler; import cn.dev33.satoken.stp.SaLoginModel; import cn.dev33.satoken.stp.StpUtil; @@ -39,14 +39,14 @@ import java.util.concurrent.CompletableFuture; import static top.continew.admin.system.enums.PasswordPolicyEnum.PASSWORD_EXPIRATION_DAYS; /** - * 登录策略 + * 认证处理器抽象类 * * @author KAI * @since 2024/12/22 14:52:32 */ @Component @RequiredArgsConstructor -public abstract class AbstractAuthStrategy { +public abstract class AbstractAuthHandler { @Resource private RoleService roleService; @Resource diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AccountLoginStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/handler/AccountAuthHandler.java similarity index 94% rename from continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AccountLoginStrategy.java rename to continew-module-system/src/main/java/top/continew/admin/auth/handler/AccountAuthHandler.java index a8d8871a..ebfefc2b 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/AccountLoginStrategy.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/handler/AccountAuthHandler.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package top.continew.admin.auth.strategy.impl; +package top.continew.admin.auth.handler; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -24,7 +24,7 @@ import top.continew.admin.auth.enums.AuthTypeEnum; import top.continew.admin.auth.model.req.AccountAuthReq; import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.auth.service.LoginService; -import top.continew.admin.auth.strategy.AuthStrategy; +import top.continew.admin.auth.AuthHandler; import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.util.SecureUtils; import top.continew.admin.system.model.entity.UserDO; @@ -35,14 +35,14 @@ import top.continew.starter.core.util.ExceptionUtils; import top.continew.starter.core.validation.ValidationUtils; /** - * 账号登录策略实现 + * 账号认证处理器 * * @author KAI * @since 2024/12/22 14:58:32 */ @Component @RequiredArgsConstructor -public class AccountLoginStrategy extends AbstractAuthStrategy implements AuthStrategy { +public class AccountAuthHandler extends AbstractAuthHandler implements AuthHandler { private final UserService userService; private final LoginService loginService; diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/EmailAuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/handler/EmailAuthHandler.java similarity index 90% rename from continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/EmailAuthStrategy.java rename to continew-module-system/src/main/java/top/continew/admin/auth/handler/EmailAuthHandler.java index ff5c876a..b5948086 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/EmailAuthStrategy.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/handler/EmailAuthHandler.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package top.continew.admin.auth.strategy.impl; +package top.continew.admin.auth.handler; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -23,7 +23,7 @@ import top.continew.admin.auth.enums.AuthTypeEnum; import top.continew.admin.auth.model.req.EmailAuthReq; import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.auth.service.LoginService; -import top.continew.admin.auth.strategy.AuthStrategy; +import top.continew.admin.auth.AuthHandler; import top.continew.admin.common.constant.CacheConstants; import top.continew.admin.system.model.entity.UserDO; import top.continew.admin.system.model.resp.ClientResp; @@ -32,14 +32,14 @@ import top.continew.starter.cache.redisson.util.RedisUtils; import top.continew.starter.core.validation.ValidationUtils; /** - * 邮箱登录策略实现 + * 邮箱认证处理器 * * @author KAI * @since 2024/12/22 14:58:48 */ @Component @RequiredArgsConstructor -public class EmailAuthStrategy extends AbstractAuthStrategy implements AuthStrategy { +public class EmailAuthHandler extends AbstractAuthHandler implements AuthHandler { private final UserService userService; private final LoginService loginService; @@ -78,7 +78,7 @@ public class EmailAuthStrategy extends AbstractAuthStrategy implements AuthStrat String email = authReq.getEmail(); String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + email; String captcha = RedisUtils.get(captchaKey); - ValidationUtils.throwIfBlank(captcha, AbstractAuthStrategy.CAPTCHA_EXPIRED); + ValidationUtils.throwIfBlank(captcha, AbstractAuthHandler.CAPTCHA_EXPIRED); ValidationUtils.throwIfNotEqualIgnoreCase(authReq.getCaptcha(), captcha, CAPTCHA_ERROR); RedisUtils.delete(captchaKey); // 验证邮箱 diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/PhoneAuthStrategy.java b/continew-module-system/src/main/java/top/continew/admin/auth/handler/PhoneAuthHandler.java similarity index 89% rename from continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/PhoneAuthStrategy.java rename to continew-module-system/src/main/java/top/continew/admin/auth/handler/PhoneAuthHandler.java index f9833972..4d810ed9 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/strategy/impl/PhoneAuthStrategy.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/handler/PhoneAuthHandler.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package top.continew.admin.auth.strategy.impl; +package top.continew.admin.auth.handler; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -23,7 +23,7 @@ import top.continew.admin.auth.enums.AuthTypeEnum; import top.continew.admin.auth.model.req.PhoneAuthReq; import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.auth.service.LoginService; -import top.continew.admin.auth.strategy.AuthStrategy; +import top.continew.admin.auth.AuthHandler; import top.continew.admin.common.constant.CacheConstants; import top.continew.admin.system.model.entity.UserDO; import top.continew.admin.system.model.resp.ClientResp; @@ -32,14 +32,14 @@ import top.continew.starter.cache.redisson.util.RedisUtils; import top.continew.starter.core.validation.ValidationUtils; /** - * 手机号登录策略实现 + * 手机号认证处理器 * * @author KAI * @since 2024/12/22 14:59:11 */ @Component @RequiredArgsConstructor -public class PhoneAuthStrategy extends AbstractAuthStrategy implements AuthStrategy { +public class PhoneAuthHandler extends AbstractAuthHandler implements AuthHandler { private final UserService userService; private final LoginService loginService; @@ -79,8 +79,8 @@ public class PhoneAuthStrategy extends AbstractAuthStrategy implements AuthStrat String phone = authReq.getPhone(); String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + phone; String captcha = RedisUtils.get(captchaKey); - ValidationUtils.throwIfBlank(captcha, AbstractAuthStrategy.CAPTCHA_EXPIRED); - ValidationUtils.throwIfNotEqualIgnoreCase(authReq.getCaptcha(), captcha, AbstractAuthStrategy.CAPTCHA_ERROR); + ValidationUtils.throwIfBlank(captcha, AbstractAuthHandler.CAPTCHA_EXPIRED); + ValidationUtils.throwIfNotEqualIgnoreCase(authReq.getCaptcha(), captcha, AbstractAuthHandler.CAPTCHA_ERROR); RedisUtils.delete(captchaKey); // 验证手机号 diff --git a/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java b/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java index 8d83f8cd..3d03cb0e 100644 --- a/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java +++ b/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java @@ -29,7 +29,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import top.continew.admin.auth.config.AuthStrategyContext; +import top.continew.admin.auth.config.AuthHandlerContext; import top.continew.admin.auth.model.req.AuthReq; import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.auth.model.resp.RouteResp; @@ -66,7 +66,7 @@ public class AuthController { private final LoginService loginService; - private final AuthStrategyContext authStrategyContext; + private final AuthHandlerContext authHandlerContext; @SaIgnore @Operation(summary = "登录", description = "统一登录入口") @@ -83,7 +83,7 @@ public class AuthController { ValidationUtils.throwIf(!clientResp.getAuthType().contains(authType), StrUtil.format("暂未授权此类型:{}", authType)); try { // 执行登录策略 - return (LoginResp)authStrategyContext.getStrategy(authType).login(loginReq, clientResp, request); + return (LoginResp)authHandlerContext.getHandler(authType).login(loginReq, clientResp, request); } catch (Exception e) { log.error("登录失败: {}", e.getMessage(), e); throw new BusinessException("登录失败: " + e.getMessage()); -- Gitee From dad046c959753bf62dd417efba6ea6a823478739 Mon Sep 17 00:00:00 2001 From: KAI <1373639299@qq.com> Date: Wed, 25 Dec 2024 16:07:41 +0800 Subject: [PATCH 08/12] =?UTF-8?q?style:=20=E6=B3=A8=E9=87=8A=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/top/continew/admin/auth/enums/AuthTypeEnum.java | 2 +- .../continew/admin/auth/handler/AbstractAuthHandler.java | 2 +- .../top/continew/admin/auth/handler/EmailAuthHandler.java | 2 +- .../top/continew/admin/auth/handler/PhoneAuthHandler.java | 2 +- .../java/top/continew/admin/auth/model/req/AuthReq.java | 5 +++-- .../java/top/continew/admin/auth/service/LoginService.java | 7 +++++++ .../continew/admin/auth/service/impl/LoginServiceImpl.java | 3 ++- .../src/main/resources/config/application-dev.yml | 6 +++--- 8 files changed, 19 insertions(+), 10 deletions(-) diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java b/continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java index 104b9d5c..bb2e62f3 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java @@ -49,7 +49,7 @@ public enum AuthTypeEnum implements BaseEnum { /** * 第三方授权 */ - SOCIAL_AUTH("SocialAuth", "第三方授权", UiConstants.COLOR_DEFAULT); + SOCIAL_AUTH("socialAuth", "第三方授权", UiConstants.COLOR_DEFAULT); private final String value; private final String description; diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/handler/AbstractAuthHandler.java b/continew-module-system/src/main/java/top/continew/admin/auth/handler/AbstractAuthHandler.java index 05480ea4..cd7c46e9 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/handler/AbstractAuthHandler.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/handler/AbstractAuthHandler.java @@ -42,7 +42,7 @@ import static top.continew.admin.system.enums.PasswordPolicyEnum.PASSWORD_EXPIRA * 认证处理器抽象类 * * @author KAI - * @since 2024/12/22 14:52:32 + * @since 2024/12/22 14:52 */ @Component @RequiredArgsConstructor diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/handler/EmailAuthHandler.java b/continew-module-system/src/main/java/top/continew/admin/auth/handler/EmailAuthHandler.java index b5948086..0c6e840d 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/handler/EmailAuthHandler.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/handler/EmailAuthHandler.java @@ -35,7 +35,7 @@ import top.continew.starter.core.validation.ValidationUtils; * 邮箱认证处理器 * * @author KAI - * @since 2024/12/22 14:58:48 + * @since 2024/12/22 14:58 */ @Component @RequiredArgsConstructor diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/handler/PhoneAuthHandler.java b/continew-module-system/src/main/java/top/continew/admin/auth/handler/PhoneAuthHandler.java index 4d810ed9..72189669 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/handler/PhoneAuthHandler.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/handler/PhoneAuthHandler.java @@ -35,7 +35,7 @@ import top.continew.starter.core.validation.ValidationUtils; * 手机号认证处理器 * * @author KAI - * @since 2024/12/22 14:59:11 + * @since 2024/12/22 14:59 */ @Component @RequiredArgsConstructor diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java index da023d30..7820faca 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/AuthReq.java @@ -26,13 +26,14 @@ import lombok.Data; * 登录参数基础类 * * @author KAI - * @since 2024/12/22 15:16:39 + * @since 2024/12/22 15:16 */ @Data @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "authType", visible = true) @JsonSubTypes({@JsonSubTypes.Type(value = AccountAuthReq.class, name = "account"), @JsonSubTypes.Type(value = EmailAuthReq.class, name = "email"), - @JsonSubTypes.Type(value = PhoneAuthReq.class, name = "phone")}) + @JsonSubTypes.Type(value = PhoneAuthReq.class, name = "phone"), + @JsonSubTypes.Type(value = SocialAuthReq.class, name = "socialAuth")}) public abstract class AuthReq { @Schema(description = "客户端id") diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/service/LoginService.java b/continew-module-system/src/main/java/top/continew/admin/auth/service/LoginService.java index e3257967..529ec973 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/service/LoginService.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/service/LoginService.java @@ -70,4 +70,11 @@ public interface LoginService { * @return 路由树 */ List buildRouteTree(Long userId); + + /** + * 发送安全消息 + * + * @param user 用户信息 + */ + void sendSecurityMsg(UserDO user); } diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java b/continew-module-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java index 00b4dd49..e021bd2d 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java @@ -251,7 +251,8 @@ public class LoginServiceImpl implements LoginService { * * @param user 用户信息 */ - private void sendSecurityMsg(UserDO user) { + @Override + public void sendSecurityMsg(UserDO user) { MessageReq req = new MessageReq(); MessageTemplateEnum socialRegister = MessageTemplateEnum.SOCIAL_REGISTER; req.setTitle(socialRegister.getTitle().formatted(projectProperties.getName())); diff --git a/continew-webapi/src/main/resources/config/application-dev.yml b/continew-webapi/src/main/resources/config/application-dev.yml index 119d8424..4e62a950 100644 --- a/continew-webapi/src/main/resources/config/application-dev.yml +++ b/continew-webapi/src/main/resources/config/application-dev.yml @@ -1,7 +1,7 @@ --- ### 项目配置 project: # URL(跨域配置默认放行此 URL,第三方登录回调默认使用此 URL 为前缀,请注意更改为你实际的前端 URL) - url: http://localhost:5173 + url: http://120.46.172.119:1234 --- ### 服务器配置 server: @@ -203,8 +203,8 @@ justauth: enabled: true type: GITEE: - client-id: 5d271b7f638941812aaf8bfc2e2f08f06d6235ef934e0e39537e2364eb8452c4 - client-secret: 1f7d08**********5b7**********29e + client-id: a0ef43747707a28fe0c01d901496af5a0ac9d34274793103e7baa043c495e60a + client-secret: eb29099d5d1942088b87ded007cb14e4d216aa79957f944920ab4bdd1bb39b67 redirect-uri: ${project.url}/social/callback?source=gitee GITHUB: client-id: 38080dad08cfbdfacca9 -- Gitee From b18c35d000ca9dc9a7722a42e03ebd045bc270d9 Mon Sep 17 00:00:00 2001 From: KAI <1373639299@qq.com> Date: Wed, 25 Dec 2024 16:08:06 +0800 Subject: [PATCH 09/12] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9Eoauth2=E7=99=BB?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/auth/handler/SocialAuthHandler.java | 173 ++++++++++++++++++ .../admin/auth/model/req/SocialAuthReq.java | 49 +++++ 2 files changed, 222 insertions(+) create mode 100644 continew-module-system/src/main/java/top/continew/admin/auth/handler/SocialAuthHandler.java create mode 100644 continew-module-system/src/main/java/top/continew/admin/auth/model/req/SocialAuthReq.java diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/handler/SocialAuthHandler.java b/continew-module-system/src/main/java/top/continew/admin/auth/handler/SocialAuthHandler.java new file mode 100644 index 00000000..e0987a21 --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/auth/handler/SocialAuthHandler.java @@ -0,0 +1,173 @@ +/* + * 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.auth.handler; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.ReUtil; +import cn.hutool.json.JSONUtil; +import com.xkcoding.justauth.AuthRequestFactory; +import jakarta.servlet.http.HttpServletRequest; +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 org.springframework.stereotype.Component; +import top.continew.admin.auth.AuthHandler; +import top.continew.admin.auth.enums.AuthTypeEnum; +import top.continew.admin.auth.model.req.SocialAuthReq; +import top.continew.admin.auth.model.resp.LoginResp; +import top.continew.admin.auth.service.LoginService; +import top.continew.admin.common.constant.RegexConstants; +import top.continew.admin.common.constant.SysConstants; +import top.continew.admin.common.enums.GenderEnum; +import top.continew.admin.system.model.entity.RoleDO; +import top.continew.admin.system.model.entity.UserDO; +import top.continew.admin.system.model.entity.UserSocialDO; +import top.continew.admin.system.model.resp.ClientResp; +import top.continew.admin.system.service.RoleService; +import top.continew.admin.system.service.UserRoleService; +import top.continew.admin.system.service.UserService; +import top.continew.admin.system.service.UserSocialService; +import top.continew.starter.core.exception.BadRequestException; +import top.continew.starter.core.validation.ValidationUtils; + +import java.time.LocalDateTime; +import java.util.Collections; + +/** + * 手机号认证处理器 + * + * @author KAI + * @since 2024/12/25 14:21 + */ +@Component +@RequiredArgsConstructor + +public class SocialAuthHandler extends AbstractAuthHandler implements AuthHandler { + private final AuthRequestFactory authRequestFactory; + private final UserSocialService userSocialService; + private final UserService userService; + private final RoleService roleService; + private final UserRoleService userRoleService; + private final LoginService loginService; + + /** + * 获取认证类型 + * + * @return 第三方认证类型 + */ + @Override + public AuthTypeEnum getAuthType() { + return AuthTypeEnum.SOCIAL_AUTH; + } + + /** + * 校验第三方登录请求对象 + * + * @param authReq 登录请求参数 + */ + @Override + public void validate(SocialAuthReq authReq) { + ValidationUtils.validate(authReq); + } + + /** + * 第三方登录 + * + * @param authReq 第三方登录请求对象 + * @param request HTTP请求对象 + * @return 登录响应 + */ + @Override + public LoginResp login(SocialAuthReq authReq, ClientResp clientResp, HttpServletRequest request) { + this.validate(authReq); + if (StpUtil.isLogin()) { + StpUtil.logout(); + } + AuthRequest authRequest = this.getAuthRequest(authReq.getSource()); + AuthCallback callback = new AuthCallback(); + callback.setCode(authReq.getCode()); + callback.setState(authReq.getState()); + AuthResponse response = authRequest.login(callback); + ValidationUtils.throwIf(!response.ok(), response.getMsg()); + AuthUser authUser = response.getData(); + String source = authUser.getSource(); + String openId = authUser.getUuid(); + UserSocialDO userSocial = userSocialService.getBySourceAndOpenId(source, openId); + UserDO user; + if (null == userSocial) { + String username = authUser.getUsername(); + String nickname = authUser.getNickname(); + UserDO existsUser = userService.getByUsername(username); + String randomStr = RandomUtil.randomString(RandomUtil.BASE_CHAR, 5); + if (null != existsUser || !ReUtil.isMatch(RegexConstants.USERNAME, username)) { + username = randomStr + IdUtil.fastSimpleUUID(); + } + if (!ReUtil.isMatch(RegexConstants.GENERAL_NAME, nickname)) { + nickname = source.toLowerCase() + randomStr; + } + user = new UserDO(); + user.setUsername(username); + user.setNickname(nickname); + user.setGender(GenderEnum.valueOf(authUser.getGender().name())); + user.setAvatar(authUser.getAvatar()); + user.setDeptId(SysConstants.SUPER_DEPT_ID); + Long userId = userService.add(user); + RoleDO role = roleService.getByCode(SysConstants.SUPER_ROLE_CODE); + userRoleService.assignRolesToUser(Collections.singletonList(role.getId()), userId); + userSocial = new UserSocialDO(); + userSocial.setUserId(userId); + userSocial.setSource(source); + userSocial.setOpenId(openId); + loginService.sendSecurityMsg(user); + } else { + user = BeanUtil.copyProperties(userService.getById(userSocial.getUserId()), UserDO.class); + } + loginService.checkUserStatus(user); + userSocial.setMetaJson(JSONUtil.toJsonStr(authUser)); + userSocial.setLastLoginTime(LocalDateTime.now()); + userSocialService.saveOrUpdate(userSocial); + // 执行登录 + String token = this.authCertificate(user, clientResp); + return LoginResp.builder().token(token).build(); + } + + private AuthRequest getAuthRequest(String source) { + try { + return authRequestFactory.get(source); + } catch (Exception e) { + throw new BadRequestException("暂不支持 [%s] 平台账号登录".formatted(source)); + } + } + + /** + * 获取认证信息 + * + * @param user 用户信息 + * @param clientResp 客户端信息 + * @return 认证信息 + */ + @Override + protected String authCertificate(UserDO user, ClientResp clientResp) { + return super.authCertificate(user, clientResp); + } + +} diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/model/req/SocialAuthReq.java b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/SocialAuthReq.java new file mode 100644 index 00000000..2eb749f6 --- /dev/null +++ b/continew-module-system/src/main/java/top/continew/admin/auth/model/req/SocialAuthReq.java @@ -0,0 +1,49 @@ +/* + * 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.auth.model.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * 第三方登录参数 + * + * @author KAI + * @since 2024/12/25 15:43 + */ +@Data +@Schema(description = "第三方登录参数") +public class SocialAuthReq extends AuthReq { + /** + * 第三方登录平台 + */ + @NotBlank(message = "第三方登录平台不能为空") + private String source; + + /** + * 第三方登录code + */ + @NotBlank(message = "第三方登录code不能为空") + private String code; + + /** + * 第三方登录state + */ + @NotBlank(message = "第三方登录state不能为空") + private String state; +} -- Gitee From 8590cdd5653d5ab06f1741c25692fbcab0bbbea2 Mon Sep 17 00:00:00 2001 From: KAI <1373639299@qq.com> Date: Wed, 25 Dec 2024 18:28:47 +0800 Subject: [PATCH 10/12] =?UTF-8?q?chore:=20=E7=AC=AC=E4=B8=89=E6=96=B9?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/top/continew/admin/auth/enums/AuthTypeEnum.java | 2 +- .../top/continew/admin/auth/handler/SocialAuthHandler.java | 1 - .../continew/admin/system/service/impl/ClientServiceImpl.java | 3 ++- .../top/continew/admin/controller/auth/AuthController.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java b/continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java index bb2e62f3..92edad69 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/enums/AuthTypeEnum.java @@ -44,7 +44,7 @@ public enum AuthTypeEnum implements BaseEnum { /** * 手机号 */ - PHONE("phone", "手机号", UiConstants.COLOR_DEFAULT), + PHONE("phone", "手机号", UiConstants.COLOR_SUCCESS), /** * 第三方授权 diff --git a/continew-module-system/src/main/java/top/continew/admin/auth/handler/SocialAuthHandler.java b/continew-module-system/src/main/java/top/continew/admin/auth/handler/SocialAuthHandler.java index e0987a21..1bd9a17f 100644 --- a/continew-module-system/src/main/java/top/continew/admin/auth/handler/SocialAuthHandler.java +++ b/continew-module-system/src/main/java/top/continew/admin/auth/handler/SocialAuthHandler.java @@ -60,7 +60,6 @@ import java.util.Collections; */ @Component @RequiredArgsConstructor - public class SocialAuthHandler extends AbstractAuthHandler implements AuthHandler { private final AuthRequestFactory authRequestFactory; private final UserSocialService userSocialService; diff --git a/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java b/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java index 98bddfdf..b813c0ee 100644 --- a/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java +++ b/continew-module-system/src/main/java/top/continew/admin/system/service/impl/ClientServiceImpl.java @@ -30,6 +30,7 @@ import top.continew.admin.system.model.req.ClientReq; import top.continew.admin.system.model.resp.ClientDetailResp; import top.continew.admin.system.model.resp.ClientResp; import top.continew.admin.system.service.ClientService; +import top.continew.starter.core.constant.StringConstants; import top.continew.starter.core.validation.ValidationUtils; import top.continew.starter.extension.crud.service.BaseServiceImpl; @@ -46,7 +47,7 @@ import java.util.List; public class ClientServiceImpl extends BaseServiceImpl implements ClientService { @Override protected void beforeAdd(ClientReq req) { - String clientId = DigestUtil.md5Hex(req.getClientKey(), req.getClientSecret()); + String clientId = DigestUtil.md5Hex(req.getClientKey() + StringConstants.COLON + req.getClientSecret()); req.setClientId(clientId); } diff --git a/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java b/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java index 3d03cb0e..99dd9fe9 100644 --- a/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java +++ b/continew-webapi/src/main/java/top/continew/admin/controller/auth/AuthController.java @@ -77,7 +77,7 @@ public class AuthController { // 获取并验证客户端信息 ClientResp clientResp = clientService.getClientByClientId(loginReq.getClientId()); - ValidationUtils.throwIfNull(clientResp, "客户端信息不存在,请检查客户端标识是否正确!"); + ValidationUtils.throwIfNull(clientResp, "客户端信息不存在,请检查客户端id是否正确!"); // 验证认证类型 ValidationUtils.throwIf(!clientResp.getAuthType().contains(authType), StrUtil.format("暂未授权此类型:{}", authType)); -- Gitee From 93c8956dd73cb77c904d8a778b1a0a6185525586 Mon Sep 17 00:00:00 2001 From: KAI <1373639299@qq.com> Date: Wed, 25 Dec 2024 18:29:19 +0800 Subject: [PATCH 11/12] =?UTF-8?q?chore:=20=E5=AE=A2=E6=88=B7=E7=AB=AF?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=88=9D=E5=A7=8B=E5=8C=96sql=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../db/changelog/mysql/main_data.sql | 27 +++++++++++++++++++ .../db/changelog/mysql/main_table.sql | 17 ++++++++++++ 2 files changed, 44 insertions(+) diff --git a/continew-webapi/src/main/resources/db/changelog/mysql/main_data.sql b/continew-webapi/src/main/resources/db/changelog/mysql/main_data.sql index 09cd2ecb..6f767215 100644 --- a/continew-webapi/src/main/resources/db/changelog/mysql/main_data.sql +++ b/continew-webapi/src/main/resources/db/changelog/mysql/main_data.sql @@ -188,3 +188,30 @@ VALUES (1, '开发环境', 'local_dev', 2, NULL, NULL, NULL, 'C:/continew-admin/data/file/', 'http://localhost:8000/file', '本地存储', b'1', 1, 1, 1, NOW()), (2, '生产环境', 'local_prod', 2, NULL, NULL, NULL, '../data/file/', 'http://api.continew.top/file', '本地存储', b'0', 2, 2, 1, NOW()); +-- 客户端管理管理菜单 +INSERT INTO `sys_menu` +(`title`, `parent_id`, `type`, `path`, `name`, `component`, `redirect`, `icon`, `is_external`, `is_cache`, `is_hidden`, `permission`, `sort`, `status`, `create_user`, `create_time`, `update_user`, `update_time`) +VALUES +( '客户端管理', 1000, 2, '/system/client', 'SystemClient', 'system/client/index', NULL, 'mobile', b'0', b'0', b'0', NULL, 9, 1, 1, NOW(), NULL, NULL); + +SET @parentId = LAST_INSERT_ID(); + +-- 客户端管理管理按钮 +INSERT INTO `sys_menu` +(`title`, `parent_id`, `type`, `path`, `name`, `component`, `redirect`, `icon`, `is_external`, `is_cache`, `is_hidden`, `permission`, `sort`, `status`, `create_user`, `create_time`, `update_user`, `update_time`) +VALUES + ('列表', @parentId, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:list', 1, 1, 1, NOW(), NULL, NULL), + ('详情', @parentId, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:detail', 2, 1, 1, NOW(), NULL, NULL), + ('新增', @parentId, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:add', 3, 1, 1, NOW(), NULL, NULL), + ('修改', @parentId, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:update', 4, 1, 1, NOW(), NULL, NULL), + ('删除', @parentId, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:delete', 5, 1, 1, NOW(), NULL, NULL), + ('导出', @parentId, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:export', 6, 1, 1, NOW(), NULL, NULL); +-- 插入客户端字典数据 +INSERT INTO `sys_dict` (`id`, `name`, `code`, `description`, `is_system`, `create_user`, `create_time`, `update_user`, `update_time`) VALUES (4, '客户端类型', 'client_type', NULL, b'0', 1, '2024-12-17 18:09:37', NULL, NULL); +INSERT INTO `sys_dict_item` (`id`, `label`, `value`, `color`, `sort`, `description`, `status`, `dict_id`, `create_user`, `create_time`, `update_user`, `update_time`) VALUES (659457796923719711, '桌面端', 'pc', 'blue', 999, NULL, 1, 4, 1, '2024-12-17 18:09:51', NULL, NULL); +INSERT INTO `sys_dict_item` (`id`, `label`, `value`, `color`, `sort`, `description`, `status`, `dict_id`, `create_user`, `create_time`, `update_user`, `update_time`) VALUES (659457877756346402, '安卓', 'android', '#148628', 999, NULL, 1, 4, 1, '2024-12-17 18:10:10', NULL, NULL); +INSERT INTO `sys_dict_item` (`id`, `label`, `value`, `color`, `sort`, `description`, `status`, `dict_id`, `create_user`, `create_time`, `update_user`, `update_time`) VALUES (659457929665052709, '小程序', 'xcx', '#7930AD', 999, NULL, 1, 4, 1, '2024-12-17 18:10:23', NULL, NULL); +-- 插入客户端数据 +INSERT INTO `sys_client` (`id`, `client_id`, `client_key`, `client_secret`, `auth_type`, `client_type`, `active_timeout`, `timeout`, `status`, `create_user`, `create_time`, `update_user`, `update_time`) VALUES (1, 'ef51c9a3e9046c4f2ea45142c8a8344a', 'pc', 'dd77ab1e353a027e0d60ce3b151e8642', '[\"account\", \"socialAuth\", \"email\", \"phone\"]', 'pc', 1800, 86400, 1, 1, now(), 1, '2024-12-25 17:41:36'); + + diff --git a/continew-webapi/src/main/resources/db/changelog/mysql/main_table.sql b/continew-webapi/src/main/resources/db/changelog/mysql/main_table.sql index 95e77b8f..69fac008 100644 --- a/continew-webapi/src/main/resources/db/changelog/mysql/main_table.sql +++ b/continew-webapi/src/main/resources/db/changelog/mysql/main_table.sql @@ -294,3 +294,20 @@ CREATE TABLE IF NOT EXISTS `sys_file` ( INDEX `idx_create_user`(`create_user`), INDEX `idx_update_user`(`update_user`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文件表'; + +CREATE TABLE IF NOT EXISTS `sys_client` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `client_id` varchar(50) NOT NULL COMMENT '客户端ID', + `client_key` varchar(255) NOT NULL COMMENT '客户端Key', + `client_secret` varchar(255) NOT NULL COMMENT '客户端秘钥', + `auth_type` json DEFAULT NULL COMMENT '授权类型', + `client_type` varchar(50) DEFAULT NULL COMMENT '客户端类型', + `active_timeout` int DEFAULT '-1' COMMENT 'Token最低活跃频率(-1为不限制)', + `timeout` int DEFAULT '2592000' COMMENT 'Token有效期(默认30天,单位:秒)', + `status` tinyint(1) UNSIGNED NOT NULL COMMENT '状态(1:启用;2:禁用)', + `create_user` bigint(20) NOT NULL COMMENT '创建人', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_user` bigint(20) DEFAULT NULL COMMENT '修改人', + `update_time` datetime DEFAULT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户端管理'; -- Gitee From 1de2945bd5a97527a0b0b50619e1040d3b2af0b9 Mon Sep 17 00:00:00 2001 From: KAI <1373639299@qq.com> Date: Wed, 25 Dec 2024 18:49:46 +0800 Subject: [PATCH 12/12] =?UTF-8?q?revert:=20dev=E9=85=8D=E7=BD=AE=E5=9B=9E?= =?UTF-8?q?=E6=BB=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/config/application-dev.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/continew-webapi/src/main/resources/config/application-dev.yml b/continew-webapi/src/main/resources/config/application-dev.yml index 4e62a950..119d8424 100644 --- a/continew-webapi/src/main/resources/config/application-dev.yml +++ b/continew-webapi/src/main/resources/config/application-dev.yml @@ -1,7 +1,7 @@ --- ### 项目配置 project: # URL(跨域配置默认放行此 URL,第三方登录回调默认使用此 URL 为前缀,请注意更改为你实际的前端 URL) - url: http://120.46.172.119:1234 + url: http://localhost:5173 --- ### 服务器配置 server: @@ -203,8 +203,8 @@ justauth: enabled: true type: GITEE: - client-id: a0ef43747707a28fe0c01d901496af5a0ac9d34274793103e7baa043c495e60a - client-secret: eb29099d5d1942088b87ded007cb14e4d216aa79957f944920ab4bdd1bb39b67 + client-id: 5d271b7f638941812aaf8bfc2e2f08f06d6235ef934e0e39537e2364eb8452c4 + client-secret: 1f7d08**********5b7**********29e redirect-uri: ${project.url}/social/callback?source=gitee GITHUB: client-id: 38080dad08cfbdfacca9 -- Gitee