java 请求加密_如何对Java请求的@requestBody前端加密后端解密?

背景

随着 Spring Boot 使用越来越广泛,Spring Boot 已经成为 Java 程序员面试的知识点,很多同学对 Spring Boot 理解不是那么深刻,经常就会被几个连环跑给干趴下了!

这一文章主要讲解如何对Java请求的@requestBody前端加密后端解密。为了方便所以我采用的最简单的base64加解密作为讲解。直接上干货。

技术讲解

Spring中处理JSON请求使用@RequestBody和@ResponseBody注解,针对JSON请求加解密和过滤字符串,Spring提供了RequestBodyAdvice和ResponseBodyAdvice两个接口。在这我只讲解@RequestBody注解的相关使用

实现RequestBodyAdvice接口

package com.dengf.rent.interceptor;

import org.springframework.core.MethodParameter;

import org.springframework.http.HttpInputMessage;

import org.springframework.http.converter.HttpMessageConverter;

import org.springframework.web.bind.annotation.ControllerAdvice;

import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.IOException;

import java.lang.reflect.Type;

@ControllerAdvice(basePackages = "com.dengf.rent.controller")

public class MyRequestBodyAdvice implements RequestBodyAdvice {

@Override

public boolean supports(MethodParameter methodParameter, Type type, Class extends HttpMessageConverter>> aClass) {

return true;

}

@Override

public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class extends HttpMessageConverter>> aClass) throws IOException {

try {

return new MyHttpInputMessage(httpInputMessage);

} catch (Exception e) {

e.printStackTrace();

return httpInputMessage;

}

}

@Override

public Object afterBodyRead(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class extends HttpMessageConverter>> aClass) {

return o;

}

@Override

public Object handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class extends HttpMessageConverter>> aClass) {

return o;

}

}

在beforeBodyRead中处理相关

package com.dengf.rent.interceptor;

import com.alibaba.fastjson.JSONObject;

import com.dengf.rent.util.CommonUtil;

import org.apache.commons.io.IOUtils;

import org.springframework.http.HttpHeaders;

import org.springframework.http.HttpInputMessage;

import java.io.IOException;

import java.io.InputStream;

public class MyHttpInputMessage implements HttpInputMessage {

private HttpHeaders headers;

private InputStream body;

public MyHttpInputMessage(HttpInputMessage inputMessage) throws Exception {

String data = IOUtils.toString(inputMessage.getBody(), "UTF-8");

JSONObject json = JSONObject.parseObject(data);

String res = CommonUtil.decript(json.getString("data"));

this.body = IOUtils.toInputStream(res, "UTF-8");

}

@Override

public InputStream getBody() throws IOException {

return body;

}

@Override

public HttpHeaders getHeaders() {

return headers;

}

}

base64加解密工具类

package com.dengf.rent.util;

import sun.misc.BASE64Decoder;

import sun.misc.BASE64Encoder;

import java.io.IOException;

public class CommonUtil {

public static String decript(String data) throws IOException {

BASE64Decoder decoder = new BASE64Decoder();

byte[] bytes = decoder.decodeBuffer(data);

return new String(bytes);

}

public static String encript(Object data){

BASE64Encoder encoder = new BASE64Encoder();

String res = encoder.encode(data.toString().getBytes());

return res;

}

}

注意

由于不够细心出了一个小问题,青秧真的是找了好一会儿才找到根节。下面上报错问题:

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Invalid UTF-8 middle byte 0xd0

at [Source: (ByteArrayInputStream); line: 1, column: 146]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Invalid UTF-8 middle byte 0xd0

at [Source: (ByteArrayInputStream); line: 1, column: 146]

at [Source: (ByteArrayInputStream); line: 1, column: 143] (through reference chain: com.yanhua.ydyh.mobilenurse.vo.BaseListVo["LstRow"]->java.util.ArrayList[0]->com.yanhua.ydyh.mobilenurse.vo.patient.EscortsInformationVo["CPHRXB"])

