当前位置: 首页 > news >正文

辽宁沈阳建设工程信息网站域名注册的流程是什么

辽宁沈阳建设工程信息网站,域名注册的流程是什么,网站开发需要哪些人怎么分工,怎么做彩票平台网站吗目录 一、 加解密方式介绍 1.1 Hash算法加密 1.2. 对称加密 1.3 非对称加密 二、 我们要讲什么#xff1f; 三、 接口加解密 四、 数据加解密 一、 加解密方式介绍 所有的加密方式我们可以分为三类#xff1a;对称加密、非对称加密、Hash算法加密。 算法内部的具体实现…目录 一、 加解密方式介绍 1.1 Hash算法加密 1.2. 对称加密 1.3 非对称加密 二、 我们要讲什么 三、 接口加解密 四、 数据加解密 一、 加解密方式介绍 所有的加密方式我们可以分为三类对称加密、非对称加密、Hash算法加密。 算法内部的具体实现见(我们只是算法的搬运工)13种加密与解密算法【一】-CSDN博客 1.1 Hash算法加密 这种加密方式是一种不可逆的加密方式它通常用于验证数据的完整性(例如密码)。 例如MD5(严格的不可逆、单向加密、加盐)、Base64(严格说是一种编码转换、可以加解密) 1.2. 对称加密 这种加密方式就是在加密和解密的过程中都使用了一个相同的秘钥(不妨我们将其记作password(和密码同名-_-))。那么我们对数据的加密、解密都使用这个秘钥。特点是加解密速度快。缺点是被人知道秘钥就GG。 这种加密方式的算法例如DES、AES、SM4(国密4)…… 1.3 非对称加密 在这种加密的方式中会出现密钥对包括一个私钥和一个公钥。其中公钥和私钥无关(不能相互推出)。而实际上在双方之间进行数据的加密传输在每一方自己的操作中进行数据的解密会涉及到两对秘钥对。 我们看这个图就很清楚。我们将甲方比作是后端乙方比作是前端。 后端会有一对密钥对同理前端也会有一对密钥对。需要注意的是我们的公钥是可以被公布的(和私钥无关)即我们的数据被截获也无法解密。这样一来以后端为例后端持有前端的公钥当后端对前端返回数据的时候后端使用前端的公钥对数据进行加密。从而前端获取到数据后使用自己的私钥进行解密。同理前端给后端的数据也会使用后端的公钥进行加密后端接受到数据后就会使用后端的私钥进行解密。从而实现前后端之间数据的加密传输。 这种非对称加密方式的算法有RSA、SM2(国密2)…… 二、 我们要讲什么 我们先从前端给的一个请求说起。前端想要对着接口给后端一些数据从而让后端完成业务处理和持久化。很好好比一个登录注册的请求后端完成了这方面的接口。前端也对着接口发送数据然后被恶意人员截获好啊我们的数据都是明文恶意人员又把这个请求放走完成我们的业务逻辑与持久化。那么其实我们的这个账号就十分危险其他方面也各种意义的危险。 所以从这里我们不希望前后端之间的数据被其他人(各种其他人)所看见就是某种意义上不能裸奔所以前端给后端发的数据应该是被加密过的并且我们需要保证后端能够处理这段加密的数据。那么同理后端完成业务逻辑与持久化之后返回给前端的响应也不能裸奔也需要进行加密并且保证前端可以处理被加密的数据。 那么如果我们使用对称加密恶意人员各种操作总之搞到了我们的秘钥。其实还是裸奔。所以我们回去使用非对称加密。 好继续说上边的前端给后端加密后的数据在后端里我们先对数据进行了解密从而到达我们的业务逻辑处理。然后后端调用Mapper完成持久化存储到数据库中。现在又有一个技术高超的恶意人员黑到了我们的数据库。哈哈你的数据都是裸奔。这也就很不安全各种意义上的危险。 于是乎后端在调用Mapper的时候也应该对必要的字段进行加密所以后端会有个拦截器去看看“这家伙要存储的东西有没有是要加密的”。然后对数据加密之后存储到数据库中。那么拿出来的时候也一样后端还有个拦截器看看“有没有数据是被加密的”。之后对数据解密从而完成业务逻辑处理。 三、 接口加解密 我们讲解ruoyi项目中如下文件。 Request流只能读取一次 package org.dromara.common.encrypt.annotation;import java.lang.annotation.*;/*** 强制加密注解** author Michelle.Chung*/ Documented Target({ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) public interface ApiEncrypt {// 最终实现 ApiEncrypt 的注解用于加在 Controller 的方法上指定是否对请求进行解密对响应进行加密/*** 响应加密忽略默认不加密为 true 时加密*/boolean response() default false;}package org.dromara.common.encrypt.config;import jakarta.servlet.DispatcherType; import org.dromara.common.encrypt.filter.CryptoFilter; import org.dromara.common.encrypt.properties.ApiDecryptProperties; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean;/*** api 解密自动配置** author wdhcr*/ AutoConfiguration EnableConfigurationProperties(ApiDecryptProperties.class) // 获取接口加解密相关配置信息 ConditionalOnProperty(value api-decrypt.enabled, havingValue true) public class ApiDecryptAutoConfiguration {Bean // 注册过滤器 Filterpublic FilterRegistrationBeanCryptoFilter cryptoFilterRegistration(ApiDecryptProperties properties) {FilterRegistrationBeanCryptoFilter registration new FilterRegistrationBean();registration.setDispatcherTypes(DispatcherType.REQUEST);// 设置过滤器并且将配置类传给过滤器registration.setFilter(new CryptoFilter(properties));// 对全部路径进行过滤registration.addUrlPatterns(/*);registration.setName(cryptoFilter);// 优先级最高registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);return registration;} }package org.dromara.common.encrypt.filter;import cn.hutool.core.util.ObjectUtil; import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.dromara.common.core.constant.HttpStatus; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.encrypt.annotation.ApiEncrypt; import org.dromara.common.encrypt.properties.ApiDecryptProperties; import org.springframework.http.HttpMethod; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.HandlerExecutionChain; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import java.io.IOException;/*** Crypto 过滤器** author wdhcr*/ public class CryptoFilter implements Filter { // 实现过滤器重写其 init()、doFilter()、destroy() 方法private final ApiDecryptProperties properties;public CryptoFilter(ApiDecryptProperties properties) {this.properties properties;}Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 强转请求和响应HttpServletRequest servletRequest (HttpServletRequest) request;HttpServletResponse servletResponse (HttpServletResponse) response;// 这里是封装了一个方法用来 从请求中获取到注解判断是否为加密请求如果是那么就返回注解否则返回 null// 那么如果 不是加密请求null 就会跳过直接放行// 是的话 就会返回注解然后进行解密ApiEncrypt apiEncrypt this.getApiEncryptAnnotation(servletRequest);// apiEncrypt 不为空 说明 存在加密注解那么就进行解密// 且 响应加密那么 responseFlag 为 trueboolean responseFlag apiEncrypt ! null apiEncrypt.response();// 新建请求和响应的包装类ServletRequest requestWrapper null;ServletResponse responseWrapper null;EncryptResponseBodyWrapper responseBodyWrapper null;/*** 对请求的数据进行解密* 对响应的数据进行加密*/// 这里需要说明一下就是标识头是被 AES 加密过的// 首先看看是不是请求// 是否为 put 或者 post 请求换句话说DELETE 和 GET方法不用解密if (HttpMethod.PUT.matches(servletRequest.getMethod()) || HttpMethod.POST.matches(servletRequest.getMethod())) {// 是否存在加密标头这个就说明前端传来了密文String headerValue servletRequest.getHeader(properties.getHeaderFlag());if (StringUtils.isNotBlank(headerValue)) {// 请求解密将请求后端的私钥以及加密标头放入进行解密requestWrapper new DecryptRequestBodyWrapper(servletRequest,properties.getPrivateKey(), properties.getHeaderFlag());} else {// 就是说我们是没有看到加密标头但是又存在加密注解那么就抛出异常if (ObjectUtil.isNotNull(apiEncrypt)) {// 获取 异常处理器 然后抛出异常HandlerExceptionResolver exceptionResolver SpringUtils.getBean(handlerExceptionResolver, HandlerExceptionResolver.class);exceptionResolver.resolveException(servletRequest, servletResponse, null,new ServiceException(没有访问权限请联系管理员授权, HttpStatus.FORBIDDEN));return;}// 没有加密注解没有加密标头那么直接放行这个请求// 其实到这里 对请求来说 就结束了因为没有加密注解所以 responseFlag 为 false直接放行}}// 判断是否响应加密if (responseFlag) {// 对应的响应内容进行包装加密// 这一步只是 对 response 进行包装并没有对 response 进行加密因为 下边还有判断 是不是直接放行responseBodyWrapper new EncryptResponseBodyWrapper(servletResponse);responseWrapper responseBodyWrapper;}// 如果 requestWrapper 和 responseWrapper 都为空那么直接放行chain.doFilter(ObjectUtil.defaultIfNull(requestWrapper, request),ObjectUtil.defaultIfNull(responseWrapper, response));// 不为空且响应加密那么对 responseBodyWrapper 进行加密处理if (responseFlag) {// 重置 responseservletResponse.reset();// 对原始内容加密将响应后端的公钥以及加密标头放入进行加密String encryptContent responseBodyWrapper.getEncryptContent(servletResponse, properties.getPublicKey(), properties.getHeaderFlag());// 对加密后的内容写出servletResponse.getWriter().write(encryptContent);}}/*** 获取 ApiEncrypt 注解*/private ApiEncrypt getApiEncryptAnnotation(HttpServletRequest servletRequest) {RequestMappingHandlerMapping handlerMapping SpringUtils.getBean(requestMappingHandlerMapping, RequestMappingHandlerMapping.class);// 获取注解try {HandlerExecutionChain mappingHandler handlerMapping.getHandler(servletRequest);if (ObjectUtil.isNotNull(mappingHandler)) {Object handler mappingHandler.getHandler();if (ObjectUtil.isNotNull(handler)) {// 从handler获取注解if (handler instanceof HandlerMethod handlerMethod) {return handlerMethod.getMethodAnnotation(ApiEncrypt.class);}}}} catch (Exception e) {throw new RuntimeException(e);}return null;}Overridepublic void destroy() {} }package org.dromara.common.encrypt.filter;import cn.hutool.core.io.IoUtil; import jakarta.servlet.ReadListener; import jakarta.servlet.ServletInputStream; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequestWrapper; import org.dromara.common.core.constant.Constants; import org.dromara.common.encrypt.utils.EncryptUtils; import org.springframework.http.MediaType;import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets;/*** 解密请求参数工具类** author wdhcr*/ public class DecryptRequestBodyWrapper extends HttpServletRequestWrapper {// 存储请求体以便能够重复读取private final byte[] body;public DecryptRequestBodyWrapper(HttpServletRequest request, String privateKey, String headerFlag) throws IOException {super(request);// 以下的操作使得最终 被加密的body 被解密出来// body 是通过 AES 加密// 只有我们获得了 AES 密码 我们才可以 解密 body// 根据请求头的 headerFlag 获取到 RSA 加密后的 AES 密码String headerRsa request.getHeader(headerFlag);// 将 AES 密码从 RSA 解密出来String decryptAes EncryptUtils.decryptByRsa(headerRsa, privateKey);// 将 AES 密码从 Base64 解密出来String aesPassword EncryptUtils.decryptByBase64(decryptAes);// 设置 请求的编码格式request.setCharacterEncoding(Constants.UTF8);// 读取请求体byte[] readBytes IoUtil.readBytes(request.getInputStream(), false);String requestBody new String(readBytes, StandardCharsets.UTF_8);// 将 body 从 AES 解密出来String decryptBody EncryptUtils.decryptByAes(requestBody, aesPassword);body decryptBody.getBytes(StandardCharsets.UTF_8);}Overridepublic BufferedReader getReader() {return new BufferedReader(new InputStreamReader(getInputStream()));}Overridepublic int getContentLength() {return body.length;}Overridepublic long getContentLengthLong() {return body.length;}Overridepublic String getContentType() {return MediaType.APPLICATION_JSON_VALUE;}Overridepublic ServletInputStream getInputStream() {final ByteArrayInputStream bais new ByteArrayInputStream(body);return new ServletInputStream() {Overridepublic int read() {return bais.read();}Overridepublic int available() {return body.length;}Overridepublic boolean isFinished() {return false;}Overridepublic boolean isReady() {return false;}Overridepublic void setReadListener(ReadListener readListener) {}};} }package org.dromara.common.encrypt.filter;import cn.hutool.core.util.RandomUtil; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.WriteListener; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponseWrapper; import org.dromara.common.encrypt.utils.EncryptUtils;import java.io.*; import java.nio.charset.StandardCharsets;/*** 加密响应参数包装类** author Michelle.Chung*/ public class EncryptResponseBodyWrapper extends HttpServletResponseWrapper {private final ByteArrayOutputStream byteArrayOutputStream;private final ServletOutputStream servletOutputStream;private final PrintWriter printWriter;public EncryptResponseBodyWrapper(HttpServletResponse response) throws IOException {super(response);// 新建一个输出流this.byteArrayOutputStream new ByteArrayOutputStream();this.servletOutputStream this.getOutputStream();this.printWriter new PrintWriter(new OutputStreamWriter(byteArrayOutputStream));}Overridepublic PrintWriter getWriter() {return printWriter;}Overridepublic void flushBuffer() throws IOException {if (servletOutputStream ! null) {servletOutputStream.flush();}if (printWriter ! null) {printWriter.flush();}}Overridepublic void reset() {byteArrayOutputStream.reset();}public byte[] getResponseData() throws IOException {flushBuffer();return byteArrayOutputStream.toByteArray();}public String getContent() throws IOException {flushBuffer();return byteArrayOutputStream.toString();}/*** 获取加密内容** param servletResponse response* param publicKey RSA公钥 (用于加密 AES 秘钥)* param headerFlag 请求头标志* return 加密内容* throws IOException*/public String getEncryptContent(HttpServletResponse servletResponse, String publicKey, String headerFlag) throws IOException {// 生成秘钥String aesPassword RandomUtil.randomString(32);// 秘钥使用 Base64 编码String encryptAes EncryptUtils.encryptByBase64(aesPassword);// Rsa 公钥加密 Base64 编码String encryptPassword EncryptUtils.encryptByRsa(encryptAes, publicKey);// 设置响应头servletResponse.addHeader(Access-Control-Expose-Headers, headerFlag);servletResponse.setHeader(headerFlag, encryptPassword);servletResponse.setHeader(Access-Control-Allow-Origin, *);servletResponse.setHeader(Access-Control-Allow-Methods, *);servletResponse.setCharacterEncoding(StandardCharsets.UTF_8.toString());// 获取原始内容String originalBody this.getContent();// 对内容进行加密return EncryptUtils.encryptByAes(originalBody, aesPassword);}Overridepublic ServletOutputStream getOutputStream() throws IOException {return new ServletOutputStream() {Overridepublic boolean isReady() {return false;}Overridepublic void setWriteListener(WriteListener writeListener) {}Overridepublic void write(int b) throws IOException {byteArrayOutputStream.write(b);}Overridepublic void write(byte[] b) throws IOException {byteArrayOutputStream.write(b);}Overridepublic void write(byte[] b, int off, int len) throws IOException {byteArrayOutputStream.write(b, off, len);}};}}四、 数据加解密 我们讲解ruoyi中如下文件 package org.dromara.common.encrypt.annotation;import org.dromara.common.encrypt.enumd.AlgorithmType; import org.dromara.common.encrypt.enumd.EncodeType;import java.lang.annotation.*;/*** 字段加密注解** author 老马*/ Documented Inherited Target({ElementType.FIELD}) Retention(RetentionPolicy.RUNTIME) public interface EncryptField { // 最终我们就是在字段上加这个注解然后通过反射获取到注解信息然后对字段进行加密解密/*** 加密算法*/AlgorithmType algorithm() default AlgorithmType.DEFAULT;/*** 秘钥。AES、SM4需要*/String password() default ; // 处理对称加密的秘钥// 下边两个是非对称加密的秘钥/*** 公钥。RSA、SM2需要*/String publicKey() default ;/*** 私钥。RSA、SM2需要*/String privateKey() default ;// 编码方式/*** 编码方式。对加密算法为BASE64的不起作用*/EncodeType encode() default EncodeType.DEFAULT;}package org.dromara.common.encrypt.config;import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties; import lombok.extern.slf4j.Slf4j; import org.dromara.common.encrypt.core.EncryptorManager; import org.dromara.common.encrypt.interceptor.MybatisDecryptInterceptor; import org.dromara.common.encrypt.interceptor.MybatisEncryptInterceptor; import org.dromara.common.encrypt.properties.EncryptorProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean;/*** 加解密配置** author 老马* version 4.6.0*/ AutoConfiguration(after MybatisPlusAutoConfiguration.class) // 需在 MybatisPlusAutoConfiguration 之后加载// 使用这个注解会自动注入到 IoC 容器 EnableConfigurationProperties(EncryptorProperties.class) // 加载配置文件 ConditionalOnProperty(value mybatis-encryptor.enable, havingValue true) // 只有配置了// mybatis-encryptor.enabletrue 时才// 会创建 Bean Slf4j public class EncryptorAutoConfiguration {Autowired // 获取配置文件成为 Beanprivate EncryptorProperties properties;// 注入 EncryptorManager 加密管理器// 当项目一启动就会把 EncryptorManager 加载到 IoC 容器中Beanpublic EncryptorManager encryptorManager(MybatisPlusProperties mybatisPlusProperties) {return new EncryptorManager(mybatisPlusProperties.getTypeAliasesPackage());}// 加密拦截器Beanpublic MybatisEncryptInterceptor mybatisEncryptInterceptor(EncryptorManager encryptorManager) {return new MybatisEncryptInterceptor(encryptorManager, properties);}// 解密拦截器Beanpublic MybatisDecryptInterceptor mybatisDecryptInterceptor(EncryptorManager encryptorManager) {return new MybatisDecryptInterceptor(encryptorManager, properties);}} package org.dromara.common.encrypt.properties;import org.dromara.common.encrypt.enumd.AlgorithmType; import org.dromara.common.encrypt.enumd.EncodeType; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties;/*** 加解密属性配置类** author 老马* version 4.6.0*/ Data ConfigurationProperties(prefix mybatis-encryptor) // 根据前缀匹配 public class EncryptorProperties {/*** 过滤开关*/private Boolean enable;/*** 默认算法*/private AlgorithmType algorithm;/*** 安全秘钥*/private String password;/*** 公钥*/private String publicKey;/*** 私钥*/private String privateKey;/*** 编码方式base64/hex*/private EncodeType encode;}package org.dromara.common.encrypt.interceptor;import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.executor.resultset.ResultSetHandler; import org.apache.ibatis.plugin.*; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.encrypt.annotation.EncryptField; import org.dromara.common.encrypt.core.EncryptContext; import org.dromara.common.encrypt.core.EncryptorManager; import org.dromara.common.encrypt.enumd.AlgorithmType; import org.dromara.common.encrypt.enumd.EncodeType; import org.dromara.common.encrypt.properties.EncryptorProperties;import java.lang.reflect.Field; import java.sql.Statement; import java.util.*;/*** 出参解密拦截器** author 老马* version 4.6.0*/ Slf4j Intercepts({Signature(type ResultSetHandler.class,method handleResultSets,args {Statement.class}) }) // 这个意思是拦截 目标为ResultSetHandler.class 拦截结果集// 方法名为handleResultSets// 参数为Statement.class AllArgsConstructor public class MybatisDecryptInterceptor implements Interceptor {private final EncryptorManager encryptorManager;private final EncryptorProperties defaultProperties;Overridepublic Object intercept(Invocation invocation) throws Throwable {// 拦截到结果集Object result invocation.proceed();if (result null) {return null;}// 如果结果集不空就将结果集解密后返回。decryptHandler(result);return result;}/*** 解密对象** param sourceObject 待加密对象*/private void decryptHandler(Object sourceObject) {if (ObjectUtil.isNull(sourceObject)) {return;}if (sourceObject instanceof Map?, ? map) {new HashSet(map.values()).forEach(this::decryptHandler);return;}if (sourceObject instanceof List? list) {if(CollUtil.isEmpty(list)) {return;}// 判断第一个元素是否含有注解。如果没有直接返回提高效率Object firstItem list.get(0);if (ObjectUtil.isNull(firstItem) || CollUtil.isEmpty(encryptorManager.getFieldCache(firstItem.getClass()))) {return;}list.forEach(this::decryptHandler);return;}// 不在缓存中的类,就是没有加密注解的类(当然也有可能是typeAliasesPackage写错)SetField fields encryptorManager.getFieldCache(sourceObject.getClass());if(ObjectUtil.isNull(fields)){return;}try {for (Field field : fields) {field.set(sourceObject, this.decryptField(Convert.toStr(field.get(sourceObject)), field));}} catch (Exception e) {log.error(处理解密字段时出错, e);}}/*** 字段值进行加密。通过字段的批注注册新的加密算法** param value 待加密的值* param field 待加密字段* return 加密后结果*/private String decryptField(String value, Field field) {if (ObjectUtil.isNull(value)) {return null;}EncryptField encryptField field.getAnnotation(EncryptField.class);EncryptContext encryptContext new EncryptContext();encryptContext.setAlgorithm(encryptField.algorithm() AlgorithmType.DEFAULT ? defaultProperties.getAlgorithm() : encryptField.algorithm());encryptContext.setEncode(encryptField.encode() EncodeType.DEFAULT ? defaultProperties.getEncode() : encryptField.encode());encryptContext.setPassword(StringUtils.isBlank(encryptField.password()) ? defaultProperties.getPassword() : encryptField.password());encryptContext.setPrivateKey(StringUtils.isBlank(encryptField.privateKey()) ? defaultProperties.getPrivateKey() : encryptField.privateKey());encryptContext.setPublicKey(StringUtils.isBlank(encryptField.publicKey()) ? defaultProperties.getPublicKey() : encryptField.publicKey());return this.encryptorManager.decrypt(value, encryptContext);}Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}Overridepublic void setProperties(Properties properties) {} }package org.dromara.common.encrypt.interceptor;import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.executor.parameter.ParameterHandler; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Signature; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.encrypt.annotation.EncryptField; import org.dromara.common.encrypt.core.EncryptContext; import org.dromara.common.encrypt.core.EncryptorManager; import org.dromara.common.encrypt.enumd.AlgorithmType; import org.dromara.common.encrypt.enumd.EncodeType; import org.dromara.common.encrypt.properties.EncryptorProperties; import org.springframework.web.servlet.HandlerInterceptor;import java.lang.reflect.Field; import java.sql.PreparedStatement; import java.util.*;/*** 入参加密拦截器** author 老马* version 4.6.0*/ Slf4j Intercepts({Signature(type ParameterHandler.class,method setParameters,args {PreparedStatement.class}) }) // 这个意思是拦截 目标为ParameterHandler.class 拦截参数处理// 方法名为setParameters// 参数为PreparedStatement.class AllArgsConstructor public class MybatisEncryptInterceptor implements Interceptor { // 继承Interceptor接口插件需要实现这个接口// 而我们平常写的拦截器是继承了 HandlerInterceptor 接口// 实现 Mybatis 自定义插件private final EncryptorManager encryptorManager;private final EncryptorProperties defaultProperties;Override// 这个是核心方法用于实现拦截逻辑public Object intercept(Invocation invocation) throws Throwable {return invocation;}Override// 这个方法用于对目标进行包装返回一个代理对象public Object plugin(Object target) {// 拦截器只对ParameterHandler进行加密if (target instanceof ParameterHandler parameterHandler) {// 获得参数 -- 待加密对象Object parameterObject parameterHandler.getParameterObject();if (ObjectUtil.isNotNull(parameterObject) !(parameterObject instanceof String)) {// 对参数加密进行加密this.encryptHandler(parameterObject);}}return target;}/*** 加密对象** param sourceObject 待加密对象*/private void encryptHandler(Object sourceObject) {// 如果对象为空直接返回if (ObjectUtil.isNull(sourceObject)) {return;}// 判断是否为map如果是就递归加密if (sourceObject instanceof Map?, ? map) {new HashSet(map.values()).forEach(this::encryptHandler);return;}// 判断是否为list如果是就递归加密if (sourceObject instanceof List? list) {if(CollUtil.isEmpty(list)) {return;}// 判断第一个元素是否含有注解。如果没有直接返回提高效率// List中放的是对象 它们的字段都相同 所以只需要判断第一个元素即可Object firstItem list.get(0);if (ObjectUtil.isNull(firstItem) || CollUtil.isEmpty(encryptorManager.getFieldCache(firstItem.getClass()))) {return;}list.forEach(this::encryptHandler);return;}// 不在缓存中的类,就是没有加密注解的类(当然也有可能是typeAliasesPackage写错)SetField fields encryptorManager.getFieldCache(sourceObject.getClass());if(ObjectUtil.isNull(fields)){return;}try {// 对加密字段进行加密for (Field field : fields) {field.set(sourceObject, this.encryptField(Convert.toStr(field.get(sourceObject)), field));}} catch (Exception e) {log.error(处理加密字段时出错, e);}}/*** 字段值进行加密。通过字段的批注注册新的加密算法** param value 待加密的值* param field 待加密字段* return 加密后结果*/private String encryptField(String value, Field field) {if (ObjectUtil.isNull(value)) {return null;}EncryptField encryptField field.getAnnotation(EncryptField.class);// 设置加密上下文EncryptContext encryptContext new EncryptContext();encryptContext.setAlgorithm(encryptField.algorithm() AlgorithmType.DEFAULT ? defaultProperties.getAlgorithm() : encryptField.algorithm());encryptContext.setEncode(encryptField.encode() EncodeType.DEFAULT ? defaultProperties.getEncode() : encryptField.encode());encryptContext.setPassword(StringUtils.isBlank(encryptField.password()) ? defaultProperties.getPassword() : encryptField.password());encryptContext.setPrivateKey(StringUtils.isBlank(encryptField.privateKey()) ? defaultProperties.getPrivateKey() : encryptField.privateKey());encryptContext.setPublicKey(StringUtils.isBlank(encryptField.publicKey()) ? defaultProperties.getPublicKey() : encryptField.publicKey());// 进行加密return this.encryptorManager.encrypt(value, encryptContext);}Overridepublic void setProperties(Properties properties) {} }package org.dromara.common.encrypt.core;import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReflectUtil; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.io.Resources; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.encrypt.annotation.EncryptField; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.type.ClassMetadata; import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.util.ClassUtils;import java.lang.reflect.Field; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors;/*** 加密管理类** author 老马* version 4.6.0*/ Slf4j NoArgsConstructor public class EncryptorManager {/*** 缓存加密器*/// key:加密配置value加密执行者MapEncryptContext, IEncryptor encryptorMap new ConcurrentHashMap();/*** 类加密字段缓存*/// key:实体类value加密字段集合MapClass?, SetField fieldCache new ConcurrentHashMap();/*** 构造方法传入类加密字段缓存** param typeAliasesPackage 实体类包*/public EncryptorManager(String typeAliasesPackage) {// 当前项目启动扫描实体类包获取加密字段scanEncryptClasses(typeAliasesPackage);}/*** 获取类加密字段缓存*/public SetField getFieldCache(Class? sourceClazz) {if (ObjectUtil.isNotNull(fieldCache)) {return fieldCache.get(sourceClazz);}return null;}/*** 注册加密执行者到缓存** param encryptContext 加密执行者需要的相关配置参数*/public IEncryptor registAndGetEncryptor(EncryptContext encryptContext) {if (encryptorMap.containsKey(encryptContext)) {return encryptorMap.get(encryptContext);}// 根据算法获取加密执行者IEncryptor encryptor ReflectUtil.newInstance(encryptContext.getAlgorithm().getClazz(), encryptContext);encryptorMap.put(encryptContext, encryptor);return encryptor;}/*** 移除缓存中的加密执行者** param encryptContext 加密执行者需要的相关配置参数*/public void removeEncryptor(EncryptContext encryptContext) {this.encryptorMap.remove(encryptContext);}/*** 根据配置进行加密。会进行本地缓存对应的算法和对应的秘钥信息。** param value 待加密的值* param encryptContext 加密相关的配置信息*/public String encrypt(String value, EncryptContext encryptContext) {IEncryptor encryptor this.registAndGetEncryptor(encryptContext);return encryptor.encrypt(value, encryptContext.getEncode());}/*** 根据配置进行解密** param value 待解密的值* param encryptContext 加密相关的配置信息*/public String decrypt(String value, EncryptContext encryptContext) {IEncryptor encryptor this.registAndGetEncryptor(encryptContext);return encryptor.decrypt(value);}/*** 通过 typeAliasesPackage 设置的扫描包 扫描缓存实体*/private void scanEncryptClasses(String typeAliasesPackage) {PathMatchingResourcePatternResolver resolver new PathMatchingResourcePatternResolver();CachingMetadataReaderFactory factory new CachingMetadataReaderFactory();// 获取所有扫描包的路径String[] packagePatternArray StringUtils.splitPreserveAllTokens(typeAliasesPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);String classpath ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX;try {// 对每个路径下的包进行扫描for (String packagePattern : packagePatternArray) {String path ClassUtils.convertClassNameToResourcePath(packagePattern);Resource[] resources resolver.getResources(classpath path /*.class);for (Resource resource : resources) {// 获取类元数据获取类名如果有加密注解则加入缓存ClassMetadata classMetadata factory.getMetadataReader(resource).getClassMetadata();Class? clazz Resources.classForName(classMetadata.getClassName());// 封装方法获取加密字段集合SetField encryptFieldSet getEncryptFieldSetFromClazz(clazz);if (CollUtil.isNotEmpty(encryptFieldSet)) {fieldCache.put(clazz, encryptFieldSet);}}}} catch (Exception e) {log.error(初始化数据安全缓存时出错:{}, e.getMessage());}}/*** 获得一个类的加密字段集合*/private SetField getEncryptFieldSetFromClazz(Class? clazz) {SetField fieldSet new HashSet();// 判断clazz如果是接口,内部类,匿名类就直接返回if (clazz.isInterface() || clazz.isMemberClass() || clazz.isAnonymousClass()) {return fieldSet;}while (clazz ! null) {Field[] fields clazz.getDeclaredFields();fieldSet.addAll(Arrays.asList(fields));clazz clazz.getSuperclass();}fieldSet fieldSet.stream().filter(field -field.isAnnotationPresent(EncryptField.class) field.getType() String.class).collect(Collectors.toSet());for (Field field : fieldSet) {field.setAccessible(true);}return fieldSet;}}
http://www.dnsts.com.cn/news/7380.html

