diff --git a/continew-admin-common/src/main/java/top/continew/admin/common/model/dto/LoginUser.java b/continew-admin-common/src/main/java/top/continew/admin/common/model/dto/LoginUser.java index 2db75620..5f4b2c8e 100644 --- a/continew-admin-common/src/main/java/top/continew/admin/common/model/dto/LoginUser.java +++ b/continew-admin-common/src/main/java/top/continew/admin/common/model/dto/LoginUser.java @@ -99,10 +99,24 @@ public class LoginUser implements Serializable { */ private LocalDateTime loginTime; - public LoginUser(Set permissions, Set roleCodes, Set roles) { + /** + * 最后一次修改密码时间 + */ + private LocalDateTime pwdResetTime; + + /** + * 登录时系统设置的密码过期天数 + */ + private Integer passwordExpirationDays; + + public LoginUser(Set permissions, + Set roleCodes, + Set roles, + Integer passwordExpirationDays) { this.permissions = permissions; this.roleCodes = roleCodes; this.roles = roles; + this.passwordExpirationDays = passwordExpirationDays; } /** @@ -116,4 +130,21 @@ public class LoginUser implements Serializable { } return roleCodes.contains(SysConstants.ADMIN_ROLE_CODE); } + + /** + * 密码是否已过期 + * + * @return 是否过期 + */ + public boolean isPasswordExpired() { + // 永久有效 + if (this.passwordExpirationDays == null || this.passwordExpirationDays <= SysConstants.NO) { + return false; + } + // 初始密码(第三方登录用户)暂不提示修改 + if (this.pwdResetTime == null) { + return false; + } + return this.pwdResetTime.plusDays(this.passwordExpirationDays).isBefore(LocalDateTime.now()); + } } diff --git a/continew-admin-system/src/main/java/top/continew/admin/auth/config/satoken/LoginPasswordProperties.java b/continew-admin-system/src/main/java/top/continew/admin/auth/config/satoken/LoginPasswordProperties.java new file mode 100644 index 00000000..27b849f1 --- /dev/null +++ b/continew-admin-system/src/main/java/top/continew/admin/auth/config/satoken/LoginPasswordProperties.java @@ -0,0 +1,38 @@ +/* + * 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.satoken; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 密码配置属性 + * + * @author Charles7c + * @since 2024/6/15 22:15 + */ +@Data +@Component +@ConfigurationProperties(prefix = "auth.password") +public class LoginPasswordProperties { + + /** + * 排除(放行)路径配置 + */ + private String[] excludes = new String[0]; +} \ No newline at end of file diff --git a/continew-admin-system/src/main/java/top/continew/admin/auth/config/satoken/SaTokenConfiguration.java b/continew-admin-system/src/main/java/top/continew/admin/auth/config/satoken/SaTokenConfiguration.java index 157b8548..5f6ba3aa 100644 --- a/continew-admin-system/src/main/java/top/continew/admin/auth/config/satoken/SaTokenConfiguration.java +++ b/continew-admin-system/src/main/java/top/continew/admin/auth/config/satoken/SaTokenConfiguration.java @@ -16,9 +16,17 @@ package top.continew.admin.auth.config.satoken; +import cn.dev33.satoken.interceptor.SaInterceptor; +import cn.dev33.satoken.router.SaRouter; import cn.dev33.satoken.stp.StpInterface; +import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import top.continew.admin.common.model.dto.LoginUser; +import top.continew.admin.common.util.helper.LoginHelper; +import top.continew.starter.auth.satoken.autoconfigure.SaTokenExtensionProperties; +import top.continew.starter.core.constant.StringConstants; +import top.continew.starter.core.util.validate.CheckUtils; /** * Sa-Token 配置 @@ -27,8 +35,12 @@ import org.springframework.context.annotation.Configuration; * @since 2022/12/19 22:13 */ @Configuration +@RequiredArgsConstructor public class SaTokenConfiguration { + private final SaTokenExtensionProperties properties; + private final LoginPasswordProperties loginPasswordProperties; + /** * Sa-Token 权限认证配置 */ @@ -36,4 +48,20 @@ public class SaTokenConfiguration { public StpInterface stpInterface() { return new SaTokenPermissionImpl(); } + + /** + * SaToken 拦截器配置 + */ + @Bean + public SaInterceptor saInterceptor() { + return new SaInterceptor(handle -> SaRouter.match(StringConstants.PATH_PATTERN) + .notMatch(properties.getSecurity().getExcludes()) + .check(r -> { + LoginUser loginUser = LoginHelper.getLoginUser(); + if (SaRouter.isMatchCurrURI(loginPasswordProperties.getExcludes())) { + return; + } + CheckUtils.throwIf(loginUser.isPasswordExpired(), "密码已过期,请修改密码"); + })); + } } diff --git a/continew-admin-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java b/continew-admin-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java index 9650535b..c3dc5f3c 100644 --- a/continew-admin-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java +++ b/continew-admin-system/src/main/java/top/continew/admin/auth/service/impl/LoginServiceImpl.java @@ -68,6 +68,8 @@ import java.time.LocalDateTime; import java.util.*; import java.util.concurrent.CompletableFuture; +import static top.continew.admin.system.enums.PasswordPolicyEnum.PASSWORD_EXPIRATION_DAYS; + /** * 登录业务实现 * @@ -209,8 +211,11 @@ public class LoginServiceImpl implements LoginService { .listRoleCodeByUserId(userId), threadPoolTaskExecutor); CompletableFuture> roleFuture = CompletableFuture.supplyAsync(() -> roleService .listByUserId(userId), threadPoolTaskExecutor); + CompletableFuture passwordExpirationDaysFuture = CompletableFuture.supplyAsync(() -> optionService + .getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name())); CompletableFuture.allOf(permissionFuture, roleCodeFuture, roleFuture); - LoginUser loginUser = new LoginUser(permissionFuture.join(), roleCodeFuture.join(), roleFuture.join()); + LoginUser loginUser = new LoginUser(permissionFuture.join(), roleCodeFuture.join(), roleFuture + .join(), passwordExpirationDaysFuture.join()); BeanUtil.copyProperties(user, loginUser); return LoginHelper.login(loginUser); } diff --git a/continew-admin-system/src/main/java/top/continew/admin/system/service/UserService.java b/continew-admin-system/src/main/java/top/continew/admin/system/service/UserService.java index 5836b473..663e9510 100644 --- a/continew-admin-system/src/main/java/top/continew/admin/system/service/UserService.java +++ b/continew-admin-system/src/main/java/top/continew/admin/system/service/UserService.java @@ -29,7 +29,6 @@ import top.continew.starter.data.mybatis.plus.service.IService; import top.continew.starter.extension.crud.service.BaseService; import java.io.IOException; -import java.time.LocalDateTime; import java.util.List; /** @@ -90,14 +89,6 @@ public interface UserService extends BaseService