前言
- •为了安全考虑,添加启用浏览器保护的某些头是很有用的,比如X-Frame-Options, X-XSS-Protection和X-Content-Type-Options
- •而HeaderWriterFilter就支持往响应头写入各种响应头
1、HeadersConfigurer
- •HeadersConfigurer是HeaderWriterFilter对应的配置类, 是在获取HttpSecurity的时候默认开启的,也可以通过HttpSecurity.headers()手动开启
1.1 主要方法
- •这个配置类主要就是为了注册HeaderWriter。分为两种配置方式,一种是用户自定义,一种是官方提供的
- •HeaderWriter:负责写入响应头的类
- •第一种:
public HeadersConfigurer addHeaderWriter(HeaderWriter headerWriter) {
Assert.notNull(headerWriter, "headerWriter cannot be null");
this.headerWriters.add(headerWriter);
return this;
}
- •第二种:
/**
* 下面全是头部写入器的配置类
* 配置类是全部都new出来的,但是里面的头部写入器可能并没有开启
*/
private final ContentTypeOptionsConfig contentTypeOptions = new ContentTypeOptionsConfig();
private final XXssConfig xssProtection = new XXssConfig();
private final CacheControlConfig cacheControl = new CacheControlConfig();
private final HstsConfig hsts = new HstsConfig();
private final FrameOptionsConfig frameOptions = new FrameOptionsConfig();
private final HpkpConfig hpkp = new HpkpConfig();
private final ContentSecurit服务器托管网yPolicyConfig contentSecurityPolicy = new ContentSecurityPolicyConfig();
private final ReferrerPolicyConfig referrerPolicy = new ReferrerPolicyConfig();
private final FeaturePolicyConfig featurePolicy = new FeaturePolicyConfig();
private final PermissionsPolicyConfig permissionsPolicy = new PermissionsPolicyConfig();
1.2 构建流程
- •HeadersConfigurer只重写了configure(…)方法:内部就是创建过滤器
@Override
public void configure(H http) {
HeaderWriterFilter headersFilter = createHeaderWriterFilter();
http.addFilter(headersFilter);
}
- •HeaderWriterFilter中的头部写入器 = 用户自定义 + 默认配置类中开启的
/**
* 获得头部写入器
*/
private HeaderWriterFilter createHeaderWriterFilter() {
//获得所有的头部写入器
List writers = getHeaderWriters();
if (writers.isEmpty()) {
throw new IllegalStateException(
"Headers security is enabled, but no headers will be added. Either add headers or disable headers security");
}
HeaderWriterFilter headersFilter = new HeaderWriterFilter(writers);
headersFilter = postProcess(headersFilter);
return headersFilter;
}
/**
* 获得所有的头部写入器
*/
private List getHeaderWriters() {
//添加默认头部写入器(也需要开启的)
List writers = new ArrayList();
addIfNotNull(writers, this.contentTypeOptions.writer);
addIfNotNull(writers, this.xssProtection.writer);
addIfNotNull(writers, this.cacheControl.writer);
addIfNotNull(writers, this.hsts.writer);
addIfNotNull(writers, this.frameOptions.writer);
addIfNotNull(writers, this.hpkp.writer);
addIfNotNull(writers, this.contentSecurityPolicy.writer);
addIfNotNull(writers, this.referrerPolicy.writer);
addIfNotNull(wri服务器托管网ters, this.featurePolicy.writer);
addIfNotNull(writers, this.permissionsPolicy.writer);
//添加用户注册的头部写入器
writers.addAll(this.headerWriters);
return writers;
}
2、HeaderWriterFilter
2.1 doFilterInternal(…)
- •我们直接看doFilterInternal(…)方法:可以看出过滤器支持在请求的前后写入响应头
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
//是否在请求的开始就写头
if (this.shouldWriteHeadersEagerly) {
doHeadersBefore(request, response, filterChain);
}
else {
doHeadersAfter(request, response, filterChain);
}
}
- •doHeadersBefore(…):此方法就是调用HeaderWriter写入响应头,然后执行后续的过滤器
private void doHeadersBefore(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
writeHeaders(request, response);
filterChain.doFilter(request, response);
}
- •doHeadersAfter(…):此方法稍微复杂点,这里包装了request和response
private void doHeadersAfter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
//将response包装为HeaderWriterResponse是为了在执行过程中就可以进行头部写入
HeaderWriterResponse headerWriterResponse = new HeaderWriterResponse(request, response);
HeaderWriterRequest headerWriterRequest = new HeaderWriterRequest(request, headerWriterResponse);
try {
filterChain.doFilter(headerWriterRequest, headerWriterResponse);
}
finally {
headerWriterResponse.writeHeaders();
}
}
- •我们主要看下HeaderWriterResponse的源码,主要就是重写了onResponseCommitted()方法
class HeaderWriterResponse extends OnCommittedResponseWrapper {
private final HttpServletRequest request;
HeaderWriterResponse(HttpServletRequest request, HttpServletResponse response) {
super(response);
this.request = request;
}
/**
* 此方法可以直接调用
* 比如说Controller中执行response.(include,sendError, redirect, flushBuffer)的时候,此方法就会执行
*/
@Override
protected void onResponseCommitted() {
writeHeaders();
this.disableOnResponseCommitted();
}
protected void writeHeaders() {
if (isDisableOnResponseCommitted()) {
return;
}
HeaderWriterFilter.this.writeHeaders(this.request, getHttpResponse());
}
private HttpServletResponse getHttpResponse() {
return (HttpServletResponse) getResponse();
}
}
2.2 shouldWriteHeadersEagerly
- •前面我们提到了HeaderWriter的执行顺序是通过shouldWriteHeadersEagerly这个标志位来决定,但是这个标志位不可以在HeadersConfigurer中直接配置
- •但是我们前面提到了所有的过滤器都有一个基于ObjectPostProcessor的回调方法,这个回调方法在HeadersConfigurer的createHeaderWriterFilter()方法中被调用
image.png
- •我们再看postProcess(…)方法的源码:
- •分析可知道这是遍历所有的ObjectPostProcessor,然后看有哪些ObjectPostProcessor的泛型和传入的object一样,一样就执行回调方法
public Object postProcess(Object object) {
for (ObjectPostProcessor opp : postProcessors) {
Class> oppClass = opp.getClass();
Class> oppType = GenericTypeResolver.resolveTypeArgument(oppClass,
ObjectPostProcessor.class);
if (oppType == null || oppType.isAssignableFrom(object.getClass())) {
object = opp.postProcess(object);
}
}
return object;
}
- •所以说我们可以通过以下的代码配置shouldWriteHeadersEagerly的值
http.headers().addObjectPostProcessor(new ObjectPostProcessor() {
@Override
public O postProcess(O object) {
HeaderWriterFilter filter = object;
filter.setShouldWriteHeadersEagerly(true);
return object;
}
});
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
minio 4.20 发布的版本支持基于ftp 以及sftp 进行minio 管理了,对于一些业务需要使用ftp 以及sftp 的就比较方便了 我们同时可以使用多协议模式进行minio 访问了 参考使用 docker-compose version: ‘3…