相关文章:

  • 平台网站 备案吗wordpress绑定手机号
  • 整站优化的公司自己能搞定吗?
  • 服务器网站过多对排名静态网站开发一体化课程
  • 电子商务网站建设内涵ps网页排版设计
  • 北京网站建设方案排名网站怎么增加关键词库
  • 凡科网站可以做自适应的吗网站制作公司网站源码
  • 公司设计网站需要多久店铺推广方法
  • 网站后台管理密码忘了wordpress 视频
  • 做导航网站seo 网站制作
  • 做汽配外贸是在哪个网站做企查查网页版
  • 郴州市住房建设局门户网站南京网站设计公司哪家好
  • 赛扬e3300做网站wordpress 5编辑器使用
  • 基于j2ee的网站开发设计开题报告线上推广渠道主要有哪些
  • 网站 用户体验的重要性南京建企业网站哪家好
  • 湖南网站设计费用国外网站加速器
  • 介绍一个电影的网站模板下载英特尔nuc做网站服务器
  • 东莞做网站首选泉州台商区建设局网站
  • 表格如何给网站做链接地址查询食品注册商标查询官网
  • 网站首页锚文本建设网站个人银行
  • 网站推广服务商百度关键词排名技术
  • 专业网站建设公司兴田德润优惠吗济源网络推广
  • 丹阳网站优化怎么做分销平台
  • 做网站需要什么cailiao各大网站流量排名
  • 电商网站建设服务网页设计入门与提高
  • 济南网站怎么做网站常见结构有那些
  • 电脑手机网站制作浙江高端网站建设
  • 做外墙资料的网站wordpress footer 插件
  • 建站优化公司杭州微网站开发公司
  • 商丘做微信网站sqwyy如何给网站流量来源做标记通过在网址后边加问号?
  • 邢台建设局网站网站维护好的方法