在项目中遇到一个问题,需要对接口返回的数据进行加密给前端。项目中的controller一般都是返回一个实体form,重写的一个视图解析器继承ModelAndViewResolver,对返回的form转成json格式返回给前端。

视图解析器:

public class JsonModelAndViewResolver implements ModelAndViewResolver,
InitializingBean, ApplicationContextAware {
private String defaultContentType = "text/html";
private Log log = LogFactory.getLog(super.getClass());
private JsonSerialization jsonSerialization;
private ApplicationContext applicationContext; public void afterPropertiesSet() throws Exception {
if (this.jsonSerialization != null)
return;
this.jsonSerialization = JsonSerializationFactory.getInstance(this.applicationContext);
} public void setApplicationContext(ApplicationContext paramApplicationContext)
throws BeansException {
this.applicationContext = paramApplicationContext;
} //执行这个方法
public ModelAndView resolveModelAndView(Method paramMethod,
Class paramClass, Object paramObject,
ExtendedModelMap paramExtendedModelMap,
NativeWebRequest paramNativeWebRequest) {
if (Rest.class.isAssignableFrom(paramClass)) {
try {
HttpServletResponse localHttpServletResponse = (HttpServletResponse) paramNativeWebRequest.getNativeResponse(HttpServletResponse.class);
responseJson(paramObject, localHttpServletResponse);
} catch (IOException localIOException) {
throw new WebException(localIOException.getMessage(),
localIOException);
}
return null;
}
return UNRESOLVED;
} public void responseJson(Object paramObject,
HttpServletResponse paramHttpServletResponse) throws IOException {
if (!(StringUtils.hasText(paramHttpServletResponse.getContentType())))
paramHttpServletResponse.setContentType(this.defaultContentType);
String str = writeResult(paramObject);
PrintWriter localPrintWriter = paramHttpServletResponse.getWriter();
if (this.log.isInfoEnabled())
this.log.info("Rest result=" + str);
if ("{}".equals(str)) {
this.log.info("image stream is not write ");
return;
}
localPrintWriter.write(str);
localPrintWriter.flush();
} protected String writeResult(Object paramObject) {
String str = null;
if (paramObject == null) {
str = "{}";
} else if ((paramObject instanceof Number)
|| (paramObject instanceof Boolean)) {
str = "{\"resultCode\":\"" + paramObject.toString() + "\"}";
} else if ((paramObject instanceof String)) {
String result = (String) paramObject;
str = result;
} else {
if (paramObject instanceof ModelAndView)
paramObject = ((ModelAndView) paramObject).getModel();
str = getJsonSerialization().toJSONString(paramObject);
}
return str;
} public String getDefaultContentType() {
return this.defaultContentType;
} public void setDefaultContentType(String paramString) {
this.defaultContentType = paramString;
} public JsonSerialization getJsonSerialization() {
return this.jsonSerialization;
} public void setJsonSerialization(JsonSerialization paramJsonSerialization) {
this.jsonSerialization = paramJsonSerialization;
}
}

  本来考虑直接修改视图解析器,对返回json串加密,但发现项目中有些接口直接在controller中直接通过PrintWriter返回了参数,显然有这种方法是拦截不到的。

最后通过HttpServletResponseWrapper截取返回数据流加密重新输出给前端的方式。

代码参照如下:

ResponseWrapper:

package com.paic.egis.smts.toa.web.interceptor;

import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.PrintWriter; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper; import com.paic.egis.smts.common.util.LoggerUtil; public class ResponseWrapper extends HttpServletResponseWrapper {
private PrintWriter cachedWriter;
private CharArrayWriter bufferedWriter; public ResponseWrapper(HttpServletResponse response) throws IOException {
super(response);
bufferedWriter = new CharArrayWriter();
cachedWriter = new PrintWriter(bufferedWriter);
} public PrintWriter getWriter() throws IOException {
return cachedWriter;
} public String getResult() {
byte[] bytes = bufferedWriter.toString().getBytes();
try {
return new String(bytes, "UTF-8");
} catch (Exception e) {
LoggerUtil.logError(this.getClass().getName(), "getResult", e);
return "";
}
} }

  过滤器如下:

package com.paic.egis.smts.toa.web.filter;

import java.io.IOException;
import java.io.PrintWriter; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse; import com.alibaba.dubbo.common.utils.StringUtils;
import com.paic.egis.smts.common.util.LoggerUtil;
import com.paic.egis.smts.common.util.PropertiesUtil;
import com.paic.egis.smts.pama.security.Base64Utils;
import com.paic.egis.smts.toa.web.interceptor.ResponseWrapper;
import com.paic.egis.smts.trusteesship.util.RSACoder; public class ResponseWrapperFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException { String version = req.getParameter("version");
if(StringUtils.isEmpty(version)){ chain.doFilter(req, resp); } else { HttpServletResponse response = (HttpServletResponse) resp;
ResponseWrapper mr = new ResponseWrapper(response); chain.doFilter(req, mr); PrintWriter out = resp.getWriter();
try {
//取返回的json串
String result = mr.getResult();
System.out.println(result);
//加密
String encryptStr = encryptRSA(result);
out.write(encryptStr);
} catch (Exception e) {
LoggerUtil.logError(this.getClass().getName(), "doFilter", e);
} finally {
out.flush();
out.close();
}
}
} @Override
public void init(FilterConfig filterconfig) throws ServletException { } //rsa公钥加密
public String encryptRSA(String content) throws Exception{
String publicKeyStr = PropertiesUtil.getProperty("response.publicKey");
byte[] encryptBytes = RSACoder.encrypt(content.getBytes("utf-8"), publicKeyStr,"public");
return Base64Utils.encode(encryptBytes);
}
}

  在测试阶段发现,有的接口会出现重复加密的问题。

