update 同步ruoyi
commit
7bacfd9c4c
|
|
@ -19,7 +19,6 @@ import com.ruoyi.common.redis.utils.RedisUtils;
|
||||||
import com.ruoyi.common.satoken.utils.LoginHelper;
|
import com.ruoyi.common.satoken.utils.LoginHelper;
|
||||||
import com.ruoyi.system.api.RemoteLogService;
|
import com.ruoyi.system.api.RemoteLogService;
|
||||||
import com.ruoyi.system.api.RemoteUserService;
|
import com.ruoyi.system.api.RemoteUserService;
|
||||||
import com.ruoyi.system.api.domain.SysLogininfor;
|
|
||||||
import com.ruoyi.system.api.domain.SysUser;
|
import com.ruoyi.system.api.domain.SysUser;
|
||||||
import com.ruoyi.system.api.model.LoginUser;
|
import com.ruoyi.system.api.model.LoginUser;
|
||||||
import com.ruoyi.system.api.model.XcxLoginUser;
|
import com.ruoyi.system.api.model.XcxLoginUser;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
package com.ruoyi.auth.service;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import com.ruoyi.common.core.constant.CacheConstants;
|
||||||
|
import com.ruoyi.common.core.constant.Constants;
|
||||||
|
import com.ruoyi.common.core.exception.ServiceException;
|
||||||
|
import com.ruoyi.common.redis.service.RedisService;
|
||||||
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
|
import com.ruoyi.system.api.domain.SysUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录密码方法
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SysPasswordService
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private RedisService redisService;
|
||||||
|
|
||||||
|
private int maxRetryCount = CacheConstants.passwordMaxRetryCount;
|
||||||
|
|
||||||
|
private Long lockTime = CacheConstants.passwordLockTime;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SysRecordLogService recordLogService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录账户密码错误次数缓存键名
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
* @return 缓存键key
|
||||||
|
*/
|
||||||
|
private String getCacheKey(String username)
|
||||||
|
{
|
||||||
|
return CacheConstants.PWD_ERR_CNT_KEY + username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validate(SysUser user, String password)
|
||||||
|
{
|
||||||
|
String username = user.getUserName();
|
||||||
|
|
||||||
|
Integer retryCount = redisService.getCacheObject(getCacheKey(username));
|
||||||
|
|
||||||
|
if (retryCount == null)
|
||||||
|
{
|
||||||
|
retryCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retryCount >= Integer.valueOf(maxRetryCount).intValue())
|
||||||
|
{
|
||||||
|
String errMsg = String.format("密码输入错误%s次,帐户锁定%s分钟", maxRetryCount, lockTime);
|
||||||
|
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL,errMsg);
|
||||||
|
throw new ServiceException(errMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!matches(user, password))
|
||||||
|
{
|
||||||
|
retryCount = retryCount + 1;
|
||||||
|
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, String.format("密码输入错误%s次", retryCount));
|
||||||
|
redisService.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
|
||||||
|
throw new ServiceException("用户不存在/密码错误");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clearLoginRecordCache(username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches(SysUser user, String rawPassword)
|
||||||
|
{
|
||||||
|
return SecurityUtils.matchesPassword(rawPassword, user.getPassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearLoginRecordCache(String loginName)
|
||||||
|
{
|
||||||
|
if (redisService.hasKey(getCacheKey(loginName)))
|
||||||
|
{
|
||||||
|
redisService.deleteObject(getCacheKey(loginName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.ruoyi.auth.service;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import com.ruoyi.common.core.constant.Constants;
|
||||||
|
import com.ruoyi.common.core.constant.SecurityConstants;
|
||||||
|
import com.ruoyi.common.core.utils.ServletUtils;
|
||||||
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.core.utils.ip.IpUtils;
|
||||||
|
import com.ruoyi.system.api.RemoteLogService;
|
||||||
|
import com.ruoyi.system.api.domain.SysLogininfor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录日志方法
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SysRecordLogService
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private RemoteLogService remoteLogService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录登录信息
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
* @param status 状态
|
||||||
|
* @param message 消息内容
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public void recordLogininfor(String username, String status, String message)
|
||||||
|
{
|
||||||
|
SysLogininfor logininfor = new SysLogininfor();
|
||||||
|
logininfor.setUserName(username);
|
||||||
|
logininfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
|
||||||
|
logininfor.setMsg(message);
|
||||||
|
// 日志状态
|
||||||
|
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
|
||||||
|
{
|
||||||
|
logininfor.setStatus(Constants.LOGIN_SUCCESS_STATUS);
|
||||||
|
}
|
||||||
|
else if (Constants.LOGIN_FAIL.equals(status))
|
||||||
|
{
|
||||||
|
logininfor.setStatus(Constants.LOGIN_FAIL_STATUS);
|
||||||
|
}
|
||||||
|
remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.ruoyi.common.core.constant;
|
package com.ruoyi.common.core.constant;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 缓存的key 常量
|
* 缓存常量信息
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
|
|
@ -22,6 +22,16 @@ public interface CacheConstants {
|
||||||
*/
|
*/
|
||||||
String LOGINID_JOIN_CODE = ":";
|
String LOGINID_JOIN_CODE = ":";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码最大错误次数
|
||||||
|
*/
|
||||||
|
int passwordMaxRetryCount = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码锁定时间,默认10(分钟)
|
||||||
|
*/
|
||||||
|
long passwordLockTime = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登陆错误 redis key
|
* 登陆错误 redis key
|
||||||
*/
|
*/
|
||||||
|
|
@ -37,4 +47,23 @@ public interface CacheConstants {
|
||||||
*/
|
*/
|
||||||
Integer LOGIN_ERROR_LIMIT_TIME = 10;
|
Integer LOGIN_ERROR_LIMIT_TIME = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码 redis key
|
||||||
|
*/
|
||||||
|
String CAPTCHA_CODE_KEY = "captcha_codes:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数管理 cache key
|
||||||
|
*/
|
||||||
|
String SYS_CONFIG_KEY = "sys_config:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典管理 cache key
|
||||||
|
*/
|
||||||
|
String SYS_DICT_KEY = "sys_dict:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录账户密码错误次数 redis key
|
||||||
|
*/
|
||||||
|
String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,11 +66,6 @@ public interface Constants {
|
||||||
*/
|
*/
|
||||||
String LOGIN_FAIL = "Error";
|
String LOGIN_FAIL = "Error";
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证码 redis key
|
|
||||||
*/
|
|
||||||
String CAPTCHA_CODE_KEY = "captcha_codes:";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证码有效期(分钟)
|
* 验证码有效期(分钟)
|
||||||
*/
|
*/
|
||||||
|
|
@ -81,14 +76,4 @@ public interface Constants {
|
||||||
*/
|
*/
|
||||||
String REPEAT_SUBMIT_KEY = "repeat_submit:";
|
String REPEAT_SUBMIT_KEY = "repeat_submit:";
|
||||||
|
|
||||||
/**
|
|
||||||
* 参数管理 cache key
|
|
||||||
*/
|
|
||||||
String SYS_CONFIG_KEY = "sys_config:";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字典管理 cache key
|
|
||||||
*/
|
|
||||||
String SYS_DICT_KEY = "sys_dict:";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ public class ValidateCodeServiceImpl implements ValidateCodeService {
|
||||||
if (StringUtils.isEmpty(uuid)) {
|
if (StringUtils.isEmpty(uuid)) {
|
||||||
throw new CaptchaExpireException();
|
throw new CaptchaExpireException();
|
||||||
}
|
}
|
||||||
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
|
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
|
||||||
String captcha = RedisUtils.getCacheObject(verifyKey);
|
String captcha = RedisUtils.getCacheObject(verifyKey);
|
||||||
RedisUtils.deleteObject(verifyKey);
|
RedisUtils.deleteObject(verifyKey);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,4 +73,12 @@ public class SysLogininforController extends BaseController {
|
||||||
return R.ok();
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SaCheckPermission("system:logininfor:unlock")
|
||||||
|
@Log(title = "账户解锁", businessType = BusinessType.OTHER)
|
||||||
|
@GetMapping("/unlock/{userName}")
|
||||||
|
public AjaxResult unlock(@PathVariable("userName") String userName) {
|
||||||
|
redisService.deleteObject(CacheConstants.PWD_ERR_CNT_KEY + userName);
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ public class SysConfigServiceImpl implements ISysConfigService {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void clearConfigCache() {
|
public void clearConfigCache() {
|
||||||
Collection<String> keys = RedisUtils.keys(Constants.SYS_CONFIG_KEY + "*");
|
Collection<String> keys = RedisUtils.keys(CacheConstants.SYS_CONFIG_KEY + "*");
|
||||||
RedisUtils.deleteObject(keys);
|
RedisUtils.deleteObject(keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -201,6 +201,6 @@ public class SysConfigServiceImpl implements ISysConfigService {
|
||||||
* @return 缓存键key
|
* @return 缓存键key
|
||||||
*/
|
*/
|
||||||
private String getCacheKey(String configKey) {
|
private String getCacheKey(String configKey) {
|
||||||
return Constants.SYS_CONFIG_KEY + configKey;
|
return CacheConstants.SYS_CONFIG_KEY + configKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,13 @@ export function delLogininfor(infoId) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 解锁用户登录状态
|
||||||
|
export function unlockLogininfor(userName) {
|
||||||
|
return request({
|
||||||
|
url: '/system/logininfor/unlock/' + userName,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
// 清空登录日志
|
// 清空登录日志
|
||||||
export function cleanLogininfor() {
|
export function cleanLogininfor() {
|
||||||
return request({
|
return request({
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="top-right-btn">
|
<div class="top-right-btn" :style="style">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top">
|
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top" v-if="search">
|
||||||
<el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" />
|
<el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip class="item" effect="dark" content="刷新" placement="top">
|
<el-tooltip class="item" effect="dark" content="刷新" placement="top">
|
||||||
|
|
@ -42,6 +42,23 @@ export default {
|
||||||
columns: {
|
columns: {
|
||||||
type: Array,
|
type: Array,
|
||||||
},
|
},
|
||||||
|
search: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
gutter: {
|
||||||
|
type: Number,
|
||||||
|
default: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
style() {
|
||||||
|
const ret = {};
|
||||||
|
if (this.gutter) {
|
||||||
|
ret.marginRight = `${this.gutter / 2}px`;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
// 显隐列初始默认隐藏列
|
// 显隐列初始默认隐藏列
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,17 @@
|
||||||
v-hasPermi="['system:logininfor:remove']"
|
v-hasPermi="['system:logininfor:remove']"
|
||||||
>清空</el-button>
|
>清空</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="el-icon-unlock"
|
||||||
|
size="mini"
|
||||||
|
:disabled="single"
|
||||||
|
@click="handleUnlock"
|
||||||
|
v-hasPermi="['system:logininfor:unlock']"
|
||||||
|
>解锁</el-button>
|
||||||
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button
|
||||||
type="warning"
|
type="warning"
|
||||||
|
|
@ -115,7 +126,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { list, delLogininfor, cleanLogininfor } from "@/api/system/logininfor";
|
import { list, delLogininfor, cleanLogininfor, unlockLogininfor } from "@/api/system/logininfor";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Logininfor",
|
name: "Logininfor",
|
||||||
|
|
@ -126,8 +137,12 @@ export default {
|
||||||
loading: true,
|
loading: true,
|
||||||
// 选中数组
|
// 选中数组
|
||||||
ids: [],
|
ids: [],
|
||||||
|
// 非单个禁用
|
||||||
|
single: true,
|
||||||
// 非多个禁用
|
// 非多个禁用
|
||||||
multiple: true,
|
multiple: true,
|
||||||
|
// 选择用户名
|
||||||
|
selectName: "",
|
||||||
// 显示搜索条件
|
// 显示搜索条件
|
||||||
showSearch: true,
|
showSearch: true,
|
||||||
// 总条数
|
// 总条数
|
||||||
|
|
@ -177,7 +192,9 @@ export default {
|
||||||
/** 多选框选中数据 */
|
/** 多选框选中数据 */
|
||||||
handleSelectionChange(selection) {
|
handleSelectionChange(selection) {
|
||||||
this.ids = selection.map(item => item.infoId)
|
this.ids = selection.map(item => item.infoId)
|
||||||
|
this.single = selection.length!=1
|
||||||
this.multiple = !selection.length
|
this.multiple = !selection.length
|
||||||
|
this.selectName = selection.map(item => item.userName);
|
||||||
},
|
},
|
||||||
/** 排序触发事件 */
|
/** 排序触发事件 */
|
||||||
handleSortChange(column, prop, order) {
|
handleSortChange(column, prop, order) {
|
||||||
|
|
@ -204,6 +221,15 @@ export default {
|
||||||
this.$modal.msgSuccess("清空成功");
|
this.$modal.msgSuccess("清空成功");
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
|
/** 解锁按钮操作 */
|
||||||
|
handleUnlock() {
|
||||||
|
const username = this.selectName;
|
||||||
|
this.$modal.confirm('是否确认解锁用户"' + username + '"数据项?').then(function() {
|
||||||
|
return unlockLogininfor(username);
|
||||||
|
}).then(() => {
|
||||||
|
this.$modal.msgSuccess("用户" + username + "解锁成功");
|
||||||
|
}).catch(() => {});
|
||||||
|
},
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
this.download('system/logininfor/export', {
|
this.download('system/logininfor/export', {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue