上节我们讨论了 Spring Security 如何防范 CSRF 攻击,本节我们讨论如何用最简单的方式提升 Spring Security Web 项目的安全性。
Spring Security 可以通过「HTTP 安全响应头」的方式提升安全性。
本节我们讨论如何实现 HTTP 安全响应头。
Spring Security 提供了一些默认 HTTP 安全性相关的响应头。这些默认响应头如下:
当用户通过了认证,访问了敏感信息而后点击了退出,此时若浏览器对页面进行了缓存,攻击者就可能通过点击浏览器「后退」按键访问到刚刚认证用户看到的内容。
Spring Security 默认禁用浏览器页面缓存,这样可以减少敏感信息泄漏风险。
浏览器为了增强用户体验,会去嗅探用户请求的内容格式。例如当浏览器访问到某个 JavaScript 文件,然而此时并没有指定其文件类型,此时浏览器则会自动判断并且执行它。
内容嗅探带来了一些问题,比如攻击者会利用某些可被解析成多种内容格式的文件,执行 XSS 攻击。例如,有些网站可能允许用户上传和预览 PostScript 代码,攻击者创建一个 PostScript 文档,同时该文档也是一个 JavaScript 格式文件,此时,攻击者便可以实现 XSS 攻击。
Spring Security 默认禁用了内容嗅探功能。
通常我们访问网站的时候是直接输入域名,比如:mybank.example.com,此时默认情况下浏览器会访问 http://mybank.example.com。HTTP 协议由于信息不加密,无法保证访问目标的真实性,容易受到中间人攻击。增加 Strict-Transport-Security 响应头,可以强制将访问协议转换成 Https。
允许网站被放到 iframe 对象里,这种情况下攻击者可能通过设置 CSS,让用户的点击发生在非意愿的位置。
默认情况下 Spring Security 拒绝网页在 iframe 对象中渲染。
尽管大部分浏览器都已经内置了过滤 XSS 攻击的支持,但也并非所有浏览器都默认支持。增加 XSS-Protection 头可以确保 XSS 攻击过滤已启动。
Spring Security 提供了一系列默认 Http 安全响应头,我们可以便捷的配置它们。
例如,为 X-Frame-Options
指定值 SAMEORIGIN
:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) {
http.headers(headers -> headers.frameOptions(frameOptions -> frameOptions.sameOrigin()));
}
}
如果不希望默认头被自动添加,可以通过如下方式配置,例如仅添加 Cache Control 头:
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
// 取消自动添加默认头
.defaultsDisabled()
// 添加 CacheControl 头
.cacheControl(withDefaults())
);
}
}
或者通过以下方式禁用所有 HTTP 安全响应头:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers(headers -> headers.disable());
}
}
Spring Security 默认包含「Cache Control」头。
如果只需要缓存指定类型的内容,我们可以通过 HttpServletResponse.setHeader(String,String)
方式指定缓存项,如 CSS、JavaScript、图片等。
我们也可以直接禁用掉「Cache Control」头,方式如下:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) {
http.headers(headers -> headers.cacheControl(cache -> cache.disable()));
}
}
Spring Security 默认包含了 Content-Type
头。如果需要禁用它,可以通过如下方式:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) {
http.headers(headers -> headers.contentTypeOptions(contentTypeOptions -> contentTypeOptions.disable()));
}
}
HTTP Strict Transport Security(HSTS)头,在 Spring Security 中是被默认开启的,我们可以修改它的默认状态,如下:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers(headers -> headers
.httpStrictTransportSecurity(hsts -> hsts
.includeSubDomains(true)
.preload(true)
.maxAgeInSeconds(31536000)
)
);
}
}
默认情况下,Spring Security 通过 X-Frame-Options 头方式禁止 iframe 层渲染,我们可以通过如下方式修改其配置:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers(headers -> headers.frameOptions(frameOptions -> frameOptions.sameOrigin()));
}
}
默认情况下,Spring Security 为了防止 XSS 攻击增加了 X-XSS-Protection 头,我们可以通过以下方式对其配置进行修改:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers(headers -> headers.xssProtection(xss -> xss.block(false)));
}
}
Spring Security 的实现机制使得它可以轻易的添加安全响应头。
例如配置如下自定义头:
X-Custom-Security-Header: header-value
我们可以通过 StaticHeadersWriter 对象添加:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers(headers -> headers.addHeaderWriter(new StaticHeadersWriter("X-Custom-Security-Header","header-value")));
}
}
当Spring Security 的默认配置方式不能满足我们添加响应头的需求时,我们可以通过 HeadersWriter
实例动态添加。例如动态添加 X-Frame-Options
头:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers(headers -> headers.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN)));
}
}
有时候我们只想为某个确定的请求添加响应头,例如只针对对登录页面的请求,这是可以通过 DelegatingRequestMatcherHeaderWriter
实现。例如:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
RequestMatcher matcher = new AntPathRequestMatcher("/login");
DelegatingRequestMatcherHeaderWriter headerWriter = new DelegatingRequestMatcherHeaderWriter(matcher,new XFrameOptionsHeaderWriter());
http.headers(headers -> headers.frameOptions(frameOptions -> frameOptions.disable()).addHeaderWriter(headerWriter));
}
}
本节讨论了如何利用 HTTP 请求头提升 Spring Security Web 项目的安全性,主要内容有:
下节我们讨论针对 HTTP 协议,我们还能有哪些安全性提升策略。
0/1000