最近项目组安全整改,然后需要把所有的安全隐患问题一扫而空,其中也踩了不少的坑,记录下来,以便后续遇到类似问题能立马解决
- CSP
- CSRF
CSP全称Content Security Policy,主要限制图片资源、css资源、js资源的加载
设置方式
# 使用meta标签
<meta http-equiv="Content-Security-Policy" content="font-src 'self' data:; img-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; default-src 'self';">
# 在服务端的Nginx配置里面加上header
add_header Content-Security-Policy "font-src 'self' data:; img-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; default-src 'self';"
Tips:self表示加载自身网站的资源,xxx-src表示限制某种类型文件加载的名字(font-src表示字体文件iconfont加载),然后有一些小图片资源编译成base64,然后采用的协议是data:image/png;base64,xxx所以需要在img-src里面将data:放通。有一些产品线需要进行网站数据的埋点,需要引入第三方的js,那么就需要在对应的script-src里面放通对应的域名https://xxx.com。(而且域名不需要加上单引号)
这两种方法,实践告诉我们,使用meta标签最优,为什么呢?因为如果你往服务器的响应头里面设置,那么每个请求都带上对应的信息,既浪费了带宽,也降低了网页的访问效率,而且给低速的网络的设备增添了不少压力。
CSRF:众所周知的跨站伪造攻击。为了防护,需要给每次的请求带上唯一的Token。那么这里涉及到几个问题,设置的时机还有扩展性。比方说,跨部门单点登陆的时候怎么办?token怎么携带过去,文件资源需要下载到本地怎么办?
解决方案
# 单点登陆
- 协商多平台使用同一个API获取Token,每次登陆成功后请求该API获取Token
- 同域名下通过url传参、session方式
- 跨部门的话通过一个双方协商好的登陆中转站进行跳转(所谓中转站就是弄出一个页面,然后里面做一些平台鉴权的访问,通过鉴权之后就可以直接跳转到其它部门的网站里面。但是这里需要注意的是同步上线的问题,而且文件每次都需要加上唯一标识符)
# 文件下载
- 通过form表单提交直接下载,如果需要带上token的话,在url里面带上(表单不支持设置header头)
- 通过xhr、blob、a标签进行下载,token在xhr请求的时候设置上
/*
* 文件下载代码
* 需要注意的是,后台返回来的文件名是通过Content-Disposition获取的,大概是这样
* Content-Disposition: xxx;filename="xxxxx.ppt";所以有要对文件名获取的操作
*/
let fileNameReg = /(?=filename=([^.]+(?:\.[a-z]+)?))/;
/**
* 下载文件函数
* @param {String} url
* @param {Object} opt
* - header { key: value }
* - method 'get' || 'post'
* - responseType '' | 'arraybuffer' | 'blob' | 'document' | 'json' | 'text';
* - params { key: value }
*/
function downloadFile (url, opt) {
let xhr = new XMLHttpRequest({
responseType: opt.responseType || 'json'
});
url = formateURL(url, opt);
xhr.onreadystatechange = (