设置时间,过期限制学员登录,但是不限制系统用户
This commit is contained in:
parent
52b3a345bf
commit
7896c7c5c2
|
|
@ -98,17 +98,24 @@ const user = {
|
||||||
commit('SET_NAME', user.userName)
|
commit('SET_NAME', user.userName)
|
||||||
commit('SET_NICK_NAME', user.nickName)
|
commit('SET_NICK_NAME', user.nickName)
|
||||||
commit('SET_AVATAR', avatar)
|
commit('SET_AVATAR', avatar)
|
||||||
/* 初始密码提示 */
|
|
||||||
if(res.isDefaultModifyPwd) {
|
// 检查是否是学员角色
|
||||||
MessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
const isStudentRole = res.roles && res.roles.some(role => role === 'student' || (typeof role === 'string' && role.includes('学员')))
|
||||||
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
|
|
||||||
}).catch(() => {})
|
// 学员角色不需要修改密码提示
|
||||||
}
|
if (!isStudentRole) {
|
||||||
/* 过期密码提示 */
|
/* 初始密码提示 */
|
||||||
if(!res.isDefaultModifyPwd && res.isPasswordExpired) {
|
if(res.isDefaultModifyPwd) {
|
||||||
MessageBox.confirm('您的密码已过期,请尽快修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
MessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||||
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
|
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
|
||||||
}).catch(() => {})
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
/* 过期密码提示 */
|
||||||
|
if(!res.isDefaultModifyPwd && res.isPasswordExpired) {
|
||||||
|
MessageBox.confirm('您的密码已过期,请尽快修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||||
|
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
resolve(res)
|
resolve(res)
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
|
|
||||||
|
|
@ -84,17 +84,21 @@ service.interceptors.response.use(res => {
|
||||||
return res.data
|
return res.data
|
||||||
}
|
}
|
||||||
if (code === 401) {
|
if (code === 401) {
|
||||||
if (!isRelogin.show) {
|
// 登录接口返回401时,不应该显示"登录状态已过期"提示,因为用户还没有登录
|
||||||
|
const isLoginRequest = res.config && res.config.url &&
|
||||||
|
(res.config.url.includes('/login') || res.config.url.includes('/student/login') || res.config.url.includes('/register'))
|
||||||
|
|
||||||
|
if (!isLoginRequest && !isRelogin.show) {
|
||||||
isRelogin.show = true
|
isRelogin.show = true
|
||||||
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||||
isRelogin.show = false
|
isRelogin.show = false
|
||||||
store.dispatch('LogOut').then(() => {
|
store.dispatch('LogOut').then(() => {
|
||||||
location.href = '/index'
|
location.href = '/index'
|
||||||
})
|
})
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
isRelogin.show = false
|
isRelogin.show = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
|
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
|
||||||
} else if (code === 500) {
|
} else if (code === 500) {
|
||||||
Message({ message: msg, type: 'error' })
|
Message({ message: msg, type: 'error' })
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ddnai.common.constant.Constants;
|
import com.ddnai.common.constant.Constants;
|
||||||
import com.ddnai.common.core.domain.AjaxResult;
|
import com.ddnai.common.core.domain.AjaxResult;
|
||||||
|
import com.ddnai.common.exception.ServiceException;
|
||||||
import com.ddnai.common.core.domain.entity.SysMenu;
|
import com.ddnai.common.core.domain.entity.SysMenu;
|
||||||
import com.ddnai.common.core.domain.entity.SysUser;
|
import com.ddnai.common.core.domain.entity.SysUser;
|
||||||
import com.ddnai.common.core.domain.model.LoginBody;
|
import com.ddnai.common.core.domain.model.LoginBody;
|
||||||
|
|
@ -165,6 +166,16 @@ public class SysLoginController
|
||||||
// 根据学员编号查找用户(使用user_name作为学员编号)
|
// 根据学员编号查找用户(使用user_name作为学员编号)
|
||||||
SysUser user = userService.selectUserByUserName(studentNo.trim());
|
SysUser user = userService.selectUserByUserName(studentNo.trim());
|
||||||
|
|
||||||
|
// 检查系统有效时间(系统管理员不受限制)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
loginService.validateSystemExpireTime(studentNo, user != null ? user.getUserId() : null);
|
||||||
|
}
|
||||||
|
catch (ServiceException e)
|
||||||
|
{
|
||||||
|
return AjaxResult.error(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
// 如果找不到,返回错误
|
// 如果找不到,返回错误
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,18 @@ public class DataScopeAspect
|
||||||
protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope)
|
protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope)
|
||||||
{
|
{
|
||||||
// 获取当前的用户
|
// 获取当前的用户
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
LoginUser loginUser = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
loginUser = SecurityUtils.getLoginUser();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// 如果无法获取登录用户(例如匿名访问或登录过程中),则跳过数据权限过滤
|
||||||
|
// 这种情况通常发生在登录接口、注册接口等匿名访问的场景
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotNull(loginUser))
|
if (StringUtils.isNotNull(loginUser))
|
||||||
{
|
{
|
||||||
SysUser currentUser = loginUser.getUser();
|
SysUser currentUser = loginUser.getUser();
|
||||||
|
|
|
||||||
|
|
@ -134,8 +134,8 @@ public class SecurityConfig
|
||||||
// 注解标记允许匿名访问的url
|
// 注解标记允许匿名访问的url
|
||||||
.authorizeHttpRequests((requests) -> {
|
.authorizeHttpRequests((requests) -> {
|
||||||
permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll());
|
permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll());
|
||||||
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
|
// 对于登录login 学员登录student/login 注册register 验证码captchaImage 允许匿名访问
|
||||||
requests.antMatchers("/login", "/register", "/captchaImage").permitAll()
|
requests.antMatchers("/login", "/student/login", "/register", "/captchaImage").permitAll()
|
||||||
// API接口,可匿名访问
|
// API接口,可匿名访问
|
||||||
.antMatchers("/api/**").permitAll()
|
.antMatchers("/api/**").permitAll()
|
||||||
// 静态资源,可匿名访问
|
// 静态资源,可匿名访问
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
package com.ddnai.framework.web.service;
|
package com.ddnai.framework.web.service;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
|
|
@ -25,6 +28,7 @@ import com.ddnai.common.utils.ip.IpUtils;
|
||||||
import com.ddnai.framework.manager.AsyncManager;
|
import com.ddnai.framework.manager.AsyncManager;
|
||||||
import com.ddnai.framework.manager.factory.AsyncFactory;
|
import com.ddnai.framework.manager.factory.AsyncFactory;
|
||||||
import com.ddnai.framework.security.context.AuthenticationContextHolder;
|
import com.ddnai.framework.security.context.AuthenticationContextHolder;
|
||||||
|
import com.ddnai.common.core.domain.entity.SysUser;
|
||||||
import com.ddnai.system.service.ISysConfigService;
|
import com.ddnai.system.service.ISysConfigService;
|
||||||
import com.ddnai.system.service.ISysUserService;
|
import com.ddnai.system.service.ISysUserService;
|
||||||
|
|
||||||
|
|
@ -36,6 +40,8 @@ import com.ddnai.system.service.ISysUserService;
|
||||||
@Component
|
@Component
|
||||||
public class SysLoginService
|
public class SysLoginService
|
||||||
{
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SysLoginService.class);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TokenService tokenService;
|
private TokenService tokenService;
|
||||||
|
|
||||||
|
|
@ -135,6 +141,8 @@ public class SysLoginService
|
||||||
*/
|
*/
|
||||||
public void loginPreCheck(String username, String password)
|
public void loginPreCheck(String username, String password)
|
||||||
{
|
{
|
||||||
|
// 检查系统有效时间(系统管理员不受限制)
|
||||||
|
validateSystemExpireTime(username, null);
|
||||||
// 用户名或密码为空 错误
|
// 用户名或密码为空 错误
|
||||||
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
|
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
|
||||||
{
|
{
|
||||||
|
|
@ -164,6 +172,91 @@ public class SysLoginService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验系统有效时间
|
||||||
|
* 检查 system.top 参数,如果存在且截止时间小于当前时间,则阻止登录
|
||||||
|
* 系统管理员(用户ID=1)不受此限制
|
||||||
|
*
|
||||||
|
* @param username 用户名(用于记录日志)
|
||||||
|
* @param userId 用户ID(如果为1则跳过检查,为null时通过用户名查找用户判断)
|
||||||
|
*/
|
||||||
|
public void validateSystemExpireTime(String username, Long userId)
|
||||||
|
{
|
||||||
|
// 如果提供了用户ID,判断是否是系统管理员
|
||||||
|
if (userId != null)
|
||||||
|
{
|
||||||
|
if (com.ddnai.common.utils.SecurityUtils.isAdmin(userId))
|
||||||
|
{
|
||||||
|
// 系统管理员不受限制,直接返回
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (StringUtils.isNotEmpty(username))
|
||||||
|
{
|
||||||
|
// 如果没有提供用户ID,通过用户名查找用户判断是否是系统管理员
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SysUser user = userService.selectUserByUserName(username);
|
||||||
|
if (user != null && user.isAdmin())
|
||||||
|
{
|
||||||
|
// 系统管理员不受限制,直接返回
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// 查找用户失败,继续检查系统有效时间
|
||||||
|
log.debug("查找用户失败,继续检查系统有效时间: {}", username, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取系统有效时间配置
|
||||||
|
String expireTimeStr = configService.selectConfigByKey("system.top");
|
||||||
|
if (StringUtils.isNotEmpty(expireTimeStr))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 解析日期时间(支持 yyyy-MM-dd 和 yyyy-MM-dd HH:mm:ss 格式)
|
||||||
|
Date expireTime = DateUtils.parseDate(expireTimeStr);
|
||||||
|
Date now = DateUtils.getNowDate();
|
||||||
|
|
||||||
|
// 如果配置的是日期格式(yyyy-MM-dd),则将其转换为当天的结束时间(23:59:59)
|
||||||
|
// 这样当天仍然可以登录
|
||||||
|
if (expireTime != null)
|
||||||
|
{
|
||||||
|
// 如果配置值只包含日期部分(长度为10),则认为是日期格式
|
||||||
|
if (expireTimeStr.trim().length() == 10)
|
||||||
|
{
|
||||||
|
// 将日期设置为当天的23:59:59
|
||||||
|
java.util.Calendar cal = java.util.Calendar.getInstance();
|
||||||
|
cal.setTime(expireTime);
|
||||||
|
cal.set(java.util.Calendar.HOUR_OF_DAY, 23);
|
||||||
|
cal.set(java.util.Calendar.MINUTE, 59);
|
||||||
|
cal.set(java.util.Calendar.SECOND, 59);
|
||||||
|
cal.set(java.util.Calendar.MILLISECOND, 999);
|
||||||
|
expireTime = cal.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果当前时间在过期时间之后,则系统已过期
|
||||||
|
if (now.after(expireTime))
|
||||||
|
{
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, "系统有效时间已过期"));
|
||||||
|
throw new ServiceException("系统出现问题,请联系管理员");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ServiceException e)
|
||||||
|
{
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// 日期解析失败,记录日志但不阻止登录
|
||||||
|
log.warn("系统有效时间配置解析失败: {}", expireTimeStr, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 记录登录信息
|
* 记录登录信息
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user