SpringBoot 解决HttpServletRequest只能读取一次

时间:2023-03-09 22:48:10
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