业务逻辑,通过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只能读取一次的更多相关文章

  1. 解决HttpServletRequest的输入流只能读取一次的问题

    背景 通常对安全性有要求的接口都会对请求参数做一些签名验证,而我们一般会把验签的逻辑统一放到过滤器或拦截器里,这样就不用每个接口都去重复编写验签的逻辑. 在一个项目中会有很多的接口,而不同的接口可能接 ...

  2. 大白话讲解如何解决HttpServletRequest的请求参数只能读取一次的问题

    大家在开发过程中,可能会遇到对请求参数做下处理的场景,比如读取上送的参数中看调用方上送的系统编号是否是白名单里面的(更多的会用request中获取IP地址判断).需要对请求方上送的参数进行大小写转换或 ...

  3. springboot请求体中的流只能读取一次的问题

    场景交代 在springboot中添加拦截器进行权限拦截时,需要获取请求参数进行验证.当参数在url后面时(queryString)获取参数进行验证之后程序正常运行.但是,当请求参数在请求体中的时候, ...

  4. 解决SpringMVC拦截器中Request数据只能读取一次的问题

    解决SpringMVC拦截器中Request数据只能读取一次的问题 开发项目中,经常会直接在request中取数据,如Json数据,也经常用到@RequestBody注解,也可以直接通过request ...

  5. 解决spring http输入流和输出流只能读取一次

    1.需求:给某些请求接口记录日志,记录请求的数据和响应的数据和请求所花费的时间.这里采用非侵入式编程,也业务代码进行解耦.按照spring AOP 的编程思想. 2.编程设计:在spring 拦截器中 ...

  6. httpServletRequest中的流只能读取一次的原因

    首先,我们复习一下InputStream read方法的基础知识, java InputStream read方法内部有一个,postion,标志当前流读取到的位置,每读取一次,位置就会移动一次,如果 ...

  7. request.getInputStream() 流只能读取一次问题

    问题: 一次开发过程中同事在 sptring interceptor 中获取 request body 中值,以对数据的校验和预处理等操作 .导致之后spring 在读取request body 值做 ...

  8. 关于springboot配置文件的另类读取方法

    一.背景故事   前阵子我接手了公司另外一个同事手里的项目,项目是用的springboot 写的,但是比较坑的就是这个项目写的有点不伦不类.虽然是用的springboot,但由于他是拿了一堆代码拼凑起 ...

  9. Request.getInputStrema只能读取一次的分析过程

    1. 我们先来看一下继承关系HttpServletRequest 接口继承ServletRequest接口 public abstract interface  ServletRequest{ pub ...

随机推荐

  1. netcore swagger xml发布丢失问题

    1.netcore2.1.2,swagger.aspnetcore 1.1.0版本.发布netcore项目时swagger的接口文档xml 遗漏,始终发布不上去.后来查阅资料,讲的好像是netcore ...

  2. arcgis api for javascript 添加图层时设置标注,自定义符号

    <!DOCTYPE html> <html> <head> <meta charset="gb2312"> <meta nam ...

  3. notepad去掉空行

    选择替换,把查找模式设置为正则表达式,在查找框中自己输入 ^\s+  ,替换框留空,点“全部替换”,即可(先全选).注意:不要复制我的,自己输入,且用英文格式输入.

  4. Protobuf数据类型

    protobuf编译文件和源码在点击打开链接 1:   数据类型: double: 浮点数 float: 单精度浮点 int32: int类型,使用可变长编码,编码负数不够高效,如果有负数那么使用si ...

  5. DatabaseGenerated(转)

    在EF中,我们建立数据模型的时候,可以给属性配置数据生成选项DatabaseGenerated,它后有三个枚举值:Identity.None和Computed. Identity:自增长 None:不 ...

  6. 09 查找列表中元素,移除每个元素的空格,并查找以a或A开头并且以c结尾的所有元素

    li = ["alex"," aric","Alex","Tony","rain"]for i in ...

  7. C#回调浅析(委托、接口回调)

    https://wenku.baidu.com/view/ed724173bd64783e08122b2f.html

  8. Java集合-----Set详解

    Set是没有重复元素的集合,是无序的 1.HashSet HashSet它是线程不安全的       HashSet常用方法:   add(E element)  将指定的元素添加到此集合(如果尚未存 ...

  9. uvalive 3887 Slim Span

    题意: 一棵生成树的苗条度被定义为最长边与最小边的差. 给出一个图,求其中生成树的最小苗条度. 思路: 最开始想用二分,始终想不到二分终止的条件,所以尝试暴力枚举最小边的长度,然后就AC了. 粗略估计 ...

  10. Ngine X 完全开发指南 读书笔记-前言

    一开始接触的编程语言是VF,那是一种可视化编程语言,所谓的可视化,就是运行结果能直接看得到的,非常直观,便于调试,适合刚刚接触编程的新人学习.当时学得懵懂,半知半解,就是感觉程序非常神奇,常常几句代码 ...