1、一些安全相关的HTTP响应头
现代浏览器提供了一些安全相关的响应头,使用这些响应头一般只需要修改服务器配置即可,不需要修改程序代码,成本很低
1.1Strict-Transport-Security(https环境下)
HTTP Strict Transport Security,简称为HSTS。它允许一个HTTPS网站,要求浏览器总是通过HTTPS来访问它。现阶段,除了Chrome浏览器,Firefox4+,以及Firefox的NoScript扩展都支持这个响应头。
我们知道HTTPS相对于HTTP有更好的安全性,而很多HTTPS网站,也可以通过HTTP来访问。开发人员的失误或者用户主动输入地址,都有可能导致用户以HTTP访问网站,降低了安全性。一般,我们会通过Web Server发送301/302重定向来解决这个问题。现在有了HSTS,可以让浏览器帮你做这个跳转,省一次HTTP请求。另外,浏览器本地替换可以保证只会发送HTTPS请求,避免被劫持。
要使用HSTS,只需要在你的HTTPS网站响应头中,加入下面这行:
strict-transport-security: max-age=16070400; includeSubDomains
includeSubDomains是可选的,用来指定是否作用于子域名。支持HSTS的浏览器遇到这个响应头,会把当前网站加入HSTS列表,然后在max-age指定的秒数内,当前网站所有请求都会被重定向为https。即使用户主动输入http://或者不输入协议部分,都将重定向到https://地址。
Chrome内置了一个HSTS列表,默认包含Google、Paypal、Twitter、Linode等等服务。我们也可以在Chrome输入chrome://net-internals/#hsts,进入HSTS管理界面。在这个页面,你可以增加/删除/查询HSTS记录。例如,你想一直以https访问某网址,通过“add Domain”加上去就好了。查看Chrome内置的全部HSTS列表,或者想把自己的网站加入这个列表。
1.2. X-Frame-Options
X-Frame-Options,是为了减少点击劫持(Clickjacking)而引入的一个响应头。Chrome4+、Firefox3.6.9+、IE8+均支持。使用方式如下:
x-frame-options: SAMEORIGIN
这个响应头支持三种配置:
- DENY:不允许被任何页面嵌入;
- SAMEORIGIN:不允许被本域以外的页面嵌入;
- ALLOW-FROM uri:不允许被指定的域名以外的页面嵌入(Chrome现阶段不支持);
如果某页面被不被允许的页面以<iframe>或<frame>的形式嵌入,IE会显示类似于“此内容无法在框架中显示”的提示信息,Chrome和Firefox都会在控制台打印信息。由于嵌入的页面不会加载,这就减少了点击劫持的发生。
1.3. X-XSS-Protection
顾名思义,这个响应头是用来防范XSS的。最早我是在介绍IE8的文章里看到这个,现在主流浏览器都支持,并且默认都开启了XSS保护,用这个header可以关闭它。它有几种配置:
- 0:禁用XSS保护;
- 1:启用XSS保护;
- 1; mode=block:启用XSS保护,并在检查到XSS攻击时,停止渲染页面(例如IE8中,检查到攻击时,整个页面会被一个#替换);
浏览器提供的XSS保护机制并不完美,但是开启后仍然可以提升攻击难度,总之没有特别的理由,不要关闭它。
1.4. X-Content-Type-Options
互联网上的资源有各种类型,通常浏览器会根据响应头的Content-Type字段来分辨它们的类型。例如:"text/html"代表html文档,"image/png"是PNG图片,"text/css"是CSS样式文档。然而,有些资源的Content-Type是错的或者未定义。这时,某些浏览器会启用MIME-sniffing来猜测该资源的类型,解析内容并执行。
例如,我们即使给一个html文档指定Content-Type为"text/plain",在IE8-中这个文档依然会被当做html来解析。利用浏览器的这个特性,攻击者甚至可以让原本应该解析为图片的请求被解析为JavaScript。通过下面这个响应头可以禁用浏览器的类型猜测行为:
X-Content-Type-Options: nosniff
这个响应头的值只能是nosniff,可用于IE8+和Chrome。另外,它还被Chrome用于扩展下载,见这里。
1.5. X-Content-Security-Policy
这个响应头主要是用来定义页面可以加载哪些资源,减少XSS的发生。之前单独介绍过,详细使用
指令 |
指令值示例 |
说明 |
default-src |
'self' cnd.a.com |
定义针对所有类型(js、image、css、web font,ajax 请求,iframe,多媒体等)资源的默认加载策略,某类型资源如果没有单独定义策略,就使用默认的。 |
script-src |
'self' js.a.com |
定义针对 JavaScript 的加载策略。 |
style-src |
'self' css.a.com |
定义针对样式的加载策略。 |
img-src |
'self' img.a.com |
定义针对图片的加载策略。 |
connect-src |
'self' |
针对 Ajax、WebSocket 等请求的加载策略。不允许的情况下,浏览器会模拟一个状态为 400 的响应。 |
font-src |
font.a.com |
针对 WebFont 的加载策略。 |
object-src |
'self' |
针对 <object>、<embed> 或 <applet> 等标签引入的 flash 等插件的加载策略。 |
media-src |
media.a.com |
针对 <audio> 或 <video> 等标签引入的 HTML 多媒体的加载策略。 |
frame-src |
'self' |
针对 frame 的加载策略。 |
sandbox |
allow-forms |
对请求的资源启用 sandbox(类似于 iframe 的 sandbox 属性)。 |
report-uri |
/report-uri |
告诉浏览器如果请求的资源不被策略允许时,往哪个地址提交日志信息。 特别的:如果想让浏览器只汇报日志,不阻止任何内容,可以改用 Content-Security-Policy-Report-Only 头。 |
指令值可以由下面这些内容组成:
指令值 |
指令示例 |
说明 |
img-src |
允许任何内容。 |
|
'none' |
img-src 'none' |
不允许任何内容。 |
'self' |
img-src 'self' |
允许来自相同来源的内容(相同的协议、域名和端口)。 |
data: |
img-src data: |
允许 data: 协议(如 base64 编码的图片)。 |
www.a.com |
img-src img.a.com |
允许加载指定域名的资源。 |
.a.com |
img-src .a.com |
允许加载 a.com 任何子域的资源。 |
img-src https://img.com |
允许加载 img.com 的 https 资源(协议需匹配)。 |
|
https: |
img-src https: |
允许加载 https 资源。 |
'unsafe-inline' |
script-src 'unsafe-inline' |
允许加载 inline 资源(例如常见的 style 属性,onclick,inline js 和 inline css 等等)。 |
'unsafe-eval' |
script-src 'unsafe-eval' |
允许加载动态 js 代码,例如 eval()。 |
从上面的介绍可以看到,CSP 协议可以控制的内容非常多。而且如果不特别指定 'unsafe-inline' 时,页面上所有 inline 样式和脚本都不会执行;不特别指定 'unsafe-eval',页面上不允许使用 new Function,setTimeout,eval 等方式执行动态代码。在限制了页面资源来源之后,被 XSS 的风险确实小不少。
2、如何在spring-security支持下使用安全响应头
2.1引入相关的依赖
《1》springBoot下
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
《2》spring下
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-bom</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
2、2类WebSecurityConfig
package com.example.controller;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
/**
* @author admin
* @date 2018/8/29
*/
@EnableWebSecurity
@Configurable
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// http.headers().httpStrictTransportSecurity().includeSubDomains(true).maxAgeInSeconds(22222);
http.headers().contentSecurityPolicy("default-src 'self'");
http.headers().xssProtection().disable();
http.headers().httpStrictTransportSecurity().maxAgeInSeconds(22222);
}
}