当 JavaWeb项目报"xxx响应头缺失“漏洞的时候,后台调用各种请求地址时又没有传地址或者不想逐个进行设定请求头的时候,该怎么做?
我这是用的JavaSpringBoot+layui写的Web项目。
首先,感谢stone和yvioo两位大佬的分享!
参考 博客园大佬:yvioo
获取自定义请求头的方式:
//增加响应头缺失代码
HttpServletRequest req=(HttpServletRequest)request;
HttpServletResponse res=(HttpServletResponse)response;
res.addHeader("X-Frame-Options","SAMEORIGIN");
res.addHeader("Referer-Policy","origin");
res.addHeader("Content-Security-Policy","object-src 'self'");
res.addHeader("X-Permitted-Cross-Domain-Policies","master-only");
res.addHeader("X-Content-Type-Options","nosniff");
res.addHeader("X-XSS-Protection","1; mode=block");
res.addHeader("X-Download-Options","noopen");
再参考这位大佬:java - springboot 添加自定义拦截器
拿到HandlerInteceptor接口,重写preHandle 方法,可以实现在请求刚送达Controller之前,就进行对请求体及返回体的设置。
引用作者注释:
HandlerInterceptor接口中有三个方法
preHandle : 在进入Controller之前执行。返回值为Boolean类型,如果返回false,表示拦截请求,不再向下执行。
如果返回true,表示放行,程序继续向下执行(如果后面没有其他Interceptor,就会执行controller方法)。
所以此方法可对请求进行判断,决定程序是否继续执行,或者进行一些初始化操作及对请求进行预处理。postHandle: 在Controller方法调用完后, 在DispatcherServlet 进行视图返回渲染之前被调用,。
可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作,比如说设置cookie,返回给前端。afterCompletion: 在整个请求结束之后执行,也就是在DispatcherServlet 渲染了对应的视图之后执行,。
所以该方法适合进行一些资源清理
package com.xxx.interceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/**
* FileName: Interceptor
* DetailedDescription:拦截器工具 发送响应头
*
* @author Cheng rong yu
* @version 1.00
* @Date 2022-07-11
*/
@Component
@Slf4j
public class Interceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
Map<String, String[]> parameterMap = request.getParameterMap();
//增加响应头缺失代码
HttpServletRequest req=(HttpServletRequest)request;
HttpServletResponse res=(HttpServletResponse)response;
res.setHeader("X-Frame-Options","SAMEORIGIN");
res.setHeader("Referer-Policy","origin");
res.setHeader("Content-Security-Policy","object-src 'self'");
res.setHeader("X-Permitted-Cross-Domain-Policies","master-only");
res.setHeader("X-Content-Type-Options","nosniff");
res.setHeader("X-XSS-Protection","1; mode=block");
res.setHeader("X-Download-Options","noopen");
//处理cookie问题
Cookie[] cookies = req.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
String value = cookie.getValue();
StringBuilder builder = new StringBuilder();
builder.append(cookie.getName()+"="+value+";");
builder.append("Secure;");//Cookie设置Secure标识
builder.append("HttpOnly;");//Cookie设置HttpOnly
res.addHeader("Set-Cookie", builder.toString());
}
}
log.info("==收到请求, requestURI: {} , queryString: {} ==", requestURI);
return true;
}
}
但,仅重写preHandle 方法还不够,因为这里只是一个接口方法,我们需要加一个真正的截取配置器类,来进行截取请求体、返回体后进行对截取信息操作,即:implements WebMvcConfigurer。
在重写addInterceptors方法时获取到InterceptorRegistry 拦截注测工具类,传入方法后,调用addInterceptor将我们写好的拦截器类作为参数传入即可。
package com.xxx.interceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
/**
* FileName: Interceptor
* DetailedDescription:java springmvc传递web请求时 截取配置工具类
*
* @author Cheng rong yu
* @version 1.00
* @Date 2022-07-11
*/
@Configuration
public class WebMvcConfigure implements WebMvcConfigurer {
/**
* 配置截取器类
*/
@Resource
private Interceptor interceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
/**
* 使用拦截注册工具类获取后进行调用 拦截器工具 发送响应头
*/
registry.addInterceptor(interceptor);
}
}
接下来,启动项目,随便点俩页面,然后查看后台:
这里会对每一个请求进行拦截后处理
到这里就结束了,但是我突然想到,如果不止这一个需求怎么办?
当然,按segmentfault发帖的作者的思路,是可以继续套娃建立自己的多个拦截器的。
首先还是找我们的HandlerInterceptor 接口小同志来玩,可以选择新建一个,或者在原有的类中处理。(此处注意:若在原有类中进行写新方法,像写过的preHandle 方法就不能再写了,因为我们在WebMvcConfigurer 拦截配置器中直接调用的类,并不是某个方法)
如果是新写的类,多调用一个就行:
registry.addInterceptor(recordLogInterceptor);