解决在Filter中读取Request中的流后, 然后再Control中读取不到的做法
我们来看一下核心代码: filter中主要做的事情, 就是来校验请求是否合法, 是否有篡改过值.
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (Boolean.valueOf(authentication)) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
if (BasicdataCommonsConstant.POST.equalsIgnoreCase(httpServletRequest.getMethod())) {
// 防止流读取一次后就没有了, 所以需要将流继续写出去
ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(httpServletRequest);
String body = HttpHelper.getBodyString(requestWrapper);
if (StringUtils.isBlank(body)) {
LOGGER.error("非法请求, 没有APP_KEY, APP_SECRET");
OutWriterUtil.outJson(response, gson.toJson(new Response(ErrorCode.AUTH_ERROR_ILLEGAL_FROMTYPE)));
return;
}
Map<String, String> parameters = gson.fromJson(body, new TypeToken<Map<String, String>>() {
}.getType());
String APP_KEY = parameters.get("appKey");
String APP_SECRET = parameters.get("appSecret");
TAuthUser authUser = authUserMap.get(APP_KEY);
if (authUser == null) {
LOGGER.error("非法请求, 没有APP_KEY, APP_SECRET");
OutWriterUtil.outJson(response, gson.toJson(new Response(ErrorCode.AUTH_ERROR_ILLEGAL_FROMTYPE)));
return;
} else if (StringUtils.isBlank(APP_SECRET)) {
LOGGER.error("非法请求, APP_SECRET为空, user={}", gson.toJson(authUser));
OutWriterUtil.outJson(response, gson.toJson(new Response(ErrorCode.AUTH_ERROR_FROMTYPE_AND_KEY_CANNT_BE_NULL)));
return;
} else if (!APP_SECRET.equals(authUser.getAppSecret())) {
LOGGER.error("非法请求: 没有APP_KEY, APP_SECRET不匹配. user={}, password={}, name={}", APP_KEY, APP_SECRET, authUser.getName());
OutWriterUtil.outJson(response, gson.toJson(new Response(ErrorCode.AUTH_ERROR_ILLEGAL_KEY)));
return;
}
String SIGNATURE = parameters.get("signature");
// 对参数进行签名
String md5 = SignatureUtil.decryptSignature(parameters);
if (!md5.equals(SIGNATURE)) {
LOGGER.error("非法请求, signature ={}", SIGNATURE);
OutWriterUtil.outJson(response, gson.toJson(new Response(ErrorCode.AUTH_ERROR_SIGNATURE_ERROR)));
return;
}
threadLocalUser.setAuthUser(authUser);
chain.doFilter(requestWrapper, response);
}
}
chain.doFilter(request, response);
}
大家都知道, 流只能读一次, 读了就没有了, 为了后面的代码还能够取得流, 我们应该还需要将其写出去才行.
所以, 我新建立了一个类. 看代码:
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
/**
* Created with antnest-platform
* User: chenyuan
* Date: 12/31/14
* Time: 8:49 PM
*/
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bais.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
}
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Created with antnest-platform
* User: chenyuan
* Date: 12/24/14
* Time: 10:39 AM
*/
public class HttpHelper {
/**
* 获取请求Body
*
* @param request
* @return
*/
public static String getBodyString(ServletRequest request) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = 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) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
}
请注意这里的编码, 最好将其转换成UTF-8的编码格式, 不然你获取到的中文则会使乱码的. 我自己也习惯于UTF-8的编码.
这样子就应该差不多了哦~
解决在Filter中读取Request中的流后, 然后再Control中读取不到的做法的更多相关文章
- 解决在mysql表中删除自增id数据后,再添加数据时,id不会自增1的问题
https://blog.csdn.net/shaojunbo24/article/details/50036859 问题:mysql表中删除自增id数据后,再添加数据时,id不会紧接.比如:自增id ...
- ASP.NET Core 2.0 中读取 Request.Body 的正确姿势
原文:ASP.NET Core 中读取 Request.Body 的正确姿势 ASP.NET Core 中的 Request.Body 虽然是一个 Stream ,但它是一个与众不同的 Stream ...
- Spring拦截器中通过request获取到该请求对应Controller中的method对象
背景:项目使用Spring 3.1.0.RELEASE,从dao到Controller层全部是基于注解配置.我的需求是想在自定义的Spring拦截器中通过request获取到该请求对应于Control ...
- SpringMVC中redirect跳转后如何保存Model中的数据?
@RequestMapping(value = "delete-user", method = RequestMethod.POST) public String deleteUs ...
- 解决在Filter中读取Request中的流后,后续controller或restful接口中无法获取流的问题
首先我们来描述一下在开发中遇到的问题,场景如下: 比如我们要拦截所有请求,获取请求中的某个参数,进行相应的逻辑处理:比如我要获取所有请求中的公共参数 token,clientVersion等等:这个时 ...
- ASP.NET Core 中读取 Request.Body 的正确姿势
ASP.NET Core 中的 Request.Body 虽然是一个 Stream ,但它是一个与众不同的 Stream —— 不允许 Request.Body.Position=0 ,这就意味着只能 ...
- 如何在ASP.NET Core自定义中间件中读取Request.Body和Response.Body的内容?
原文:如何在ASP.NET Core自定义中间件中读取Request.Body和Response.Body的内容? 文章名称: 如何在ASP.NET Core自定义中间件读取Request.Body和 ...
- 拦截器中,request中getReader()和getInputStream()只能调用一次,构建可重复读取inputStream的request.
由于 request中getReader()和getInputStream()只能调用一次 在项目中,可能会出现需要针对接口参数进行校验等问题. 因此,针对这问题,给出一下解决方案 实现方法:先将Re ...
- java读取request中的xml
java读取request中的xml 答: // 读取xml InputStream inputStream; StringBuffer sb = new StringBuffer(); inpu ...
随机推荐
- C# Winform TCP发消息
服务端: 代码: using System; using System.Collections.Generic; using System.IO; using System.Net; using Sy ...
- centOs7.5.64以上版本的操作系统搭建GitLab记录
一. 安装并配置必要的依赖关系在CentOS系统上安装所需的依赖:ssh,防火墙,postfix(用于邮件通知) ,wget,以下这些命令也会打开系统防火墙中的HTTP和SSH端口访问. 1.安装ss ...
- JZOJ8月15日提高组反思——2020年暑假终结篇
JZOJ8月15日提高组反思--2020年暑假终结篇 T1 仙人掌最短路 抱歉我只会最短路 仙人掌是啥? 听说是缩点+\(LCA\) 最短路30 T2 直接暴力计算 正解\(DP\) \(amazin ...
- PyQt(Python+Qt)学习随笔:QSlider滑动条部件功能简介
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.概述 Designer输入部件中的Horizo ...
- PyQt(Python+Qt)学习随笔:QCommandLinkButton的特征及用途
CommandLinkButton是Windows Vista引入的新控件,,它的预期用途与单选按钮类似,用于在一组互斥选项之间进行选择.命令链接按钮不应单独使用,而应作为向导和对话框中单选按钮的替代 ...
- MapReduce简单执行过程及Wordcount案例
MapReducer运行过程 以单词统计为案例. 假如现在文件中存在如下内容: aa bb aa cc dd aa 当然,这是小文件,如果文件大小较大时会将文件进行 "切片" ,此 ...
- Shiro remeberMe反序列化漏洞复现(Shiro-550)
Apache Shiro是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理等功能.Shiro框架直观.易用,同时也能提供健壮的安全性.在Apache Shiro编号为550的 issu ...
- tensorflow 小记——如何对张量做任意行求和,得到新tensor(一种方法:列表生成式)
希望实现图片上的功能 import tensorflow as tfa = tf.range(10,dtype=float)b = aa = tf.reshape(a,[-1,1])a = tf.ti ...
- AcWing 180. 排书
AStar 最坏情况\(O(log_2560 ^ 4)\) 用\(AStar\)算法做了这题,程序跑了\(408ms\). 相比于\(IDA*\)的\(100ms\)左右要慢上不少. 且\(A*\)由 ...
- GitLab的基本了解和使用
使用前提 GitLab账号 安装好git VSCODE && 配置GitPath 在vscode里配置GitPath file-preferences-setting 在search ...