一、编写加密类(AES)
/**
* aes加密解密
*/
public class AesEncryptUtils {
//参数分别代表 算法名称/加密模式/数据填充方式
private static String algorithmstr = "AES/ECB/PKCS5Padding";
public static String getAlgorithmstr() {
return algorithmstr;
}
/**
* 加密
* @param content 加密的字符串
* @param encryptKey key值
* @return
* @throws Exception
*/
public static String encrypt(String content, String encryptKey) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
Cipher cipher = Cipher.getInstance(algorithmstr);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));
byte[] b = cipher.doFinal(content.getBytes("utf-8"));
return Base64.encodeBase64String(b);
}
/**
* 解密
* @param encryptStr 解密的字符串
* @param decryptKey 解密的key值
* @return
* @throws Exception
*/
public static String decrypt(String encryptStr, String decryptKey) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
Cipher cipher = Cipher.getInstance(algorithmstr);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
byte[] encryptBytes = Base64.decodeBase64(encryptStr);
byte[] decryptBytes = cipher.doFinal(encryptBytes);
return new String(decryptBytes);
}
public static void main(String[] args) throws Exception{
String str = "pp2bQLjabobRWp2T5Ro5/GlqWCigmkwHYnrOK11VZkTkIA2hSwnEi1sijfTV6Ozd/";
System.out.println(decrypt(str,"f8db034bda44rtkb"));
}
}
二、编写Filter类
/**
* 过滤器拦截请求,实现加密解密功能
*
* @Component 将此Filter交给Spring容器管理
* @WebFilter 通过WebFilter进行Filter声明,这样容器在进行部署的时候就会处理该Filter
*
*/
@Component
public class EncryptFilter implements Filter {
Logger log = LoggerFactory.getLogger(this.getClass());
@Value("${admin.encrypt.excludeUrl}")
private String ignoreStr;
private String[] ignoreArr;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
/**
* 有错误相应返回-44
*
* @param response
* @throws IOException
*/
private void getFailResponse(HttpServletResponse response) throws IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter out = null;
out = response.getWriter();
// out.write("{\n" +
// " \"status\":"+ Constant.ENCRYPT_FAIL +",\n" +
// " \"message\": null,\n" +
// " \"data\": []\n" +
// "}");
//加密后的错误消息
out.write("+D+JO8tuwkrNbxnTTLdqStifmQceT+LlYETnIG/JZKrbAn+gIiqIp3VbzBV1y6R8B7aY53VM2xHa7cY3Osbnqw==");
out.flush();
out.close();
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
if(ignoreArr==null){
ignoreArr = ignoreStr.split(",");
}
HttpServletRequest HttpRequest=(HttpServletRequest)request;
HttpServletResponse HttpResponse=(HttpServletResponse)response;
boolean flag=isIgnore(HttpRequest,ignoreArr);
if(flag) {
try {
chain.doFilter(HttpRequest, HttpResponse);
} catch (IOException e) {
e.printStackTrace();
} catch (ServletException e) {
e.printStackTrace();
}
}else{
try{
//响应处理 包装响应对象 res 并缓存响应数据
ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response);
//执行业务逻辑 交给下一个过滤器或servlet处理
chain.doFilter(request, responseWrapper);
byte[] resData = responseWrapper.getResponseData();
//设置响应内容格式,防止解析响应内容时出错
// responseWrapper.setContentType("text/plain;charset=UTF-8");
//加密响应报文并响应
String encryptBASE64 = AesEncryptUtils.encrypt(new String(resData),Constant.ENCRYPT_STR);
PrintWriter out = response.getWriter();
out.print(encryptBASE64);
out.flush();
out.close();
}catch(Exception e){
try {
getFailResponse((HttpServletResponse)response);
} catch (IOException ioException) {
ioException.printStackTrace();
}
e.printStackTrace();
}
}
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
/**
* 哪些路径不处理
* @param request
* @param strArr
* @return
*/
public boolean isIgnore(HttpServletRequest request,String[] strArr) {
String path=request.getRequestURI();
for(String ignore:strArr) {
if(path.contains(ignore)) {
return true;
}
}
return false;
}
}
下图是对应的application.properties中的配置
其中用到了两个工具类
RequestWrapper
/**
* @Description: 请求包装类
* @Date: 2020/5/26 16:29
*/
public class RequestWrapper extends HttpServletRequestWrapper {
private String requestBody = null;
//请求体
private HttpServletRequest req = null;
// private final byte[] body;//保存流的字节数组
private final Map<String, String> reqHeaders=new HashMap<>();
public RequestWrapper(HttpServletRequest request) throws IOException {
super(request);
this.req = request;
// this.reqHeaders = new HashMap<String, String>();
// String sessionStream = getRequestBodyStr(request);//读取流中的参数
// body = sessionStream.getBytes(Charset.forName("UTF-8"));
}
public RequestWrapper(HttpServletRequest request, String requestBody) {
super(request);
this.requestBody = requestBody;
this.req = request;
// this.reqHeaders = request.get;
}
/**
* @Description: 获取请求body
* @Date: 2020/5/26 10:31
* @Param: [request]
* @Return: java.lang.String
*/
public String getRequestBodyStr(final ServletRequest request) throws IOException {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = cloneInputStream(request.getInputStream());
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
inputStream.close();
}
if (reader != null) {
reader.close();
}
}
return sb.toString();
}
/**
* @Description: 复制输入流
* @Param: [inputStream]
* @Return: java.io.InputStream
*/
public InputStream cloneInputStream(ServletInputStream inputStream) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) > -1) {
byteArrayOutputStream.write(buffer, 0, len);
}
byteArrayOutputStream.flush();
InputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
return byteArrayInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody.getBytes(req.getCharacterEncoding()));
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return bais.read();
}
};
}
/**
* 添加header的名称和值
*
* @param name
* @param value
*/
public void addHeader(String name, String value) {
reqHeaders.put(name, value);
}
@Override
public String getHeader(String name) {
// log.info("getHeader --->{}", name);
String headerValue = super.getHeader(name);
if (reqHeaders.containsKey(name)) {
headerValue = reqHeaders.get(name);
}
return headerValue;
}
/**
* 得到headers的名称
*/
@Override
public Enumeration<String> getHeaderNames() {
List<String> names = Collections.list(super.getHeaderNames());
for (String name : reqHeaders.keySet()) {
names.add(name);
}
return Collections.enumeration(names);
}
@Override
public Enumeration<String> getHeaders(String name) {
// log.info("getHeaders name --->>>>>>{}", name);
List<String> values = Collections.list(super.getHeaders(name));
// log.info("getHeaders value --->>>>>>{}", values);
if (reqHeaders.containsKey(name)) {
values = Arrays.asList(reqHeaders.get(name));
}
return Collections.enumeration(values);
}
}
ResponseWrapper
/**
* @Description: 响应包装类
* @Date: 2020/5/26 16:29
*/
public class ResponseWrapper extends HttpServletResponseWrapper {
private ByteArrayOutputStream buffer = null;
private ServletOutputStream out = null;
private PrintWriter writer = null;
public ResponseWrapper(HttpServletResponse response) throws IOException {
super(response);
buffer = new ByteArrayOutputStream();// 真正存储数据的流
out = new WapperedOutputStream(buffer);
writer = new PrintWriter(new OutputStreamWriter(buffer,this.getCharacterEncoding()));
}
/** 重载父类获取outputstream的方法 */
@Override
public ServletOutputStream getOutputStream() throws IOException {
return out;
}
/** 重载父类获取writer的方法 */
@Override
public PrintWriter getWriter() throws UnsupportedEncodingException {
return writer;
}
/** 重载父类获取flushBuffer的方法 */
@Override
public void flushBuffer() throws IOException {
if (out != null) {
out.flush();
}
if (writer != null) {
writer.flush();
}
}
@Override
public void reset() {
buffer.reset();
}
/** 将out、writer中的数据强制输出到WapperedResponse的buffer里面,否则取不到数据 */
public byte[] getResponseData() throws IOException {
flushBuffer();
return buffer.toByteArray();
}
/** 内部类,对ServletOutputStream进行包装 */
private class WapperedOutputStream extends ServletOutputStream {
private ByteArrayOutputStream bos = null;
public WapperedOutputStream(ByteArrayOutputStream stream)
throws IOException {
bos = stream;
}
@Override
public void write(int b) throws IOException {
bos.write(b);
}
@Override
public void write(byte[] b) throws IOException {
bos.write(b, 0, b.length);
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setWriteListener(WriteListener writeListener) {
}
}
}
三、写配置类
@Configuration
public class WebConfiguration {
@Autowired
private EncryptFilter encryptFilter;
@Bean
public FilterRegistrationBean registFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(encryptFilter);
registration.addUrlPatterns("/*");
registration.setName("EncryptFilter");
registration.setOrder(1);
// registration.setEnabled(false);
return registration;
}
//做跨域处理,跟这个filter没关系
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("*")
.allowedHeaders("*")
.maxAge(3600);
}
};
}
}
参考文章
1.配置过滤器对某个路径下的资源不进行拦截
2.在springBoot项目内自写的一个过滤器(对请求响应信息做加解密处理,见案例)
3.SpringBoot前后端数据传输加密