SpringBoot 解决HttpServletRequest只能读取一次
业务逻辑,通过filter读取请求的request,获取token,并将token传递后面流程使用
BodyReaderHttpServletRequestWrapper:
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 byteArrayInputStream = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
}
RepeatReadFilter:
/**
* 封装HttpServletRequest为可重复读取请求
**/
public class RepeatReadFilter implements Filter { @Override
public void init(FilterConfig filterConfig) throws ServletException { } @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
// 防止流读取一次后就没有了, 所以需要将流继续写出去
ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(httpServletRequest);
//获取用户凭证
String token = httpServletRequest.getHeader(Constants.USER_TOKEN);
if(StringUtils.isBlank(token)){
token = httpServletRequest.getParameter(Constants.USER_TOKEN);
}
//=================获取json格式的token字段=========================
String body = HttpHelper.getBodyString(requestWrapper);
if (StringUtils.isNotBlank(body)) {
JSONObject jsonObject = JSONObject.parseObject(body);
Object obj = jsonObject.get("token");
if (null != obj) {
token = obj.toString();
}
}
requestWrapper.setAttribute(Constants.USER_TOKEN,token);
chain.doFilter(requestWrapper, response);
} @Override
public void destroy() { }
}
FilterConfig:
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean registFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new RepeatReadFilter());
registration.addUrlPatterns("/app/*");
registration.setName("UrlFilter");
registration.setOrder();
return registration;
} }
AuthorizationInterceptor:
@Component
public class AuthorizationInterceptor extends HandlerInterceptorAdapter { @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
AuthIgnore annotation;
if(handler instanceof HandlerMethod) {
annotation = ((HandlerMethod) handler).getMethodAnnotation(AuthIgnore.class);
}else{
return true;
} //如果有@AuthIgnore注解,则不验证token
if(annotation != null){
return true;
} //获取用户凭证
String token = request.getHeader(Constants.USER_TOKEN);
if(StringUtils.isBlank(token)){
token = request.getParameter(Constants.USER_TOKEN);
}
if(StringUtils.isBlank(token)){
Object obj = request.getAttribute(Constants.USER_TOKEN);
if(null!=obj){
token=obj.toString();
}
} //token凭证为空
if(StringUtils.isBlank(token)){
throw new AuthException(Constants.USER_TOKEN + "不能为空", HttpStatus.UNAUTHORIZED.value());
} return true;
}
}
WebMvcConfig:
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter { @Autowired
private AuthorizationInterceptor authorizationInterceptor;
// @Autowired
// private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver; @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authorizationInterceptor).addPathPatterns("/**");
super.addInterceptors(registry);
} @Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
//argumentResolvers.add(loginUserHandlerMethodArgumentResolver);
} @Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
} @Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
}
}
在filter中读取token,在interceptor中进行读取判断使用
HttpHelper:
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();
}
}
https://blog.csdn.net/beflyabot/article/details/78053130
https://my.oschina.net/vernon/blog/363693
SpringBoot 解决HttpServletRequest只能读取一次的更多相关文章
- 解决HttpServletRequest的输入流只能读取一次的问题
背景 通常对安全性有要求的接口都会对请求参数做一些签名验证,而我们一般会把验签的逻辑统一放到过滤器或拦截器里,这样就不用每个接口都去重复编写验签的逻辑. 在一个项目中会有很多的接口,而不同的接口可能接 ...
- 大白话讲解如何解决HttpServletRequest的请求参数只能读取一次的问题
大家在开发过程中,可能会遇到对请求参数做下处理的场景,比如读取上送的参数中看调用方上送的系统编号是否是白名单里面的(更多的会用request中获取IP地址判断).需要对请求方上送的参数进行大小写转换或 ...
- springboot请求体中的流只能读取一次的问题
场景交代 在springboot中添加拦截器进行权限拦截时,需要获取请求参数进行验证.当参数在url后面时(queryString)获取参数进行验证之后程序正常运行.但是,当请求参数在请求体中的时候, ...
- 解决SpringMVC拦截器中Request数据只能读取一次的问题
解决SpringMVC拦截器中Request数据只能读取一次的问题 开发项目中,经常会直接在request中取数据,如Json数据,也经常用到@RequestBody注解,也可以直接通过request ...
- 解决spring http输入流和输出流只能读取一次
1.需求:给某些请求接口记录日志,记录请求的数据和响应的数据和请求所花费的时间.这里采用非侵入式编程,也业务代码进行解耦.按照spring AOP 的编程思想. 2.编程设计:在spring 拦截器中 ...
- httpServletRequest中的流只能读取一次的原因
首先,我们复习一下InputStream read方法的基础知识, java InputStream read方法内部有一个,postion,标志当前流读取到的位置,每读取一次,位置就会移动一次,如果 ...
- request.getInputStream() 流只能读取一次问题
问题: 一次开发过程中同事在 sptring interceptor 中获取 request body 中值,以对数据的校验和预处理等操作 .导致之后spring 在读取request body 值做 ...
- 关于springboot配置文件的另类读取方法
一.背景故事 前阵子我接手了公司另外一个同事手里的项目,项目是用的springboot 写的,但是比较坑的就是这个项目写的有点不伦不类.虽然是用的springboot,但由于他是拿了一堆代码拼凑起 ...
- Request.getInputStrema只能读取一次的分析过程
1. 我们先来看一下继承关系HttpServletRequest 接口继承ServletRequest接口 public abstract interface ServletRequest{ pub ...
随机推荐
- linux文本文件编辑命令
1.cat命令 cat命令用于查看纯文本文件(内容较少的),格式为“cat [选项] [文件]”. Linux系统中有多个用于查看文本内容的命令,每个命令都有自己的特点,比如这个cat命令就是用于查看 ...
- STL之List容器
1.List容器 1) list是一个双向链表容器,可高效地进行插入删除元素. 2)list不可以随机存取元素,所以不支持at.(pos)函数与[]操作符.It++(ok) it+5(err) 3)头 ...
- Sitecore CMS中如何管理默认字段值
在Sitecore CMS中管理默认字段值. 在创建内容时,自定义默认值对内容编辑者特别有用.通过指定良好的默认值,新创建的项目可以预先填充数据,以便内容编辑者不必浪费时间一遍又一遍地填充相同的字段. ...
- Apache+Tomcat+Memcached实现会话保持
会话保持的三种方式 Session sticky会话绑定:通过在前端调度器的配置中实现统一session发送至同一后发端服务器 Session cluster会话集群:通过配置Tomcat保持所有To ...
- ASP.NET界面重定向传值
这么说吧,当程序启动时,ASP.NET会自动创建一些经常使用的类的实例,而这些实例就是ASP.NET的内置对象,常用的实例对象有:Response(来自HttpResponse类).Request(来 ...
- 【Hadoop学习之七】Hadoop YARN
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 YARN: ...
- CS131&Cousera图像处理学习笔记 - L4&W2滤波和卷积
cs131: http://vision.stanford.edu/teaching/cs131_fall1617/ coursera: https://www.coursera.org/learn/ ...
- tomcat9 性能调优
官网最靠谱 tomcat 参数官网: http://tomcat.apache.org/tomcat-7.0-doc/config/http.html <Connector port=& ...
- [转载]CSS各种居中方法
水平居中的text-align:center 和 margin:0 auto 这两种方法都是用来水平居中的,前者是针对父元素进行设置而后者则是对子元素.他们起作用的首要条件是子元素必须没有被flo ...
- mycat水平分表
和垂直分库不同,水平分表,是将那些io频繁,且数据量大的表进行水平切分. 基本的配置和垂直分库一样,我们需要改的就是我们的 schema.xml和rule.xml文件配置(server.xml不用做任 ...