at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:241)

at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:223)

at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:206)

at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:157)

at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:130)

at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:124)

at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)

at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:131)

at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)

at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)

at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)

at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)

at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)

at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)

at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)

at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)

at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

at java.lang.Thread.run(Thread.java:748)

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Invalid UTF-8 middle byte 0xd0

at [Source: (ByteArrayInputStream); line: 1, column: 146]

at [Source: (ByteArrayInputStream); line: 1, column: 143] (through reference chain: com.yanhua.ydyh.mobilenurse.vo.BaseListVo["LstRow"]->java.util.ArrayList[0]->com.yanhua.ydyh.mobilenurse.vo.patient.EscortsInformationVo["CPHRXB"])

at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:391))

at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)

at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)

at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3084)

at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:235)

... 55 common frames omitted

Caused by: com.fasterxml.jackson.core.JsonParseException: Invalid UTF-8 middle byte 0xd0

at [Source: (ByteArrayInputStream); line: 1, column: 146]

at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1804)

at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:669)

at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidOther(UTF8StreamJsonParser.java:3543)

at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:369)

... 65 common frames omitted

这问题就是在说:有中文但是没有用utf-8编码,因为spring框架默认的不是用utf-8编码

注意查看代码这两个地方是否使用utf-8编码,都是粗心惹的祸!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前端Vue传递加密密文到后端Java,后解密的示例代码如下: 前端Vue加密代码: ```javascript // 导入jsencrypt库 import JSEncrypt from 'jsencrypt' // 创建RSA加密实例 const encrypt = new JSEncrypt() // 设置RSA公钥 const publicKey = 'YOUR_RSA_PUBLIC_KEY' encrypt.setPublicKey(publicKey) // 要加密的数据 const data = 'YOUR_DATA_TO_ENCRYPT' // 使用RSA公钥进行加密 const encryptedData = encrypt.encrypt(data) // 将加密后的数据发送到后端 // 例如使用axios发送POST请求 axios.post('/api/decrypt', { encryptedData }) .then(response => { console.log(response.data) }) .catch(error => { console.error(error) }) ``` 后端Java解密代码: ```java import org.apache.commons.codec.binary.Base64; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import javax.crypto.Cipher; import java.nio.charset.StandardCharsets; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.PKCS8EncodedKeySpec; @RestController public class DecryptionController { // 将Base64编码后的私钥字符串转换为PrivateKey对象 private PrivateKey getPrivateKey(String privateKeyStr) throws Exception { byte[] privateKeyBytes = Base64.decodeBase64(privateKeyStr); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePrivate(keySpec); } @PostMapping("/api/decrypt") public String decryptData(@RequestBody EncryptedData encryptedData) throws Exception { String privateKeyStr = "YOUR_RSA_PRIVATE_KEY"; PrivateKey privateKey = getPrivateKey(privateKeyStr); // 使用私钥进行解密 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] encryptedBytes = Base64.decodeBase64(encryptedData.getEncryptedData()); byte[] decryptedBytes = cipher.doFinal(encryptedBytes); // 返回解密后的数据 return new String(decryptedBytes, StandardCharsets.UTF_8); } } ``` 创建一个名为 `EncryptedData` 的Java类,用于接收前端传递的加密数据: ```java public class EncryptedData { private String encryptedData; public String getEncryptedData() { return encryptedData; } public void setEncryptedData(String encryptedData) { this.encryptedData = encryptedData; } } ``` 请将 `YOUR_RSA_PUBLIC_KEY` 替换为你的RSA公钥,将 `YOUR_RSA_PRIVATE_KEY` 替换为你的RSA私钥。在前端,你可以使用axios或其他HTTP库发送POST请求后端的 `/api/decrypt` 路径,并将加密后的数据作为请求体的 `encryptedData` 字段传递。后端解密后的数据作为响应返回给前端
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值