过滤器配置如下:

<filter>
<filter-name>encryptFilter</filter-name>
<filter-class>com.paic.egis.smts.toa.web.filter.ResponseWrapperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encryptFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>encryptFilter</filter-name>
<url-pattern>/do/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>encryptFilter</filter-name>
<url-pattern>/doh/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>encryptFilter</filter-name>
<url-pattern>*.doh</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>encryptFilter</filter-name>
<url-pattern>/app/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>encryptFilter</filter-name>
<url-pattern>/mamc/*</url-pattern>
</filter-mapping>

  当接口地址是类似/do/smi/queryRegionInfo.do,过滤器类中会进入两次,对应同一个response,所以在第一次out.write(encryptStr);  时,就更改了response的输出值,在第二次String result = mr.getResult();  时取得就是第一次加密后的值。

将接口改为/smi/queryRegionInfo.do就不会出现这种情况。

通过HttpServletResponseWrapper修改response输出流的更多相关文章

  1. 测试调试-利用fiddler修改response返回结果

    测试前端过程中,经常需要验证各种功能状态.不同数据层级等返回后的展示效果.一般会通过以下三种方式进行测试: 1.构造满足条件的测试数据:(耗时费力) 2.修改数据库:(前提需要了解数据库数据存储.沟通 ...

  2. nginx处理302、303和修改response返回的header和网页内容

    背景 遇到一个限制域名的平台,于是使用nginx在做网站转发,其中目标网站在访问过程中使用了多个302.303的返回状态,以便跳转到指定目标(为什么限制,就是防止他的网站的镜像). 在查找了一段资料后 ...

  3. 10、Fiddler中设置断点修改Response

    当然Fiddler中也能修改Response 第一种:打开Fiddler 点击Rules-> Automatic Breakpoint  ->After Response  (这种方法会中 ...

  4. 过滤器修改response

    过滤器通过doFilter方法的第二个参数ServletResponse将输出发送给客户,但servletResponse参数没有为过滤器提供servlet或jsp页面的访问:执行doFilter方法 ...

  5. 怎样修改Response中的内容

    重写Stream public class CatchTextStream : Stream { private Stream output; public CatchTextStream(Strea ...

  6. Spring MVC 使用 HttpServletResponseWrapper 修改返回结果

    HttpServletResponseWrapper 是什么? ServletResponse 的包装类,相关设计模式 装饰者模式. 运行环境 jdk 1.7 spring boot 整合的web环境 ...

  7. 3- 设置断点修改Response

    以下是借鉴别人的知识分享.我在这里转载,如有冒犯,还请告知. 只要你会设置断点修改请求内容的话,这个设置断点修改响应内容的方法也是一样的,只需要修改一下命令即可. 修改响应内容也有两种方法: 第一种: ...

  8. Charles 断点修改Response

    前言: 我们可以通过map功能进行重定向,但如果同一个域名进行的是不同请求与返回.此时map在这里就不适用了. 我们可以通关对某一请求进行断点,在进行修改请求或者返回.这样就可以满足我们的需求了. 一 ...

  9. java内部发送http请求并取得返回结果,修改response的cookie

    public Object userLogin(HttpServletRequest request, HttpServletResponse response, String email, Stri ...

随机推荐

  1. TSV 与 CSV

    TSV : Tab-separated values 用制表符分隔值. CSV : Comma-separated values 用逗号分隔值. 参考 RFC 4180 - Common Format ...

  2. git开发实战:认识git

    git简介: git是分布式版本控制系统,相比较svn相比,git会在本地保存完整的提交记录,即使远程服务器宕机数据消失,可以将本地分支提交到远程服务器,本地分支会保存完整的记录.只要文件提交到git ...

  3. Linux(Ubuntu)常用命令(五)—— vi/vim常用操作

    vi/vim常用命令 vim其实就是vi的升级版,vi里的所有命令vim里都可以用,一般使用来说几乎没什么差别. 注:本篇文章区分大小写! vi / vim三级模式的关系: 命令行模式 任何时候,不管 ...

  4. 数论---lcm和gcd

    cd即最大公约数,lcm即最小公倍数. 首先给出a×b=gcd×lcm 证明:令gcd(a,b)=k,a=xk,b=yk,则a×b=xykk,而lcm=xyk,所以ab=gcd*lcm. 所以求lcm ...

  5. Java实验报告(四)&第六周学习总结

    班级 计科二班 学号 20188425 姓名 IM 完成时间2019/10/07 评分等级 一.实验目的 (1)掌握类的继承 (2)变量的继承和覆盖,方法的继承,重载和覆盖的实现: 二.实验的内容 ( ...

  6. git 更新代码

    https://jingyan.baidu.com/album/ab69b2707882f52ca7189f14.html?picindex=7 git commit:将本地修改过的文件提交到本地库 ...

  7. mysql 【常用sql】

    修改过mysql数据库字段内容默认值为当前时间 --添加CreateTime 设置默认时间 CURRENT_TIMESTAMP ALTER TABLE `table_name` ADD COLUMN ...

  8. FastJSON 远程执行漏洞,速速升级!

    相信大家用 FastJSON 的人应该不少,居然有漏洞,还不知道的赶紧往下看,已经知道此漏洞的请略过-- 2019年6月22日,阿里云云盾应急响应中心监测到FastJSON存在0day漏洞,攻击者可以 ...

  9. springCloud的使用09-----高可用的注册中心

    思路:创建多个注册中心,在他们的配置文件中配置相互之间的注册 1 在eureka-server项目的resources目录下创建两个配置文件application-peer1.yml和applicat ...

  10. 48.Course Schedule(课程安排)

    Level:   Medium 题目描述: There are a total of n courses you have to take, labeled from 0 to n-1. Some c ...