mirror of
				https://github.com/continew-org/continew-admin.git
				synced 2025-11-04 10:57:10 +08:00 
			
		
		
		
	Merge branch 'jskils-fix-last-commit' into dev
This commit is contained in:
		@@ -99,10 +99,24 @@ public class LoginUser implements Serializable {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    private LocalDateTime loginTime;
 | 
					    private LocalDateTime loginTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public LoginUser(Set<String> permissions, Set<String> roleCodes, Set<RoleDTO> roles) {
 | 
					    /**
 | 
				
			||||||
 | 
					     * 最后一次修改密码时间
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private LocalDateTime pwdResetTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 登录时系统设置的密码过期天数
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private Integer passwordExpirationDays;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public LoginUser(Set<String> permissions,
 | 
				
			||||||
 | 
					                     Set<String> roleCodes,
 | 
				
			||||||
 | 
					                     Set<RoleDTO> roles,
 | 
				
			||||||
 | 
					                     Integer passwordExpirationDays) {
 | 
				
			||||||
        this.permissions = permissions;
 | 
					        this.permissions = permissions;
 | 
				
			||||||
        this.roleCodes = roleCodes;
 | 
					        this.roleCodes = roleCodes;
 | 
				
			||||||
        this.roles = roles;
 | 
					        this.roles = roles;
 | 
				
			||||||
 | 
					        this.passwordExpirationDays = passwordExpirationDays;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -116,4 +130,21 @@ public class LoginUser implements Serializable {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        return roleCodes.contains(SysConstants.ADMIN_ROLE_CODE);
 | 
					        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());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -16,9 +16,17 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package top.continew.admin.auth.config.satoken;
 | 
					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 cn.dev33.satoken.stp.StpInterface;
 | 
				
			||||||
 | 
					import lombok.RequiredArgsConstructor;
 | 
				
			||||||
import org.springframework.context.annotation.Bean;
 | 
					import org.springframework.context.annotation.Bean;
 | 
				
			||||||
import org.springframework.context.annotation.Configuration;
 | 
					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 配置
 | 
					 * Sa-Token 配置
 | 
				
			||||||
@@ -27,8 +35,12 @@ import org.springframework.context.annotation.Configuration;
 | 
				
			|||||||
 * @since 2022/12/19 22:13
 | 
					 * @since 2022/12/19 22:13
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@Configuration
 | 
					@Configuration
 | 
				
			||||||
 | 
					@RequiredArgsConstructor
 | 
				
			||||||
public class SaTokenConfiguration {
 | 
					public class SaTokenConfiguration {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final SaTokenExtensionProperties properties;
 | 
				
			||||||
 | 
					    private final LoginPasswordProperties loginPasswordProperties;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Sa-Token 权限认证配置
 | 
					     * Sa-Token 权限认证配置
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@@ -36,4 +48,20 @@ public class SaTokenConfiguration {
 | 
				
			|||||||
    public StpInterface stpInterface() {
 | 
					    public StpInterface stpInterface() {
 | 
				
			||||||
        return new SaTokenPermissionImpl();
 | 
					        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(), "密码已过期,请修改密码");
 | 
				
			||||||
 | 
					            }));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,6 +68,8 @@ import java.time.LocalDateTime;
 | 
				
			|||||||
import java.util.*;
 | 
					import java.util.*;
 | 
				
			||||||
import java.util.concurrent.CompletableFuture;
 | 
					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);
 | 
					            .listRoleCodeByUserId(userId), threadPoolTaskExecutor);
 | 
				
			||||||
        CompletableFuture<Set<RoleDTO>> roleFuture = CompletableFuture.supplyAsync(() -> roleService
 | 
					        CompletableFuture<Set<RoleDTO>> roleFuture = CompletableFuture.supplyAsync(() -> roleService
 | 
				
			||||||
            .listByUserId(userId), threadPoolTaskExecutor);
 | 
					            .listByUserId(userId), threadPoolTaskExecutor);
 | 
				
			||||||
 | 
					        CompletableFuture<Integer> passwordExpirationDaysFuture = CompletableFuture.supplyAsync(() -> optionService
 | 
				
			||||||
 | 
					            .getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name()));
 | 
				
			||||||
        CompletableFuture.allOf(permissionFuture, roleCodeFuture, roleFuture);
 | 
					        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);
 | 
					        BeanUtil.copyProperties(user, loginUser);
 | 
				
			||||||
        return LoginHelper.login(loginUser);
 | 
					        return LoginHelper.login(loginUser);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,6 @@ import top.continew.starter.data.mybatis.plus.service.IService;
 | 
				
			|||||||
import top.continew.starter.extension.crud.service.BaseService;
 | 
					import top.continew.starter.extension.crud.service.BaseService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
import java.time.LocalDateTime;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -90,14 +89,6 @@ public interface UserService extends BaseService<UserResp, UserDetailResp, UserQ
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    void updatePassword(String oldPassword, String newPassword, Long id);
 | 
					    void updatePassword(String oldPassword, String newPassword, Long id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 密码是否已过期
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param pwdResetTime 上次重置密码时间
 | 
					 | 
				
			||||||
     * @return 是否过期
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    boolean isPasswordExpired(LocalDateTime pwdResetTime);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 修改手机号
 | 
					     * 修改手机号
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package top.continew.admin.system.service.impl;
 | 
					package top.continew.admin.system.service.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.dev33.satoken.stp.StpUtil;
 | 
				
			||||||
import cn.hutool.core.bean.BeanUtil;
 | 
					import cn.hutool.core.bean.BeanUtil;
 | 
				
			||||||
import cn.hutool.core.collection.CollUtil;
 | 
					import cn.hutool.core.collection.CollUtil;
 | 
				
			||||||
import cn.hutool.core.img.ImgUtil;
 | 
					import cn.hutool.core.img.ImgUtil;
 | 
				
			||||||
@@ -210,20 +211,8 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
 | 
				
			|||||||
        baseMapper.updateById(user);
 | 
					        baseMapper.updateById(user);
 | 
				
			||||||
        // 保存历史密码
 | 
					        // 保存历史密码
 | 
				
			||||||
        userPasswordHistoryService.add(id, password, passwordRepetitionTimes);
 | 
					        userPasswordHistoryService.add(id, password, passwordRepetitionTimes);
 | 
				
			||||||
    }
 | 
					        // 修改后登出
 | 
				
			||||||
 | 
					        StpUtil.logout();
 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public boolean isPasswordExpired(LocalDateTime pwdResetTime) {
 | 
					 | 
				
			||||||
        // 永久有效
 | 
					 | 
				
			||||||
        int passwordExpirationDays = optionService.getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name());
 | 
					 | 
				
			||||||
        if (passwordExpirationDays <= SysConstants.NO) {
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // 初始密码也提示修改
 | 
					 | 
				
			||||||
        if (pwdResetTime == null) {
 | 
					 | 
				
			||||||
            return true;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return pwdResetTime.plusDays(passwordExpirationDays).isBefore(LocalDateTime.now());
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -128,7 +128,7 @@ public class AuthController {
 | 
				
			|||||||
        UserInfoResp userInfoResp = BeanUtil.copyProperties(userDetailResp, UserInfoResp.class);
 | 
					        UserInfoResp userInfoResp = BeanUtil.copyProperties(userDetailResp, UserInfoResp.class);
 | 
				
			||||||
        userInfoResp.setPermissions(loginUser.getPermissions());
 | 
					        userInfoResp.setPermissions(loginUser.getPermissions());
 | 
				
			||||||
        userInfoResp.setRoles(loginUser.getRoleCodes());
 | 
					        userInfoResp.setRoles(loginUser.getRoleCodes());
 | 
				
			||||||
        userInfoResp.setPwdExpired(userService.isPasswordExpired(userDetailResp.getPwdResetTime()));
 | 
					        userInfoResp.setPwdExpired(loginUser.isPasswordExpired());
 | 
				
			||||||
        return R.ok(userInfoResp);
 | 
					        return R.ok(userInfoResp);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -190,6 +190,16 @@ cosid:
 | 
				
			|||||||
        machine-bit: 3
 | 
					        machine-bit: 3
 | 
				
			||||||
        sequence-bit: 9
 | 
					        sequence-bit: 9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- ### 认证配置
 | 
				
			||||||
 | 
					auth:
 | 
				
			||||||
 | 
					  ## 密码配置
 | 
				
			||||||
 | 
					  password:
 | 
				
			||||||
 | 
					    excludes:
 | 
				
			||||||
 | 
					      - /auth/route
 | 
				
			||||||
 | 
					      - /auth/user/info
 | 
				
			||||||
 | 
					      - /auth/logout
 | 
				
			||||||
 | 
					      - /system/user/password
 | 
				
			||||||
 | 
					
 | 
				
			||||||
--- ### 服务器配置
 | 
					--- ### 服务器配置
 | 
				
			||||||
server:
 | 
					server:
 | 
				
			||||||
  servlet:
 | 
					  servlet:
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user