昆明网站搜索引擎优化,学校网站的建设目标是什么,黄骅市属于哪个省哪个市,国外做电商网站背景
最近项目要有向外部提供服务的能力#xff0c;但是考虑到数据安全问题#xff0c;要对接口进行加解密#xff1b;实现加解密的方案有很多#xff0c;比如过滤器、拦截器、继承RequestResponseBodyMethodProcessor什么的#xff0c;不过我最近正在了解ResponseBodyAd…背景
最近项目要有向外部提供服务的能力但是考虑到数据安全问题要对接口进行加解密实现加解密的方案有很多比如过滤器、拦截器、继承RequestResponseBodyMethodProcessor什么的不过我最近正在了解ResponseBodyAdvice RequestBodyAdvice这俩注解本着在实践中应用的目的就准备使用这两个注解来实现加解密功能。 然而配置好后请求怎么都进不到这两个注解的类里。摸索了一天的时间RestController 和ResponseBody 都加了也确认已经扫描进容器中管理了可就是无法生效。
原因
后来发现项目中之前有对所有的controller进行返回结果的统一包装使用的是继承RequestResponseBodyMethodProcessor类来实现 刚刚ResponseBodyAdvice和RequestBodyAdvice一直无法生效就在RequestResponseBodyMethodProcessor这里面做了加密的动作后来不经意间把这个类在WebMvcConfigurer中导入的代码注掉了惊奇的发现ResponseBodyAdvice RequestBodyAdvice这俩注解生效了。 所以初步定位 ResponseBodyAdvice RequestBodyAdvice 和RequestResponseBodyMethodProcessor 会冲突导致不生效。
解决
RequestResponseBodyMethodProcessor 里的逻辑抽取到ResponseBodyAdvice里本来这个也是对返回结果进行增强的所以放到这里也非常合理。 同时扩展了加密的逻辑。
核心代码 ControllerAdvice
public class ResponseProcessor implements ResponseBodyAdviceObject {private ObjectMapper om new ObjectMapper();AutowiredEncryptProperties encryptProperties;Overridepublic boolean supports(MethodParameter methodParameter, Class? extends HttpMessageConverter? aClass) {return methodParameter.hasMethodAnnotation(Encrypt.class);}Overridepublic Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class? extends HttpMessageConverter? aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {byte[] keyBytes encryptProperties.getKey().getBytes();try {if(!methodParameter.hasMethodAnnotation(NoResponseWrapperAnnotation.class)){body new ResponseWrapper(body);}body AESUtils.encrypt(JSONObject.toJSONString(body),encryptProperties.getKey());} catch (Exception e) {e.printStackTrace();}return body;}
}
java
ControllerAdvice
public class RequestProcessor extends RequestBodyAdviceAdapter {Autowiredprivate EncryptProperties encryptProperties;Overridepublic boolean supports(MethodParameter methodParameter, Type targetType, Class? extends HttpMessageConverter? converterType) {return methodParameter.hasMethodAnnotation(Decrypt.class) || methodParameter.hasParameterAnnotation(Decrypt.class);}Overridepublic HttpInputMessage beforeBodyRead(final HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class? extends HttpMessageConverter? converterType) throws IOException {byte[] body new byte[inputMessage.getBody().available()];inputMessage.getBody().read(body);try {String decrypt AESUtils.decrypt(new String(body), encryptProperties.getKey());final ByteArrayInputStream bais new ByteArrayInputStream(decrypt.getBytes());return new HttpInputMessage() {Overridepublic InputStream getBody() throws IOException {return bais;}Overridepublic HttpHeaders getHeaders() {return inputMessage.getHeaders();}};} catch (Exception e) {e.printStackTrace();}return super.beforeBodyRead(inputMessage, parameter, targetType, converterType);}
}
java
public class AESUtils {private static final String KEY_ALGORITHM AES;private static final String DEFAULT_CIPHER_ALGORITHM AES/ECB/PKCS5Padding;//默认的加密算法public static String getKey(int len){if(len % 16 ! 0){System.out.println(长度要为16的整数倍);return null;}char[] chars 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.toCharArray();char[] uuid new char[len];if (len 0) {for (int i 0; i len; i) {int x (int) (Math.random() * (len - 0 1) 0);uuid[i] chars[x % chars.length];}}return new String(uuid);}public static String byteToHexString(byte[] bytes){StringBuffer sb new StringBuffer();for (int i 0; i bytes.length; i) {String strHexInteger.toHexString(bytes[i]);if(strHex.length() 3){sb.append(strHex.substring(6));} else {if(strHex.length() 2){sb.append(0 strHex);} else {sb.append(strHex);}}}return sb.toString();}/*** AES 加密操作** param content 待加密内容* param key 加密密码* return 返回Base64转码后的加密数据*/public static String encrypt(String content, String key) {try {Cipher cipher Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器byte[] byteContent content.getBytes(utf-8);cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));// 初始化为加密模式的密码器byte[] result cipher.doFinal(byteContent);// 加密return org.apache.commons.codec.binary.Base64.encodeBase64String(result);//通过Base64转码返回} catch (Exception ex) {ex.printStackTrace();}return null;}/*** AES 解密操作** param content* param key* return*/public static String decrypt(String content, String key) {try {//实例化Cipher cipher Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);//使用密钥初始化设置为解密模式cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));//执行操作byte[] result cipher.doFinal(org.apache.commons.codec.binary.Base64.decodeBase64(content));return new String(result, utf-8);} catch (Exception ex) {ex.printStackTrace();}return null;}private static SecretKeySpec getSecretKey(final String key) throws UnsupportedEncodingException {//返回生成指定算法密钥生成器的 KeyGenerator 对象
// KeyGenerator kg null;// kg KeyGenerator.getInstance(KEY_ALGORITHM);
//
// //AES 要求密钥长度为 128
// kg.init(128, new SecureRandom(key.getBytes()));
//
// //生成一个密钥
// SecretKey secretKey kg.generateKey();return new SecretKeySpec(Arrays.copyOf(key.getBytes(utf-8), 16), KEY_ALGORITHM);// 转换为AES专用密钥}
}