渗透测试漏洞修复
This commit is contained in:
parent
d1cbf21290
commit
462a4df8af
|
|
@ -25,76 +25,78 @@ public class SysOperLog extends BaseEntity
|
|||
/** 用户编号 */
|
||||
private String userId;
|
||||
|
||||
/** 操作人员 */
|
||||
@Excel(name = "用户名")
|
||||
private String operName;
|
||||
|
||||
/** 电话 */
|
||||
@Excel(name = "手机号")
|
||||
private String phone;
|
||||
|
||||
/** 业务类型(0其它 1新增 2修改 3删除) */
|
||||
private Integer businessType;
|
||||
@Excel(name = "业务类型")
|
||||
private String type;
|
||||
|
||||
/** 操作模块 */
|
||||
@Excel(name = "操作模块")
|
||||
private String title;
|
||||
|
||||
/** 业务类型(0其它 1新增 2修改 3删除) */
|
||||
@Excel(name = "业务类型", readConverterExp = "0=其它,1=新增,2=修改,3=删除,4=授权,5=导出,6=导入,7=强退,8=生成代码,9=清空数据")
|
||||
private Integer businessType;
|
||||
|
||||
/** 业务类型数组 */
|
||||
private Integer[] businessTypes;
|
||||
|
||||
/** 请求方法 */
|
||||
@Excel(name = "请求方法")
|
||||
private String method;
|
||||
|
||||
/** 请求方式 */
|
||||
@Excel(name = "请求方式")
|
||||
private String requestMethod;
|
||||
|
||||
/** 操作类别(0其它 1后台用户 2手机端用户) */
|
||||
@Excel(name = "操作类别", readConverterExp = "0=其它,1=后台用户,2=手机端用户")
|
||||
private Integer operatorType;
|
||||
|
||||
/** 操作人员 */
|
||||
@Excel(name = "操作人员")
|
||||
private String operName;
|
||||
|
||||
/** 部门名称 */
|
||||
@Excel(name = "部门名称")
|
||||
private String deptName;
|
||||
|
||||
/** 请求url */
|
||||
@Excel(name = "请求地址")
|
||||
private String operUrl;
|
||||
|
||||
/** 操作地址 */
|
||||
@Excel(name = "操作地址")
|
||||
private String operIp;
|
||||
|
||||
/** 请求参数 */
|
||||
@Excel(name = "请求参数")
|
||||
private String operParam;
|
||||
|
||||
/** 返回参数 */
|
||||
@Excel(name = "返回参数")
|
||||
private String jsonResult;
|
||||
|
||||
/** 操作类别(0其它 1后台用户 2手机端用户) */
|
||||
@Excel(name = "资源类型")
|
||||
private String operatoType;
|
||||
|
||||
private Integer operatorType;
|
||||
|
||||
//新增的一些字段 fly
|
||||
@Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private String opersTime;
|
||||
|
||||
/** 操作地址 */
|
||||
@Excel(name = "操作地址")
|
||||
private String operIp;
|
||||
|
||||
/** 操作状态(0异常 1正常) */
|
||||
@Excel(name = "状态", readConverterExp = "0=异常,1=正常")
|
||||
@Excel(name = "状态", readConverterExp = "0=请求异常,1=请求成功")
|
||||
private Integer status;
|
||||
|
||||
/** 业务类型数组 */
|
||||
private Integer[] businessTypes;
|
||||
|
||||
/** 请求方法 */
|
||||
|
||||
private String method;
|
||||
|
||||
/** 请求方式 */
|
||||
private String requestMethod;
|
||||
|
||||
|
||||
/** 部门名称 */
|
||||
private String deptName;
|
||||
|
||||
/** 请求url */
|
||||
private String operUrl;
|
||||
|
||||
|
||||
/** 请求参数 */
|
||||
private String operParam;
|
||||
|
||||
|
||||
/** 错误消息 */
|
||||
@Excel(name = "错误消息")
|
||||
private String errorMsg;
|
||||
|
||||
/** 操作时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date operTime;
|
||||
|
||||
//新增的一些字段 fly
|
||||
/** 电话 */
|
||||
private String opersTime;
|
||||
|
||||
/** 电话 */
|
||||
private String phone;
|
||||
|
||||
private String type;
|
||||
|
||||
private String operatoType;
|
||||
|
||||
private String statusRes;
|
||||
|
||||
private String startTime;
|
||||
private String endTime;
|
||||
private String module;
|
||||
private String result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.bonus.common.core.constant.SecurityConstants;
|
|||
import com.bonus.common.core.domain.R;
|
||||
import com.bonus.common.core.utils.JwtUtils;
|
||||
import com.bonus.common.core.utils.StringUtils;
|
||||
import com.bonus.common.redis.service.RedisService;
|
||||
import com.bonus.common.security.auth.AuthUtil;
|
||||
import com.bonus.common.security.service.TokenService;
|
||||
import com.bonus.common.security.utils.SecurityUtils;
|
||||
|
|
@ -35,6 +36,9 @@ public class TokenController
|
|||
@Autowired
|
||||
private LocalSessionManager sessionManager;
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
|
||||
@PostMapping("login")
|
||||
public R<?> login(@RequestBody LoginBody form)
|
||||
|
|
@ -72,6 +76,11 @@ public class TokenController
|
|||
// 记录用户退出日志
|
||||
sysLoginService.logout(userId);
|
||||
}
|
||||
String userId = JwtUtils.getUserId(token);
|
||||
// 删除token缓存
|
||||
redisService.deleteObject(getTokenKey(token));
|
||||
// 删除用户-token关联
|
||||
redisService.deleteObject("user:token:" + userId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
|
@ -95,4 +104,6 @@ public class TokenController
|
|||
sysLoginService.register(registerBody.getUsername(), registerBody.getPassword());
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.bonus.auth.service;
|
||||
|
||||
import com.bonus.common.core.constant.CacheConstants;
|
||||
import com.bonus.common.core.constant.Constants;
|
||||
import com.bonus.common.core.constant.SecurityConstants;
|
||||
import com.bonus.common.core.constant.UserConstants;
|
||||
|
|
@ -16,8 +17,12 @@ import com.bonus.system.api.domain.SysUser;
|
|||
import com.bonus.system.api.model.LoginUser;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 登录校验方法
|
||||
*
|
||||
|
|
@ -32,6 +37,11 @@ public class SysLoginService
|
|||
@Autowired
|
||||
private RemoteUserService remoteUserService;
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
|
|
@ -42,6 +52,11 @@ public class SysLoginService
|
|||
password = AESCBCUtils.decrypt(password);*/
|
||||
username = RSAUtil.decrypt(username);
|
||||
password = RSAUtil.decrypt(password);
|
||||
// 1. 检查用户是否被锁定
|
||||
if (isLocked(username)) {
|
||||
long remainTime = redisTemplate.getExpire(CacheConstants.LOCK_KEY_PREFIX + username, TimeUnit.SECONDS);
|
||||
throw new ServiceException("用户已被锁定,请" + remainTime / 60 + "分" + remainTime % 60 + "秒后重试") ;
|
||||
}
|
||||
if(StringUtils.isNotEmpty(jwtToken)){
|
||||
Claims claims = JwtUtils.parseToken(jwtToken);
|
||||
jwtToken = (String) claims.get(SecurityConstants.DETAILS_USERNAME);
|
||||
|
|
@ -81,6 +96,7 @@ public class SysLoginService
|
|||
|
||||
if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData()))
|
||||
{
|
||||
|
||||
recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在");
|
||||
throw new ServiceException("登录用户:" + username + " 不存在");
|
||||
}
|
||||
|
|
@ -98,11 +114,21 @@ public class SysLoginService
|
|||
}
|
||||
if (!username.equals(jwtToken)) {
|
||||
if (!SecurityUtils.matchesPassword(password, user.getPassword())) {
|
||||
// 登录失败,递增失败次数
|
||||
incrementFailCount(username);
|
||||
long failCount = getFailCount(username);
|
||||
if (failCount >= CacheConstants.FAIL_LIMIT) {
|
||||
// 达到阈值,锁定用户
|
||||
lockUser(username);
|
||||
throw new ServiceException("登录失败次数达到" + CacheConstants.FAIL_LIMIT + "次,用户已锁定5分钟");
|
||||
}
|
||||
recordLogininfor(user.getUserId() + "", Constants.LOGIN_FAIL, "用户密码错误");
|
||||
throw new ServiceException("用户不存在/密码错误");
|
||||
throw new ServiceException("用户不存在/密码错误,还有"+(CacheConstants.FAIL_LIMIT-failCount)+"次机会");
|
||||
}
|
||||
}
|
||||
recordLogininfor(user.getUserId() + "", Constants.LOGIN_SUCCESS, "登录成功");
|
||||
// 3. 登录成功,重置失败次数和锁定状态
|
||||
resetLoginStatus(username);
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
|
|
@ -171,4 +197,47 @@ public class SysLoginService
|
|||
}
|
||||
remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户是否被锁定
|
||||
*/
|
||||
private boolean isLocked(String username) {
|
||||
return redisTemplate.hasKey(CacheConstants.LOCK_KEY_PREFIX + username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 递增登录失败次数
|
||||
*/
|
||||
private void incrementFailCount(String username) {
|
||||
String key = CacheConstants.FAIL_COUNT_KEY_PREFIX + username;
|
||||
redisTemplate.opsForValue().increment(key, 1);
|
||||
// 设置失败次数缓存有效期(如1小时,避免长期存储)
|
||||
if (redisTemplate.getExpire(key) == -1) {
|
||||
redisTemplate.expire(key, 1, TimeUnit.HOURS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录失败次数
|
||||
*/
|
||||
private long getFailCount(String username) {
|
||||
Object count = redisTemplate.opsForValue().get(CacheConstants.FAIL_COUNT_KEY_PREFIX + username);
|
||||
return count == null ? 0 : Long.parseLong(count.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 锁定用户
|
||||
*/
|
||||
private void lockUser(String username) {
|
||||
String key = CacheConstants.LOCK_KEY_PREFIX + username;
|
||||
redisTemplate.opsForValue().set(key, "locked");
|
||||
redisTemplate.expire(key, CacheConstants.LOCK_MINUTES, TimeUnit.MINUTES);
|
||||
}
|
||||
/**
|
||||
* 重置登录状态(成功后)
|
||||
*/
|
||||
private void resetLoginStatus(String username) {
|
||||
redisTemplate.delete(CacheConstants.FAIL_COUNT_KEY_PREFIX + username);
|
||||
redisTemplate.delete(CacheConstants.LOCK_KEY_PREFIX + username);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,4 +21,12 @@ public class CacheConstants
|
|||
* 权限缓存前缀
|
||||
*/
|
||||
public final static String LOGIN_TOKEN_KEY = "login_tokens:";
|
||||
|
||||
// 登录失败次数阈值
|
||||
public static final int FAIL_LIMIT = 5;
|
||||
// 锁定时间(分钟)
|
||||
public static final long LOCK_MINUTES = 60;
|
||||
// Redis键前缀
|
||||
public static final String FAIL_COUNT_KEY_PREFIX = "login:fail:count:";
|
||||
public static final String LOCK_KEY_PREFIX = "login:lock:";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,13 +55,25 @@ public class TokenService
|
|||
loginUser.setUsername(userName);
|
||||
loginUser.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
|
||||
refreshToken(loginUser);
|
||||
// 用户token存储key(用户ID -> 当前token)
|
||||
String userTokenKey = getTokenKey(String.valueOf(userId));
|
||||
// 获取用户当前的旧token
|
||||
String oldToken = redisService.getCacheObject(userTokenKey);
|
||||
// 如果存在旧token,删除旧的token缓存
|
||||
if (oldToken != null) {
|
||||
String oldTokenKey = getTokenKey(oldToken);
|
||||
redisService.deleteObject(oldTokenKey);
|
||||
}
|
||||
// 存储新的token关联
|
||||
redisService.setCacheObject(userTokenKey, token, expireTime, TimeUnit.SECONDS);
|
||||
String userKey = getTokenKey(loginUser.getToken());
|
||||
// Jwt存储信息
|
||||
Map<String, Object> claimsMap = new HashMap<String, Object>();
|
||||
claimsMap.put(SecurityConstants.USER_KEY, token);
|
||||
claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId);
|
||||
claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName);
|
||||
redisService.setCacheObject(getTokenKey(userKey),loginUser);
|
||||
//redisService.setCacheObject(getTokenKey(userKey),loginUser);
|
||||
//redisService.setCacheObject(userKey, loginUser, expireTime, TimeUnit.SECONDS);
|
||||
// 接口返回信息
|
||||
Map<String, Object> rspMap = new HashMap<String, Object>();
|
||||
rspMap.put("access_token", JwtUtils.createToken(claimsMap));
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import org.springframework.web.reactive.function.server.RouterFunctions;
|
|||
|
||||
/**
|
||||
* 路由配置信息
|
||||
*
|
||||
*
|
||||
* @author zys
|
||||
*/
|
||||
@Configuration
|
||||
|
|
@ -20,12 +20,12 @@ public class RouterFunctionConfiguration
|
|||
@Autowired
|
||||
private ValidateCodeHandler validateCodeHandler;
|
||||
|
||||
// @SuppressWarnings("rawtypes")
|
||||
// @Bean
|
||||
// public RouterFunction routerFunction()
|
||||
// {
|
||||
// return RouterFunctions.route(
|
||||
// RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
|
||||
// validateCodeHandler);
|
||||
// }
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Bean
|
||||
public RouterFunction routerFunction()
|
||||
{
|
||||
return RouterFunctions.route(
|
||||
RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
|
||||
validateCodeHandler);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import reactor.core.publisher.Mono;
|
|||
|
||||
/**
|
||||
* 网关鉴权
|
||||
*
|
||||
*
|
||||
* @author zys
|
||||
*/
|
||||
@Component
|
||||
|
|
@ -64,6 +64,15 @@ public class AuthFilter implements GlobalFilter, Ordered
|
|||
return chain.filter(exchange);
|
||||
}
|
||||
String token = getToken(request);
|
||||
// 获取token中的用户ID
|
||||
String userId = JwtUtils.getUserId(token);
|
||||
// 获取用户当前有效的token
|
||||
String currentToken = redisService.getCacheObject(CacheConstants.LOGIN_TOKEN_KEY + userId);
|
||||
// 如果当前token和缓存中的token不一致,说明已被挤下线
|
||||
if (currentToken == null || !currentToken.equals(token)) {
|
||||
return unauthorizedResponse(exchange,"您的账号已在其他设备登录");
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(token) )
|
||||
{
|
||||
return unauthorizedResponse(exchange, "令牌不能为空");
|
||||
|
|
@ -156,4 +165,4 @@ public class AuthFilter implements GlobalFilter, Ordered
|
|||
{
|
||||
return -200;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.bonus.common.core.domain.R;
|
|||
import com.bonus.common.core.table.PageTableHandler;
|
||||
import com.bonus.common.core.table.PageTableRequest;
|
||||
import com.bonus.common.core.table.PageTableResponse;
|
||||
import com.bonus.common.core.utils.RSAUtil;
|
||||
import com.bonus.common.core.utils.StringUtils;
|
||||
import com.bonus.common.log.annotation.Log;
|
||||
import com.bonus.common.log.enums.BusinessType;
|
||||
|
|
@ -52,7 +53,12 @@ public class UserController {
|
|||
@PostMapping
|
||||
@Log(title = "用户管理-新增用户", businessType = BusinessType.INSERT)
|
||||
@RequiresPermissions("sys:user:add")
|
||||
public R saveUser(@RequestBody UserBean userDto) {
|
||||
public R saveUser(UserBean userDto) {
|
||||
userDto.setUserName(RSAUtil.decrypt(userDto.getUserName()));
|
||||
userDto.setPhonenumber(RSAUtil.decrypt(userDto.getPhonenumber()));
|
||||
userDto.setIdNumber(RSAUtil.decrypt(userDto.getIdNumber()));
|
||||
userDto.setOrgId(RSAUtil.decrypt(userDto.getOrgId()));
|
||||
userDto.setRoleId(RSAUtil.decrypt(userDto.getRoleId()));
|
||||
String u = userService.getExistUser(userDto.getPhonenumber());
|
||||
if (u != null) {
|
||||
throw new IllegalArgumentException(u + "手机号码已被注册");
|
||||
|
|
@ -65,6 +71,8 @@ public class UserController {
|
|||
@PutMapping
|
||||
@RequiresPermissions("sys:user:add")
|
||||
public R updateUser(@RequestBody UserBean userDto) {
|
||||
userDto.setUserName(RSAUtil.decrypt(userDto.getUserName()));
|
||||
userDto.setPhone(RSAUtil.decrypt(userDto.getPhone()));
|
||||
return userService.updateUser(userDto);
|
||||
}
|
||||
|
||||
|
|
@ -72,6 +80,9 @@ public class UserController {
|
|||
@PutMapping("/{username}")
|
||||
@RequiresPermissions("sys:user:password")
|
||||
public void changePassword(@PathVariable String username, String oldPassword, String newPassword) {
|
||||
//解密
|
||||
oldPassword = RSAUtil.decrypt(oldPassword);
|
||||
newPassword = RSAUtil.decrypt(newPassword);
|
||||
userService.changePassword(username, oldPassword, newPassword);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ public interface UserDao {
|
|||
List<UserBean> list(@Param("params") Map<String, Object> params, @Param("offset") Integer offset,
|
||||
@Param("limit") Integer limit);
|
||||
|
||||
@Update("update \"ynrealname\".\"sys_role_user\" set \"is_active\" = '0' where \"userId\" = #{userId}")
|
||||
int deleteUserRole(int userId);
|
||||
|
||||
int deleteUserRole(@Param("userId") int userId);
|
||||
|
||||
int saveUserRoles(@Param("userId")String userId, @Param("roleId") String roleId);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.bonus.bmw.basic.dao.UserDao">
|
||||
<delete id="deleteUserRole">
|
||||
update "ynrealname"."sys_role_user" set "is_active" = '0' where "userId" = #{userId}
|
||||
</delete>
|
||||
|
||||
<select id="count" resultType="int">
|
||||
select count(1)
|
||||
|
|
@ -172,10 +175,8 @@
|
|||
insert into "ynrealname"."sys_role_user"("roleId", "userId","is_active") values(#{roleId},#{userId},'1')
|
||||
</insert>
|
||||
<!-- 添加用户 -->
|
||||
<insert id="saveUser">
|
||||
<selectKey resultType="java.lang.Long" keyProperty="userId" order="BEFORE">
|
||||
SELECT @@IDENTITY
|
||||
</selectKey>
|
||||
<insert id="saveUser" keyProperty="userId" useGeneratedKeys="true">
|
||||
|
||||
insert into "ynrealname"."sys_user"
|
||||
("username", "password", "loginname", "id_number","phone",
|
||||
<if test="orgId != null and orgId !=''">
|
||||
|
|
@ -270,4 +271,4 @@
|
|||
UPDATE "ynrealname"."sys_user" SET "is_push"= #{user.status} WHERE "phone" = #{user.phone} and "is_active" = #{user.isActive}
|
||||
</foreach>
|
||||
</update>
|
||||
</mapper>
|
||||
</mapper>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ function initMenu() {
|
|||
url: ctxPath + "/permissions/current",
|
||||
type: "get",
|
||||
headers: {
|
||||
"Authorization": token
|
||||
"token": token
|
||||
},
|
||||
async: false,
|
||||
success: function (data) {
|
||||
|
|
@ -98,7 +98,7 @@ function showLoginInfo() {
|
|||
type: 'get',
|
||||
url: ctxPath + '/users/current',
|
||||
headers: {
|
||||
"Authorization": token
|
||||
"token": token
|
||||
},
|
||||
async: false,
|
||||
success: function (data) {
|
||||
|
|
@ -142,7 +142,7 @@ function logout() {
|
|||
type: 'delete',
|
||||
url: DATA_URL + '/auth/logout',
|
||||
headers: {
|
||||
"Authorization": token
|
||||
"token": token
|
||||
},
|
||||
success: function (data) {
|
||||
if (data.code==401) {
|
||||
|
|
@ -293,3 +293,5 @@ function onclickIndex(lay_id){
|
|||
layui.use(['layer'], function () {
|
||||
layer = layui.layer;
|
||||
});
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -157,25 +157,27 @@ function init() {
|
|||
},
|
||||
"dom": "<'dt-toolbar'r>t<'dt-toolbar-footer'<'col-sm-4 col-xs-4 hidden-xs'i><'col-xs-8 col-sm-8' p v>>",
|
||||
"columns": [
|
||||
{"width":"5%",
|
||||
{"width":"4%",
|
||||
data: function (row, type, set, meta) {
|
||||
var c = meta.settings._iDisplayStart + meta.row + 1;
|
||||
return c;
|
||||
}
|
||||
},
|
||||
{"data": "operName", "defaultContent": "","width":"8%"},
|
||||
{"data": "phone", "defaultContent": "","width":"8%"},
|
||||
{"data": "type", "defaultContent": "","width":"8%"},
|
||||
{"data": "title", "defaultContent": "","width":"10%"},
|
||||
{"data": "operName", "defaultContent": "","width":"7%"},
|
||||
{"data": "phone", "defaultContent": "","width":"7%"},
|
||||
{"data": "type", "defaultContent": "","width":"7%"},
|
||||
{"data": "title", "defaultContent": "","width":"8%"},
|
||||
{"render": function (data, type, row) {
|
||||
let jsonResult = row['jsonResult'];
|
||||
let id = row['id'];
|
||||
let html = "";
|
||||
html = '<textarea class="layui-textarea">'+jsonResult+'</textarea>';
|
||||
return html;
|
||||
}, width: "43%"},
|
||||
{"data": "operatoType", "defaultContent": "","width":"8%"},
|
||||
{"data": "opersTime", "defaultContent": "","width":"10%"},
|
||||
}, width: "37%"},
|
||||
{"data": "operatoType", "defaultContent": "","width":"7%"},
|
||||
{"data": "opersTime", "defaultContent": "","width":"8%"},
|
||||
{"data": "operIp", "defaultContent": "","width":"8%"},
|
||||
{"data": "statusRes", "defaultContent": "","width":"7%"},
|
||||
],
|
||||
"order": [[0, "desc"], [1, "asc"]]
|
||||
});
|
||||
|
|
@ -192,3 +194,19 @@ function getNowTime() {
|
|||
var day = time.getDate() >= 10 ? time.getDate() : '0' + time.getDate();
|
||||
return year + "-" + month + "-" + day;
|
||||
}
|
||||
|
||||
function exportData() {
|
||||
var keyWord = $('#keyWord').val();
|
||||
var module = $('#module').val();
|
||||
var result = $('#result').val();
|
||||
var type = $('#type').val();
|
||||
var startTime = $('#startTime').val();
|
||||
var endTime = $('#endTime').val();
|
||||
window.location.href = DATA_URL + "/system/operlog/export?token=" + token
|
||||
+ "&keyword=" + keyWord
|
||||
+ "&module=" + module
|
||||
+ "&result=" + result
|
||||
+ "&type=" + type
|
||||
+ "&startTime=" + startTime
|
||||
+ "&endTime=" + endTime;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,9 +53,16 @@ function addUser(formData) {
|
|||
type: 'POST',
|
||||
async: false, // 默认异步true,false表示同步
|
||||
url: formUrl, // 请求地址
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: 'json', // 服务器返回数据类型
|
||||
data: JSON.stringify(formData.field), //获取提交的表单字段
|
||||
//contentType: "application/x-www-form-urlencoded",
|
||||
//dataType: 'json', // 服务器返回数据类型
|
||||
//data: JSON.stringify(formData.field), //获取提交的表单字段
|
||||
data: {
|
||||
userName : encryptRsa($("#userName").val()),
|
||||
idNumber : encryptRsa($("#idNumber").val()),
|
||||
phonenumber : encryptRsa($("#phonenumber").val()),
|
||||
orgId : encryptRsa($("#orgId").val()),
|
||||
roleId : encryptRsa($("#roleId").val())
|
||||
},
|
||||
success: function (data) {
|
||||
layer.close(loadingMsg); // 关闭提示层
|
||||
if(data.code == 200){
|
||||
|
|
@ -217,4 +224,4 @@ function reloading() {
|
|||
var index = parent.layer.getFrameIndex(window.name); //先得到当前 iframe层的索引
|
||||
parent.layer.close(index); //再执行关闭
|
||||
window.parent.location.reload();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">旧密码</label>
|
||||
<div class="col-md-10">
|
||||
<input class="form-control" placeholder="旧密码" type="text" name="oldPassword"
|
||||
<input class="form-control" placeholder="旧密码" type="text" name="oldPassword" id="oldPassword"
|
||||
data-bv-notempty="true"
|
||||
data-bv-notempty-message="旧密码 不能为空">
|
||||
</div>
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
<input class="form-control" placeholder="新密码" type="text" name="newPassword" id="newPassword"
|
||||
data-bv-notempty="true"
|
||||
data-bv-notempty-message="新密码 不能为空"
|
||||
|
||||
|
||||
data-bv-identical="true"
|
||||
data-bv-identical-field="newPassword2"
|
||||
data-bv-identical-message="两次密码不一致">
|
||||
|
|
@ -66,6 +66,7 @@
|
|||
<script type="text/javascript" src="../../layui/layui.js"></script>
|
||||
<script type="text/javascript" src="../../js/plugin/bootstrapvalidator/bootstrapValidator.min.js"></script>
|
||||
<script type="text/javascript" src="../../js/publicJs.js"></script>
|
||||
<script type="text/javascript" src="../../js/Rsa.js"></script>
|
||||
<script type="text/javascript">
|
||||
layui.use('layer', function(){
|
||||
var layer = layui.layer;
|
||||
|
|
@ -80,11 +81,11 @@
|
|||
$("#username").val(data.username);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
init();
|
||||
|
||||
|
||||
function update() {
|
||||
$('#form').bootstrapValidator();
|
||||
var bootstrapValidator = $("#form").data('bootstrapValidator');
|
||||
|
|
@ -101,7 +102,13 @@
|
|||
$.ajax({
|
||||
type : 'put',
|
||||
url : ctxPath + '/users/'+$("#username").val(),
|
||||
data : $("#form").serialize(),
|
||||
//data : $("#form").serialize(),
|
||||
data: {
|
||||
username : encryptRsa($("#username").val()),
|
||||
oldPassword : encryptRsa($("#oldPassword").val()),
|
||||
newPassword : encryptRsa($("#newPassword").val()),
|
||||
newPassword2 : encryptRsa($("#newPassword2").val())
|
||||
},
|
||||
success : function(data) {
|
||||
layer.msg("修改成功", {shift: -1, time: 1000}, function(){
|
||||
deleteCurrentTab();
|
||||
|
|
@ -127,4 +134,4 @@
|
|||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -76,10 +76,11 @@
|
|||
<script type="text/javascript" src="../../js/plugin/bootstrapvalidator/bootstrapValidator.min.js"></script>
|
||||
<script type="text/javascript" src="../../js/common.js"></script>
|
||||
<script type="text/javascript" src="../../js/dict.js"></script>
|
||||
<script type="text/javascript" src="../../js/Rsa.js"></script>
|
||||
<script type="text/javascript">
|
||||
showDictSelect("sex", "sex");
|
||||
initData();
|
||||
|
||||
|
||||
function initData(){
|
||||
$.ajax({
|
||||
type : 'get',
|
||||
|
|
@ -97,9 +98,9 @@
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$('#form').bootstrapValidator();
|
||||
|
||||
|
||||
layui.use(['layer','laydate'], function(){
|
||||
var layer = layui.layer;
|
||||
var laydate = layui.laydate;
|
||||
|
|
@ -107,21 +108,32 @@
|
|||
elem: '#birthday'
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function update() {
|
||||
var bootstrapValidator = $("#form").data('bootstrapValidator');
|
||||
bootstrapValidator.validate();
|
||||
if(!bootstrapValidator.isValid()){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var formdata = $("#form").serializeObject();
|
||||
|
||||
$.ajax({
|
||||
type : 'put',
|
||||
url : ctxPath + '/users',
|
||||
contentType: "application/json; charset=utf-8",
|
||||
data : JSON.stringify(formdata),
|
||||
contentType: "application/json; charset=utf-8",
|
||||
//data : JSON.stringify(formdata),
|
||||
data: {
|
||||
id :$("#id").val(),
|
||||
username : encryptRsa($("#username").val()),
|
||||
nickname : encryptRsa($("#nickname").val()),
|
||||
phone : encryptRsa($("#phone").val()),
|
||||
telephone : encryptRsa($("#telephone").val()),
|
||||
email : encryptRsa($("#email").val()),
|
||||
birthday : encryptRsa($("#birthday").val()),
|
||||
sex : $("#sex").val(),
|
||||
status: $("#status").val()
|
||||
},
|
||||
success : function(data) {
|
||||
layer.msg("修改成功", {shift: -1, time: 1000}, function(){
|
||||
deleteCurrentTab();
|
||||
|
|
@ -129,7 +141,7 @@
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@
|
|||
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../js/libs/jquery-3.6.0.js"></script>
|
||||
<script type="text/javascript" src="../../js/jq.js"></script>
|
||||
<script type="text/javascript" src="../../js/plugin/bootstrapvalidator/bootstrapValidator.min.js"></script>
|
||||
|
|
@ -88,6 +88,7 @@
|
|||
<script type="text/javascript" src="../../layui/layui.js"></script>
|
||||
<script type="text/javascript" src="../../js/dict.js"></script>
|
||||
<script type="text/javascript" src="../../js/publicJs.js"></script>
|
||||
<script type="text/javascript" src="../../js/Rsa.js"></script>
|
||||
<script type="text/javascript">
|
||||
layui.use(['layer','laydate'], function(){
|
||||
var layer = layui.layer;
|
||||
|
|
@ -96,14 +97,14 @@
|
|||
elem: '#birthday'
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
showDictSelect("sex", "sex");
|
||||
showDictSelect("status", "userStatus");
|
||||
|
||||
|
||||
initRoles();
|
||||
|
||||
|
||||
initData();
|
||||
|
||||
|
||||
function initData(){
|
||||
var id = getUrlParam("id");
|
||||
if(id != ""){
|
||||
|
|
@ -123,28 +124,38 @@
|
|||
$("#status").val(data.status);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
initRoleDatas(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$('#form').bootstrapValidator();
|
||||
|
||||
|
||||
function update() {
|
||||
var bootstrapValidator = $("#form").data('bootstrapValidator');
|
||||
bootstrapValidator.validate();
|
||||
if(!bootstrapValidator.isValid()){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var formdata = $("#form").serializeObject();
|
||||
formdata.roleIds = getCheckedRoleIds();
|
||||
|
||||
$.ajax({
|
||||
type : 'put',
|
||||
url : ctxPath + '/users',
|
||||
contentType: "application/json; charset=utf-8",
|
||||
data : JSON.stringify(formdata),
|
||||
contentType: "application/json; charset=utf-8",
|
||||
//data : JSON.stringify(formdata),
|
||||
data: {
|
||||
username : encryptRsa($("#username").val()),
|
||||
nickname : encryptRsa($("#nickname").val()),
|
||||
phone : encryptRsa($("#phone").val()),
|
||||
telephone : encryptRsa($("#telephone").val()),
|
||||
email : encryptRsa($("#email").val()),
|
||||
birthday : encryptRsa($("#birthday").val()),
|
||||
sex : $("#sex").val(),
|
||||
status: $("#status").val()
|
||||
},
|
||||
success : function(data) {
|
||||
layer.msg("修改成功", {shift: -1, time: 1000}, function(){
|
||||
location.href = ctxPath + "/pages/user/userList.html";
|
||||
|
|
@ -152,7 +163,7 @@
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@
|
|||
<button id="searchBt" class="layui-btn layui-btn-sm" permission="sys:operlog:query"
|
||||
><i class="layui-icon"></i>搜索
|
||||
</button>
|
||||
<button class="layui-btn layui-btn-sm" onclick="exportData()">
|
||||
导出
|
||||
</button>
|
||||
<input type="hidden" id="hidMinListDate" value="2022-07-01" />
|
||||
<input type="hidden" id="hidMaxListDate" value='@DateTime.Now.ToString("yyyy-MM-dd")' />
|
||||
</div>
|
||||
|
|
@ -75,6 +78,8 @@
|
|||
<th>返回值</th>
|
||||
<th>资源类型</th>
|
||||
<th>操作时间</th>
|
||||
<th>操作地址</th>
|
||||
<th>请求结果</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -97,4 +102,4 @@
|
|||
<script type="text/javascript" src="../../../../js/dict.js"></script>
|
||||
<script type="text/javascript" src="../../../../js/select.js"></script>
|
||||
<script type="text/javascript" src="../../../../js/work/SettingManage/OperateLog/SysOperateLog.js"
|
||||
defer="defer"></script>
|
||||
defer="defer"></script>
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@
|
|||
<script src="../../../../css/ztree/3.5/jquery.ztree.all.min.js"></script>
|
||||
<script type="text/javascript" src="../../../../js/work/SettingManage/UserManage/OrgTree.js"></script>
|
||||
<script type="text/javascript" src="../../../../js/work/SettingManage/UserManage/UserForm.js" defer="defer"></script>
|
||||
<script type="text/javascript" src="../../../../js/Rsa.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -64,8 +64,13 @@ public class SelectController {
|
|||
//@CrossOrigin
|
||||
@Log(title = "查询工程-orgId", businessType = BusinessType.SELECT)
|
||||
public R getProByOrgId(SelectBean o){
|
||||
SelfPermissionSettingUtils.getSelfPermissionByOrgId(o);
|
||||
return service.getProByOrgId(o);
|
||||
try{
|
||||
SelfPermissionSettingUtils.getSelfPermissionByOrgId(o);
|
||||
return service.getProByOrgId(o);
|
||||
} catch (Exception e) {
|
||||
return R.ok("请求异常,请联系管理员");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@GetMapping("getProByTeamId")
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import java.util.List;
|
|||
|
||||
/**
|
||||
* 操作日志记录
|
||||
*
|
||||
*
|
||||
* @author zys
|
||||
*/
|
||||
@RestController
|
||||
|
|
@ -62,11 +62,11 @@ public class SysOperlogController extends BaseController
|
|||
|
||||
|
||||
@Log(title = "操作日志", businessType = BusinessType.EXPORT)
|
||||
@RequiresPermissions("system:operlog:export")
|
||||
@PostMapping("/export")
|
||||
//@RequiresPermissions("system:operlog:export")
|
||||
@GetMapping("/export")
|
||||
public void export(HttpServletResponse response, SysOperLog operLog)
|
||||
{
|
||||
List<SysOperLog> list = operLogService.selectOperLogList(operLog);
|
||||
List<SysOperLog> list = operLogService.export(operLog);
|
||||
ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
|
||||
util.exportExcel(response, list, "操作日志");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,4 +53,5 @@ public interface SysOperLogMapper
|
|||
|
||||
List<SysOperLog> list(@Param("params") Map<String, Object> params, @Param("offset") Integer offset, @Param("limit")Integer limit);
|
||||
|
||||
List<SysOperLog> export(SysOperLog operLog);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,4 +52,6 @@ public interface ISysOperLogService
|
|||
int count(Map<String, Object> params);
|
||||
|
||||
List<SysOperLog> list(Map<String, Object> params, Integer offset, Integer limit);
|
||||
|
||||
List<SysOperLog> export(SysOperLog operLog);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import java.util.Map;
|
|||
|
||||
/**
|
||||
* 操作日志 服务层处理
|
||||
*
|
||||
*
|
||||
* @author zys
|
||||
*/
|
||||
@Service
|
||||
|
|
@ -21,7 +21,7 @@ public class SysOperLogServiceImpl implements ISysOperLogService
|
|||
|
||||
/**
|
||||
* 新增操作日志
|
||||
*
|
||||
*
|
||||
* @param operLog 操作日志对象
|
||||
* @return 结果
|
||||
*/
|
||||
|
|
@ -33,7 +33,7 @@ public class SysOperLogServiceImpl implements ISysOperLogService
|
|||
|
||||
/**
|
||||
* 查询系统操作日志集合
|
||||
*
|
||||
*
|
||||
* @param operLog 操作日志对象
|
||||
* @return 操作日志集合
|
||||
*/
|
||||
|
|
@ -45,7 +45,7 @@ public class SysOperLogServiceImpl implements ISysOperLogService
|
|||
|
||||
/**
|
||||
* 批量删除系统操作日志
|
||||
*
|
||||
*
|
||||
* @param operIds 需要删除的操作日志ID
|
||||
* @return 结果
|
||||
*/
|
||||
|
|
@ -57,7 +57,7 @@ public class SysOperLogServiceImpl implements ISysOperLogService
|
|||
|
||||
/**
|
||||
* 查询操作日志详细
|
||||
*
|
||||
*
|
||||
* @param operId 操作ID
|
||||
* @return 操作日志对象
|
||||
*/
|
||||
|
|
@ -85,4 +85,10 @@ public class SysOperLogServiceImpl implements ISysOperLogService
|
|||
public List<SysOperLog> list(Map<String, Object> params, Integer offset, Integer limit) {
|
||||
return operLogMapper.list(params,offset,limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysOperLog> export(SysOperLog operLog) {
|
||||
List<SysOperLog> res =operLogMapper.export(operLog);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,6 +160,63 @@
|
|||
OFFSET #{offset} ROWS FETCH NEXT #{limit} ROWS ONLY
|
||||
</if>
|
||||
</select>
|
||||
<select id="export" resultType="com.bonus.system.api.domain.SysOperLog">
|
||||
select
|
||||
su."username" AS operName,
|
||||
su."phone",
|
||||
a.*
|
||||
from(
|
||||
SELECT
|
||||
"user_id",
|
||||
"oper_id" AS operId,
|
||||
"title",
|
||||
"json_result" as jsonResult,
|
||||
"oper_ip" as operIp,
|
||||
"status" as status,
|
||||
CASE
|
||||
"business_type"
|
||||
WHEN 1 THEN '查询'
|
||||
WHEN 2 THEN '新增'
|
||||
WHEN 3 THEN '修改'
|
||||
WHEN 4 THEN '删除'
|
||||
WHEN 5 THEN '授权'
|
||||
WHEN 6 THEN '导出'
|
||||
WHEN 7 THEN '导入'
|
||||
WHEN 8 THEN '强退'
|
||||
WHEN 9 THEN '生成代码'
|
||||
WHEN 10 THEN '清空数据'
|
||||
ELSE '其他'
|
||||
END AS type,
|
||||
CASE
|
||||
"operator_type"
|
||||
WHEN 1 THEN '后台'
|
||||
WHEN 2 THEN 'APP'
|
||||
ELSE '其他'
|
||||
END AS operatoType ,
|
||||
CASE
|
||||
"status"
|
||||
WHEN 0 THEN '请求异常'
|
||||
WHEN 1 THEN '请求成功'
|
||||
ELSE '其他'
|
||||
END AS statusRes ,
|
||||
"create_time" AS opersTime
|
||||
FROM
|
||||
"ynrealname"."sys_oper_log"
|
||||
where
|
||||
"create_time" BETWEEN #{startTime} || ' 00:00:00' and #{endTime} || ' 23:59:59'
|
||||
<if test="type != null and type != ''">
|
||||
and "operator_type" = #{type}
|
||||
</if>
|
||||
<if test="module != null and module != ''">
|
||||
and INSTR("title", #{module}) > 0
|
||||
</if>
|
||||
<if test="result != null and result != ''">
|
||||
and INSTR("json_result", #{result}) > 0
|
||||
</if>
|
||||
) a
|
||||
LEFT JOIN "ynrealname"."sys_user" su ON su."id" = a."user_id"
|
||||
order by a.opersTime DESC
|
||||
</select>
|
||||
|
||||
<update id="cleanOperLog">
|
||||
truncate table "ynrealname"."sys_oper_log"
|
||||
|
|
|
|||
Loading…
Reference in New Issue