From 5edaf204f68640b8b948f98b0cf86b8ff3846b1c Mon Sep 17 00:00:00 2001 From: jiang Date: Wed, 24 Jul 2024 10:50:53 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=8A=A0=E8=A7=A3=E5=AF=86?= =?UTF-8?q?=E5=92=8C=E5=AE=8C=E6=95=B4=E6=80=A7=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/bonus/system/api/domain/SysUser.java | 263 +++++++++--------- .../core/utils/encryption/AesCbcUtils.java | 2 +- .../gateway/filter/AecDecryptParamFilter.java | 258 +++++++++-------- .../gateway/filter/BlackListUrlFilter.java | 31 +-- .../system/controller/SysUserController.java | 195 +++++++------ .../bonus/system/mapper/SysUserMapper.java | 2 + .../bonus/system/service/ISysUserService.java | 5 + .../service/impl/SysUserServiceImpl.java | 21 ++ .../resources/mapper/system/SysUserMapper.xml | 10 +- 9 files changed, 426 insertions(+), 361 deletions(-) diff --git a/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/domain/SysUser.java b/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/domain/SysUser.java index 6fdc833..71e2a0f 100644 --- a/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/domain/SysUser.java +++ b/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/domain/SysUser.java @@ -3,6 +3,7 @@ package com.bonus.system.api.domain; import java.util.Date; import java.util.List; import javax.validation.constraints.*; + import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import com.bonus.common.core.annotation.Excel; @@ -14,289 +15,291 @@ import com.bonus.common.core.xss.Xss; /** * 用户对象 sys_user - * + * * @author bonus */ -public class SysUser extends BaseEntity -{ +public class SysUser extends BaseEntity { private static final long serialVersionUID = 1L; - /** 用户ID */ + /** + * 用户ID + */ @Excel(name = "用户序号", type = Type.EXPORT, cellType = ColumnType.NUMERIC, prompt = "用户编号") private Long userId; - /** 部门ID */ + /** + * 部门ID + */ @Excel(name = "部门编号", type = Type.IMPORT) private Long deptId; - /** 用户账号 */ + /** + * 用户账号 + */ @Excel(name = "登录名称") private String userName; - /** 用户昵称 */ + /** + * 用户昵称 + */ @Excel(name = "用户名称") private String nickName; - /** 用户邮箱 */ + /** + * 用户邮箱 + */ @Excel(name = "用户邮箱") private String email; - /** 手机号码 */ + /** + * 手机号码 + */ @Excel(name = "手机号码", cellType = ColumnType.TEXT) private String phonenumber; - /** 用户性别 */ + /** + * 用户性别 + */ @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知") private String sex; - /** 用户头像 */ + /** + * 用户头像 + */ private String avatar; - /** 密码 */ + /** + * 密码 + */ private String password; - /** 帐号状态(0正常 1停用) */ + /** + * 帐号状态(0正常 1停用) + */ @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用") private String status; - /** 删除标志(0代表存在 2代表删除) */ + /** + * 删除标志(0代表存在 2代表删除) + */ private String delFlag; - /** 最后登录IP */ + /** + * 最后登录IP + */ @Excel(name = "最后登录IP", type = Type.EXPORT) private String loginIp; - /** 最后登录时间 */ + /** + * 最后登录时间 + */ @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) private Date loginDate; - /** 部门对象 */ + /** + * 部门对象 + */ @Excels({ - @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), - @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT) + @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), + @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT) }) private SysDept dept; - /** 角色对象 */ + /** + * 角色对象 + */ private List roles; - /** 角色组 */ + /** + * 角色组 + */ private Long[] roleIds; - /** 岗位组 */ + /** + * 岗位组 + */ private Long[] postIds; - /** 角色ID */ + /** + * 角色ID + */ private Long roleId; - /** 登录权限 */ + /** + * 登录权限 + */ private String loginType; + /** + * 审批状态 + */ + private String approvalStatus; - public SysUser() - { + public SysUser() { } - public SysUser(Long userId) - { + + public SysUser(Long userId) { this.userId = userId; } - public Long getUserId() - { + public Long getUserId() { return userId; } - public void setUserId(Long userId) - { + public void setUserId(Long userId) { this.userId = userId; } - public boolean isAdmin() - { + public boolean isAdmin() { return isAdmin(this.userId); } - public static boolean isAdmin(Long userId) - { + public static boolean isAdmin(Long userId) { return userId != null && 1L == userId; } - public Long getDeptId() - { + public Long getDeptId() { return deptId; } - public void setDeptId(Long deptId) - { + public void setDeptId(Long deptId) { this.deptId = deptId; } @Xss(message = "用户昵称不能包含脚本字符") @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符") - public String getNickName() - { + public String getNickName() { return nickName; } - public void setNickName(String nickName) - { + public void setNickName(String nickName) { this.nickName = nickName; } @Xss(message = "用户账号不能包含脚本字符") @NotBlank(message = "用户账号不能为空") @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符") - public String getUserName() - { + public String getUserName() { return userName; } - public void setUserName(String userName) - { + public void setUserName(String userName) { this.userName = userName; } @Email(message = "邮箱格式不正确") @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") - public String getEmail() - { + public String getEmail() { return email; } - public void setEmail(String email) - { + public void setEmail(String email) { this.email = email; } @Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符") - public String getPhonenumber() - { + public String getPhonenumber() { return phonenumber; } - public void setPhonenumber(String phonenumber) - { + public void setPhonenumber(String phonenumber) { this.phonenumber = phonenumber; } - public String getSex() - { + public String getSex() { return sex; } - public void setSex(String sex) - { + public void setSex(String sex) { this.sex = sex; } - public String getAvatar() - { + public String getAvatar() { return avatar; } - public void setAvatar(String avatar) - { + public void setAvatar(String avatar) { this.avatar = avatar; } - public String getPassword() - { + public String getPassword() { return password; } - public void setPassword(String password) - { + public void setPassword(String password) { this.password = password; } - public String getStatus() - { + public String getStatus() { return status; } - public void setStatus(String status) - { + public void setStatus(String status) { this.status = status; } - public String getDelFlag() - { + public String getDelFlag() { return delFlag; } - public void setDelFlag(String delFlag) - { + public void setDelFlag(String delFlag) { this.delFlag = delFlag; } - public String getLoginIp() - { + public String getLoginIp() { return loginIp; } - public void setLoginIp(String loginIp) - { + public void setLoginIp(String loginIp) { this.loginIp = loginIp; } - public Date getLoginDate() - { + public Date getLoginDate() { return loginDate; } - public void setLoginDate(Date loginDate) - { + public void setLoginDate(Date loginDate) { this.loginDate = loginDate; } - public SysDept getDept() - { + public SysDept getDept() { return dept; } - public void setDept(SysDept dept) - { + public void setDept(SysDept dept) { this.dept = dept; } - public List getRoles() - { + public List getRoles() { return roles; } - public void setRoles(List roles) - { + public void setRoles(List roles) { this.roles = roles; } - public Long[] getRoleIds() - { + public Long[] getRoleIds() { return roleIds; } - public void setRoleIds(Long[] roleIds) - { + public void setRoleIds(Long[] roleIds) { this.roleIds = roleIds; } - public Long[] getPostIds() - { + public Long[] getPostIds() { return postIds; } - public void setPostIds(Long[] postIds) - { + public void setPostIds(Long[] postIds) { this.postIds = postIds; } - public Long getRoleId() - { + public Long getRoleId() { return roleId; } - public void setRoleId(Long roleId) - { + public void setRoleId(Long roleId) { this.roleId = roleId; } @@ -308,29 +311,37 @@ public class SysUser extends BaseEntity this.loginType = loginType; } + public String getApprovalStatus() { + return approvalStatus; + } + + public void setApprovalStatus(String approvalStatus) { + this.approvalStatus = approvalStatus; + } + @Override public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("userId", getUserId()) - .append("deptId", getDeptId()) - .append("userName", getUserName()) - .append("nickName", getNickName()) - .append("email", getEmail()) - .append("phonenumber", getPhonenumber()) - .append("sex", getSex()) - .append("avatar", getAvatar()) - .append("password", getPassword()) - .append("status", getStatus()) - .append("delFlag", getDelFlag()) - .append("loginIp", getLoginIp()) - .append("loginDate", getLoginDate()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .append("dept", getDept()) - .append("loginType", getLoginType()) - .toString(); + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("deptId", getDeptId()) + .append("userName", getUserName()) + .append("nickName", getNickName()) + .append("email", getEmail()) + .append("phonenumber", getPhonenumber()) + .append("sex", getSex()) + .append("avatar", getAvatar()) + .append("password", getPassword()) + .append("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("loginIp", getLoginIp()) + .append("loginDate", getLoginDate()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .append("dept", getDept()) + .append("loginType", getLoginType()) + .toString(); } } diff --git a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/encryption/AesCbcUtils.java b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/encryption/AesCbcUtils.java index 583d16b..f01653f 100644 --- a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/encryption/AesCbcUtils.java +++ b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/encryption/AesCbcUtils.java @@ -84,7 +84,7 @@ public class AesCbcUtils { String json="{\"username\":\"guest\",\"password\":\"admin@123\"}"; String data=encrypt(json); System.err.println(data); - String jm=decrypt("HpouTnMjl/Of1leko+SHm3D436XwOROzSOhMqU0ZNUISeD/iXPK9t49sMEuBw3YO"); + String jm=decrypt("\"yeCxaGhmdDt+zDsKPr1prukR15BfIMLMOYIFKdgffGpMV76qVD8ANU4zsLiRZ87+7hd1Yje182nHhUOp/TeYCRuuUPQzmuXH7ikYVEWR1Rmc8uLq3G/BTMU6wFMSRFDBXARRl+dvnpyfX+MleF0KB1OAeuOIKv1gQPskmvDiFAniUlowf/96ZzMl7Bokqc/Lse8lMV92IQB14yQNa0+u/2kvdirzrcq+HCt9K8Ot3C59mjDqg49WoM65LEmaHmZqzdmmjbQlGH7ZOAFTLvF5kPzUsMz5Uim1uNvByB3eLFohc1UgB28DWoTyh43sRMPpq3S1BB20gcrBf3uVra/4qehBr3z98CGhGRyKHbjsCKl0Ri6YO1rp5aMRd9Y3wbOJFrZXFag5iifQx+ooDBeu6h1KCb5JfCjyAmw9+pgEL6X3eELPzK13XjblDyEikjx2Edv45MGsC0DUcjvz/Sb4E/8rn3o1Ep7W31xNCdn5mzZ8VO9POhE3DMK6woeN2C7TW+7YO/Zs9e4zKLS4vThvk5urCn2Ff2HkVBzoPtP2imuqQrY8898sbLllyaJEG0DPSrCf985ZgVa03JsO/EkMr3KAiHV5SHBZS1XEXqjdpL+YEdOnlfBXUk83kJhLj9rhUrTFza7ednQSzjq4XpIJJVy2aJhhj1chsmIM1Xl//0Dbak9Lb6VUq5Xr2IFAjNTgyxwtcFCdEvp4YZCSP6kqWgEpeAVlejyYOcNckUnWkjeHjtfgwvVsvUjWzyIRFCa7m/oY28xBV16RmW/r4XXquqKVdbPtATzrmf7pJCynXZ3IPd9ZGc1OTLnss9Ln9XNTH0E/I4Ma95fn9uxA+sOQkQ==\""); String jiemi=decrypt(data); System.err.println(jm); System.err.println(jiemi); diff --git a/bonus-gateway/src/main/java/com/bonus/gateway/filter/AecDecryptParamFilter.java b/bonus-gateway/src/main/java/com/bonus/gateway/filter/AecDecryptParamFilter.java index dd965ed..0628d0d 100644 --- a/bonus-gateway/src/main/java/com/bonus/gateway/filter/AecDecryptParamFilter.java +++ b/bonus-gateway/src/main/java/com/bonus/gateway/filter/AecDecryptParamFilter.java @@ -3,163 +3,191 @@ package com.bonus.gateway.filter; import com.bonus.common.core.exception.CaptchaException; import com.bonus.common.core.utils.StringUtils; import com.bonus.common.core.utils.encryption.AesCbcUtils; -import com.bonus.common.core.utils.global.CommonConstant; -import com.bonus.common.core.utils.global.SystemGlobal; -import com.bonus.gateway.module.GatewayContext; +import com.bonus.common.core.utils.encryption.Sm3Util; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; +import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequestDecorator; import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.util.UriComponentsBuilder; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; -import java.lang.reflect.Field; import java.net.URI; - -import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE; - -/** - * 参数自动解密 - * 拦截 - * * @author bonus - */ +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Slf4j @Component public class AecDecryptParamFilter extends AbstractGatewayFilterFactory { @Value("${system.decryptEnabled}") - public boolean jaData; + public boolean decryptEnabled; - public final static String HEARD_NAME = "decrypt"; + public static final String HEADER_NAME = "decrypt"; + public static final String HMAC_HEADER_NAME = "Params-Hash"; @Override public GatewayFilter apply(Object config) { return (exchange, chain) -> { - ServerHttpRequest serverHttpRequest = exchange.getRequest(); - String head = serverHttpRequest.getHeaders().getFirst(HEARD_NAME); - if (StringUtils.isNotEmpty(head) && HEARD_NAME.equals(head)) { + if (!decryptEnabled) { + log.info("解密功能已禁用,直接继续过滤链。"); return chain.filter(exchange); } - if (!jaData) { - return chain.filter(exchange); - } - //get请求 默认 - if (HttpMethod.GET.matches(serverHttpRequest.getMethodValue())) {//如果是get - if (exchange.getRequest().getQueryParams().isEmpty()) {//如果参数是空的 - return chain.filter(exchange); - } else { - try { - updateRequestParam(exchange); - return chain.filter(exchange); - } catch (Exception e) { - log.error(e.toString(), e); - return CommonConstant.buildResponse(exchange, HttpStatus.BAD_REQUEST.value(), "请求参数异常"); - } - } - } - if (HttpMethod.DELETE.matches(serverHttpRequest.getMethodValue())) { + ServerHttpRequest request = exchange.getRequest(); + HttpMethod method = request.getMethod(); + if (method == null) { + log.error("请求方法为 null,无法处理请求。"); return chain.filter(exchange); } - HttpHeaders heard = serverHttpRequest.getHeaders(); - if (heard != null) { - Object object = heard.getFirst("Content-Type"); - if (object != null) { - String contentType = object.toString(); - if (contentType.contains(MULTIPART_FORM_DATA_VALUE)) { - return chain.filter(exchange); - } - } - } - byte[] decrypBytes; - GatewayContext gatewayContext = exchange.getAttribute(GatewayContext.CACHE_GATEWAY_CONTEXT); - if (StringUtils.isEmpty(gatewayContext.getCacheBody())) { - if (!exchange.getRequest().getQueryParams().isEmpty()) { - try { - updateRequestParam(exchange); - return chain.filter(exchange); - } catch (Exception e) { - log.error(e.toString(), e); - return CommonConstant.buildResponse(exchange, HttpStatus.BAD_REQUEST.value(), "请输入正确的请求参数"); - } - } - //强制加密 - // return CommonConstant.buildResponse(exchange, HttpStatus.BAD_REQUEST.value(), "请求参数不正确!"); - //未强制加密 - return chain.filter(exchange); - } try { - // 获取request body - String requestBody = gatewayContext.getCacheBody(); - String decryptMsg = AesCbcUtils.decrypt(requestBody); - gatewayContext.setCacheBody(decryptMsg); - decrypBytes = decryptMsg.getBytes(); + if (method == HttpMethod.GET) { + return handleGetRequest(exchange, chain); + } + return handleRequest(exchange, chain); } catch (Exception e) { - log.error("数据 解密失败:{}", e); - return CommonConstant.buildResponse(exchange, 201, "请求参数不正确!"); + log.error("处理请求时发生错误: {}", e.getMessage(), e); + exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); + return exchange.getResponse().setComplete(); } - // 根据解密后的参数重新构建请求 - DataBufferFactory dataBufferFactory = exchange.getResponse().bufferFactory(); - Flux bodyFlux = Flux.just(dataBufferFactory.wrap(decrypBytes)); - ServerHttpRequest newRequest = serverHttpRequest.mutate().uri(serverHttpRequest.getURI()).build(); - newRequest = new ServerHttpRequestDecorator(newRequest) { - @Override - public Flux getBody() { - return bodyFlux; - } - }; - HttpHeaders headers = new HttpHeaders(); - headers.putAll(exchange.getRequest().getHeaders()); - // 由于修改了传递参数,需要重新设置CONTENT_LENGTH,长度是字节长度,不是字符串长度 - int length = decrypBytes.length; - headers.remove(HttpHeaders.CONTENT_LENGTH); - headers.setContentLength(length); - newRequest = new ServerHttpRequestDecorator(newRequest) { - @Override - public HttpHeaders getHeaders() { - return headers; - } - }; - // 把解密后的数据重置到exchange自定义属性中,在之后的日志GlobalLogFilter从此处获取请求参数打印日志 - exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT, gatewayContext); - return chain.filter(exchange.mutate().request(newRequest).build()); }; } - - /** - * 修改前端传的参数 - */ - private void updateRequestParam(ServerWebExchange exchange) throws NoSuchFieldException, IllegalAccessException { - ServerHttpRequest request = exchange.getRequest(); - URI uri = request.getURI(); - //请求参数 - String query = uri.getQuery(); - if (StringUtils.isNotBlank(query)) { - //解密请求参数 - String param = AesCbcUtils.decrypt(query); - if (StringUtils.isEmpty(param)) { - throw new CaptchaException("请求参数不正确"); + private Mono handleGetRequest(ServerWebExchange exchange, GatewayFilterChain chain) { + try { + ServerWebExchange updatedExchange = updateRequestParam(exchange); + if (updatedExchange != null) { + return chain.filter(updatedExchange); + } else { + return chain.filter(exchange); } - //使用反射强行拿出 URI 的 query - Field targetQuery = uri.getClass().getDeclaredField("query"); - //授权 - targetQuery.setAccessible(true); - //重新设置参数 - targetQuery.set(uri, param); - + } catch (Exception e) { + log.error("处理 GET 请求时发生错误: {}", e.getMessage(), e); + exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); + return exchange.getResponse().setComplete(); } } + private Mono handleRequest(ServerWebExchange exchange, GatewayFilterChain chain) { + return DataBufferUtils.join(exchange.getRequest().getBody()) + .flatMap(dataBuffer -> { + byte[] body = new byte[dataBuffer.readableByteCount()]; + dataBuffer.read(body); + DataBufferUtils.release(dataBuffer); + String requestBody = new String(body, StandardCharsets.UTF_8); + // 去掉多余的引号(如果有) + if (requestBody.startsWith("\"") && requestBody.endsWith("\"")) { + requestBody = requestBody.substring(1, requestBody.length() - 1); + } + + String decryptedBody; + try { + String providedHmac = exchange.getRequest().getHeaders().getFirst(HMAC_HEADER_NAME); + integrityVerification(providedHmac, requestBody); + decryptedBody = AesCbcUtils.decrypt(requestBody); + } catch (Exception e) { + log.error("解密请求体时发生错误: {}", e.getMessage(), e); + exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); + return exchange.getResponse().setComplete(); + } + + DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory(); + DataBuffer newBody = bufferFactory.wrap(decryptedBody.getBytes(StandardCharsets.UTF_8)); + ServerHttpRequest newRequest = createNewRequest(exchange, newBody); + + return chain.filter(exchange.mutate().request(newRequest).build()); + }); + } + + private ServerHttpRequest createNewRequest(ServerWebExchange exchange, DataBuffer newBody) { + return new ServerHttpRequestDecorator(exchange.getRequest()) { + @Override + public Flux getBody() { + return Flux.just(newBody); + } + + @Override + public HttpHeaders getHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.putAll(exchange.getRequest().getHeaders()); + headers.remove(HttpHeaders.CONTENT_LENGTH); + headers.setContentLength(newBody.readableByteCount()); + return headers; + } + }; + } + + private ServerWebExchange updateRequestParam(ServerWebExchange exchange) throws NoSuchFieldException, IllegalAccessException { + ServerHttpRequest request = exchange.getRequest(); + URI uri = request.getURI(); + String query = uri.getQuery(); + if (StringUtils.isNotBlank(query)) { + String providedHmac = exchange.getRequest().getHeaders().getFirst(HMAC_HEADER_NAME); + integrityVerification(providedHmac, query); + String decryptedParam; + try { + decryptedParam = AesCbcUtils.decrypt(query); + } catch (Exception e) { + log.error("解密查询参数时发生错误: {}", e.getMessage(), e); + throw new CaptchaException("请求参数不正确"); + } + if (StringUtils.isEmpty(decryptedParam)) { + log.error("解密后的参数为空"); + throw new CaptchaException("请求参数不正确"); + } + Map> queryParams = Arrays.stream(decryptedParam.split("&")) + .map(param -> param.split("=")) + .collect(Collectors.toMap( + param -> param[0], + param -> Collections.singletonList(param[1]) + )); + URI newUri = UriComponentsBuilder.fromUri(uri) + .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParams)) + .build(true) + .toUri(); + + ServerHttpRequest newRequest = request.mutate().uri(newUri).build(); + + return exchange.mutate().request(newRequest).build(); + } + return null; + } + + /** + * 数据完整性校验 + * + * @param providedHmac 请求头中的 HMAC 值 + * @param query 请求参数 + */ + private void integrityVerification(String providedHmac, String query) { + if (providedHmac == null) { + log.error("请求头中缺少 Params-Hash"); + throw new CaptchaException("请求参数不正确"); + } + String encrypt = Sm3Util.encrypt(query); + log.debug("加密后的参数: {}", encrypt); + log.debug("请求头中的 Params-Hash: {}", providedHmac); + if (!encrypt.equals(providedHmac)) { + log.error("参数校验失败"); + throw new CaptchaException("请求参数不正确"); + } + } } diff --git a/bonus-gateway/src/main/java/com/bonus/gateway/filter/BlackListUrlFilter.java b/bonus-gateway/src/main/java/com/bonus/gateway/filter/BlackListUrlFilter.java index fb6e60c..dc4c82d 100644 --- a/bonus-gateway/src/main/java/com/bonus/gateway/filter/BlackListUrlFilter.java +++ b/bonus-gateway/src/main/java/com/bonus/gateway/filter/BlackListUrlFilter.java @@ -12,52 +12,45 @@ import com.bonus.common.core.utils.ServletUtils; /** * 黑名单过滤器 - * + * * @author bonus */ @Component -public class BlackListUrlFilter extends AbstractGatewayFilterFactory -{ +public class BlackListUrlFilter extends AbstractGatewayFilterFactory { @Value("${system.encryptEnabled}") - public boolean encryptEnabled; + public boolean encryptEnabled; + @Override - public GatewayFilter apply(Config config) - { + public GatewayFilter apply(Config config) { return (exchange, chain) -> { String url = exchange.getRequest().getURI().getPath(); - if (config.matchBlacklist(url)) - { - return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求地址不允许访问",encryptEnabled); + if (config.matchBlacklist(url)) { + return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求地址不允许访问", encryptEnabled); } return chain.filter(exchange); }; } - public BlackListUrlFilter() - { + public BlackListUrlFilter() { super(Config.class); } - public static class Config - { + public static class Config { private List blacklistUrl; private List blacklistUrlPattern = new ArrayList<>(); - public boolean matchBlacklist(String url) - { + public boolean matchBlacklist(String url) { return !blacklistUrlPattern.isEmpty() && blacklistUrlPattern.stream().anyMatch(p -> p.matcher(url).find()); } - public List getBlacklistUrl() - { + public List getBlacklistUrl() { return blacklistUrl; } - public void setBlacklistUrl(List blacklistUrl) - { + public void setBlacklistUrl(List blacklistUrl) { this.blacklistUrl = blacklistUrl; this.blacklistUrlPattern.clear(); this.blacklistUrl.forEach(url -> { diff --git a/bonus-modules/bonus-system/src/main/java/com/bonus/system/controller/SysUserController.java b/bonus-modules/bonus-system/src/main/java/com/bonus/system/controller/SysUserController.java index faf3b42..3b03919 100644 --- a/bonus-modules/bonus-system/src/main/java/com/bonus/system/controller/SysUserController.java +++ b/bonus-modules/bonus-system/src/main/java/com/bonus/system/controller/SysUserController.java @@ -45,13 +45,12 @@ import com.bonus.system.service.ISysUserService; /** * 用户信息 - * + * * @author bonus */ @RestController @RequestMapping("/user") -public class SysUserController extends BaseController -{ +public class SysUserController extends BaseController { @Autowired private ISysUserService userService; @@ -75,53 +74,53 @@ public class SysUserController extends BaseController */ @RequiresPermissions("system:user:list") @GetMapping("/list") - @SysLog(title = "用户管理", businessType = OperaType.QUERY,logType = 0,module = "系统管理->用户管理",details = "查询用户列表") + @SysLog(title = "用户管理", businessType = OperaType.QUERY, logType = 0, module = "系统管理->用户管理", details = "查询用户列表") public TableDataInfo list(SysUser user) { - try{ - startPage(); - List list = userService.selectUserList(user); - return getDataTable(list); - }catch (Exception e){ - logger.error(e.toString(),e); - } - return getDataTableError(new ArrayList<>()); + try { + startPage(); + List list = userService.selectUserList(user); + return getDataTable(list); + } catch (Exception e) { + logger.error(e.toString(), e); + } + return getDataTableError(new ArrayList<>()); } @RequiresPermissions("system:user:export") @PostMapping("/export") - @SysLog(title = "用户管理", businessType = OperaType.EXPORT,logType = 0,module = "系统管理->用户管理",details = "导出用户信息") + @SysLog(title = "用户管理", businessType = OperaType.EXPORT, logType = 0, module = "系统管理->用户管理", details = "导出用户信息") public void export(HttpServletResponse response, SysUser user) { - try{ - List list = userService.selectUserList(user); - ExcelUtil util = new ExcelUtil(SysUser.class); - util.exportExcel(response, list, "用户数据"); - }catch (Exception e){ - logger.error(e.toString(),e); - } + try { + List list = userService.selectUserList(user); + ExcelUtil util = new ExcelUtil(SysUser.class); + util.exportExcel(response, list, "用户数据"); + } catch (Exception e) { + logger.error(e.toString(), e); + } } @PostMapping("/importData") - @SysLog(title = "用户管理", businessType = OperaType.IMPORT,logType = 0,module = "系统管理->用户管理",details = "导入用户信息") + @SysLog(title = "用户管理", businessType = OperaType.IMPORT, logType = 0, module = "系统管理->用户管理", details = "导入用户信息") public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception { - try{ + try { ExcelUtil util = new ExcelUtil(SysUser.class); List userList = util.importExcel(file.getInputStream()); String operName = SecurityUtils.getUsername(); String message = userService.importUser(userList, updateSupport, operName); return success(message); - }catch (Exception e){ - logger.error(e.toString(),e); + } catch (Exception e) { + logger.error(e.toString(), e); } return error("系统异常,请联系管理员"); } @PostMapping("/importTemplate") public void importTemplate(HttpServletResponse response) throws IOException { - try{ + try { ExcelUtil util = new ExcelUtil(SysUser.class); util.importTemplateExcel(response, "用户数据"); - }catch (Exception e){ - logger.error(e.toString(),e); + } catch (Exception e) { + logger.error(e.toString(), e); } } @@ -130,11 +129,9 @@ public class SysUserController extends BaseController */ @InnerAuth @GetMapping("/info/{username}") - public R info(@PathVariable("username") String username) - { + public R info(@PathVariable("username") String username) { SysUser sysUser = userService.selectUserByUserName(username); - if (StringUtils.isNull(sysUser)) - { + if (StringUtils.isNull(sysUser)) { return R.fail("用户名或密码错误"); } // 角色集合 @@ -154,17 +151,14 @@ public class SysUserController extends BaseController */ @InnerAuth @PostMapping("/register") - public R register(@RequestBody SysUser sysUser) - { + public R register(@RequestBody SysUser sysUser) { String username = sysUser.getUserName(); final String stringTrue = "true"; final String configKeyRegisterUser = "sys.account.registerUser"; - if (!(stringTrue.equals(configService.selectConfigByKey(configKeyRegisterUser)))) - { + if (!(stringTrue.equals(configService.selectConfigByKey(configKeyRegisterUser)))) { return R.fail("当前系统没有开启注册功能!"); } - if (!userService.checkUserNameUnique(sysUser)) - { + if (!userService.checkUserNameUnique(sysUser)) { return R.fail("保存用户'" + username + "'失败,注册账号已存在"); } return R.ok(userService.registerUser(sysUser)); @@ -172,12 +166,12 @@ public class SysUserController extends BaseController /** * 获取用户信息 - * + * * @return 用户信息 */ @GetMapping("getInfo") public AjaxResult getInfo() { - try{ + try { SysUser user = userService.selectUserById(SecurityUtils.getUserId()); // 角色集合 Set roles = permissionService.getRolePermission(user); @@ -188,8 +182,8 @@ public class SysUserController extends BaseController ajax.put("roles", roles); ajax.put("permissions", permissions); return ajax; - }catch (Exception e){ - logger.error(e.toString(),e); + } catch (Exception e) { + logger.error(e.toString(), e); } return error("系统异常,请联系管理员"); } @@ -198,24 +192,23 @@ public class SysUserController extends BaseController * 根据用户编号获取详细信息 */ @RequiresPermissions("system:user:query") - @GetMapping(value = { "/", "/{userId}" }) + @GetMapping(value = {"/", "/{userId}"}) public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) { - try{ + try { userService.checkUserDataScope(userId); AjaxResult ajax = AjaxResult.success(); List roles = roleService.selectRoleAll(); ajax.put("roles", roles); ajax.put("posts", postService.selectPostAll()); - if (StringUtils.isNotNull(userId)) - { + if (StringUtils.isNotNull(userId)) { SysUser sysUser = userService.selectUserById(userId); ajax.put(AjaxResult.DATA_TAG, sysUser); ajax.put("postIds", postService.selectPostListByUserId(userId)); ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList())); } return ajax; - }catch (Exception e){ - logger.error(e.toString(),e); + } catch (Exception e) { + logger.error(e.toString(), e); } return error("系统异常,请联系管理员"); } @@ -225,32 +218,27 @@ public class SysUserController extends BaseController */ @RequiresPermissions("system:user:add") @PostMapping - @SysLog(title = "用户管理", businessType = OperaType.INSERT,logType = 0,module = "系统管理->用户管理",details = "新增用户信息") + @SysLog(title = "用户管理", businessType = OperaType.INSERT, logType = 0, module = "系统管理->用户管理", details = "新增用户信息") public AjaxResult add(@Validated @RequestBody SysUser user) { - try{ + try { deptService.checkDeptDataScope(user.getDeptId()); roleService.checkRoleDataScope(user.getRoleIds()); - if (!userService.checkUserNameUnique(user)) - { + if (!userService.checkUserNameUnique(user)) { return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); - } - else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) - { + } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); - } - else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) - { + } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); } String pwd = ValidateUtils.isPwd(user.getPassword()); - if(StringUtils.isNotEmpty(pwd)){ + if (StringUtils.isNotEmpty(pwd)) { return error("新增用户'" + user.getUserName() + "'失败," + pwd); } user.setCreateBy(SecurityUtils.getUsername()); user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); return toAjax(userService.insertUser(user)); - }catch (Exception e){ - logger.error(e.toString(),e); + } catch (Exception e) { + logger.error(e.toString(), e); } return error("系统异常,请联系管理员"); } @@ -260,29 +248,24 @@ public class SysUserController extends BaseController */ @RequiresPermissions("system:user:edit") @PutMapping - @SysLog(title = "用户管理", businessType = OperaType.UPDATE,logType = 0,module = "系统管理->用户管理",details = "修改用户信息") + @SysLog(title = "用户管理", businessType = OperaType.UPDATE, logType = 0, module = "系统管理->用户管理", details = "修改用户信息") public AjaxResult edit(@Validated @RequestBody SysUser user) { - try{ + try { userService.checkUserAllowed(user); userService.checkUserDataScope(user.getUserId()); deptService.checkDeptDataScope(user.getDeptId()); roleService.checkRoleDataScope(user.getRoleIds()); - if (!userService.checkUserNameUnique(user)) - { + if (!userService.checkUserNameUnique(user)) { return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在"); - } - else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) - { + } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); - } - else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) - { + } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); } user.setUpdateBy(SecurityUtils.getUsername()); return toAjax(userService.updateUser(user)); - }catch (Exception e){ - logger.error(e.toString(),e); + } catch (Exception e) { + logger.error(e.toString(), e); } return error("系统异常,请联系管理员"); } @@ -292,16 +275,16 @@ public class SysUserController extends BaseController */ @RequiresPermissions("system:user:remove") @DeleteMapping("/{userIds}") - @SysLog(title = "用户管理", businessType = OperaType.DELETE,logType = 0,module = "系统管理->用户管理",details = "删除用户信息") + @SysLog(title = "用户管理", businessType = OperaType.DELETE, logType = 0, module = "系统管理->用户管理", details = "删除用户信息") public AjaxResult remove(@PathVariable Long[] userIds) { - try{ - if (ArrayUtils.contains(userIds, SecurityUtils.getUserId())) { - return error("当前用户不能删除"); - } - return toAjax(userService.deleteUserByIds(userIds)); - }catch (Exception e){ - logger.error(e.toString(),e); - } + try { + if (ArrayUtils.contains(userIds, SecurityUtils.getUserId())) { + return error("当前用户不能删除"); + } + return toAjax(userService.deleteUserByIds(userIds)); + } catch (Exception e) { + logger.error(e.toString(), e); + } return error("系统异常,请联系管理员"); } @@ -310,16 +293,16 @@ public class SysUserController extends BaseController */ @RequiresPermissions("system:user:edit") @PutMapping("/resetPwd") - @SysLog(title = "用户管理", businessType = OperaType.UPDATE,logType = 0,module = "系统管理->用户管理",details = "重置用户密码") + @SysLog(title = "用户管理", businessType = OperaType.UPDATE, logType = 0, module = "系统管理->用户管理", details = "重置用户密码") public AjaxResult resetPwd(@RequestBody SysUser user) { - try{ + try { userService.checkUserAllowed(user); userService.checkUserDataScope(user.getUserId()); user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); user.setUpdateBy(SecurityUtils.getUsername()); return toAjax(userService.resetPwd(user)); - }catch (Exception e){ - logger.error(e.toString(),e); + } catch (Exception e) { + logger.error(e.toString(), e); } return error("系统异常,请联系管理员"); } @@ -329,15 +312,15 @@ public class SysUserController extends BaseController */ @RequiresPermissions("system:user:edit") @PutMapping("/changeStatus") - @SysLog(title = "用户管理", businessType = OperaType.UPDATE,logType = 0,module = "系统管理->用户管理",details = "修改用户状态") + @SysLog(title = "用户管理", businessType = OperaType.UPDATE, logType = 0, module = "系统管理->用户管理", details = "修改用户状态") public AjaxResult changeStatus(@RequestBody SysUser user) { - try{ + try { userService.checkUserAllowed(user); userService.checkUserDataScope(user.getUserId()); user.setUpdateBy(SecurityUtils.getUsername()); return toAjax(userService.updateUserStatus(user)); - }catch (Exception e){ - logger.error(e.toString(),e); + } catch (Exception e) { + logger.error(e.toString(), e); } return error("系统异常,请联系管理员"); } @@ -348,15 +331,15 @@ public class SysUserController extends BaseController @RequiresPermissions("system:user:query") @GetMapping("/authRole/{userId}") public AjaxResult authRole(@PathVariable("userId") Long userId) { - try{ + try { AjaxResult ajax = AjaxResult.success(); SysUser user = userService.selectUserById(userId); List roles = roleService.selectRolesByUserId(userId); ajax.put("user", user); ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); return ajax; - }catch (Exception e){ - logger.error(e.toString(),e); + } catch (Exception e) { + logger.error(e.toString(), e); } return error("系统异常,请联系管理员"); } @@ -366,15 +349,15 @@ public class SysUserController extends BaseController */ @RequiresPermissions("system:user:edit") @PutMapping("/authRole") - @SysLog(title = "用户管理", businessType = OperaType.GRANT,logType = 0,module = "系统管理->用户管理",details = "用户授权角色") + @SysLog(title = "用户管理", businessType = OperaType.GRANT, logType = 0, module = "系统管理->用户管理", details = "用户授权角色") public AjaxResult insertAuthRole(Long userId, Long[] roleIds) { - try{ + try { userService.checkUserDataScope(userId); roleService.checkRoleDataScope(roleIds); userService.insertUserAuth(userId, roleIds); return success(); - }catch (Exception e){ - logger.error(e.toString(),e); + } catch (Exception e) { + logger.error(e.toString(), e); } return error("系统异常,请联系管理员"); } @@ -385,10 +368,24 @@ public class SysUserController extends BaseController @RequiresPermissions("system:user:list") @GetMapping("/deptTree") public AjaxResult deptTree(SysDept dept) { - try{ + try { return success(deptService.selectDeptTreeList(dept)); - }catch (Exception e){ - logger.error(e.toString(),e); + } catch (Exception e) { + logger.error(e.toString(), e); + } + return error("系统异常,请联系管理员"); + } + + /** + * 修改用户审批状态 + */ + @RequiresPermissions("system:user:approval") + @PostMapping("/approvalStatus") + public AjaxResult approvalStatus(@RequestBody SysUser user) { + try { + return success(userService.approvalStatus(user.getUserId())); + } catch (Exception e) { + logger.error(e.toString(), e); } return error("系统异常,请联系管理员"); } diff --git a/bonus-modules/bonus-system/src/main/java/com/bonus/system/mapper/SysUserMapper.java b/bonus-modules/bonus-system/src/main/java/com/bonus/system/mapper/SysUserMapper.java index cc1317f..65eaaae 100644 --- a/bonus-modules/bonus-system/src/main/java/com/bonus/system/mapper/SysUserMapper.java +++ b/bonus-modules/bonus-system/src/main/java/com/bonus/system/mapper/SysUserMapper.java @@ -125,4 +125,6 @@ public interface SysUserMapper { * @return 结果 */ public SysUser checkEmailUnique(String email); + + Integer approvalStatus(Long userId); } diff --git a/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/ISysUserService.java b/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/ISysUserService.java index dbf29e0..debe848 100644 --- a/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/ISysUserService.java +++ b/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/ISysUserService.java @@ -1,7 +1,10 @@ package com.bonus.system.service; import java.util.List; + +import com.bonus.common.core.domain.R; import com.bonus.system.api.domain.SysUser; +import org.apache.poi.ss.formula.functions.T; /** * 用户 业务层 @@ -203,4 +206,6 @@ public interface ISysUserService * @return 结果 */ public String importUser(List userList, Boolean isUpdateSupport, String operName); + + R approvalStatus(Long userId); } diff --git a/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/impl/SysUserServiceImpl.java b/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/impl/SysUserServiceImpl.java index a06fb24..042078c 100644 --- a/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/impl/SysUserServiceImpl.java +++ b/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/impl/SysUserServiceImpl.java @@ -5,6 +5,8 @@ import java.util.List; import java.util.stream.Collectors; import javax.validation.Validator; +import com.bonus.common.core.domain.R; +import org.apache.poi.ss.formula.functions.T; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -519,4 +521,23 @@ public class SysUserServiceImpl implements ISysUserService { return successMsg.toString(); } + /** + * @param userId + * @return + */ + @Override + public R approvalStatus(Long userId) { + try { + Integer i = userMapper.approvalStatus(userId); + if (i > 0) { + return R.ok(); + } else { + return R.fail(); + } + } catch (Exception e) { + e.printStackTrace(); + return R.fail(); + } + } + } diff --git a/bonus-modules/bonus-system/src/main/resources/mapper/system/SysUserMapper.xml b/bonus-modules/bonus-system/src/main/resources/mapper/system/SysUserMapper.xml index 237da1d..97a0ee7 100644 --- a/bonus-modules/bonus-system/src/main/resources/mapper/system/SysUserMapper.xml +++ b/bonus-modules/bonus-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -24,6 +24,7 @@ + @@ -87,7 +88,8 @@