web 安全:

XSS
XSS 全称“跨站脚本”,是注入攻击的一种。

特点是不对服务器端造成任何伤害,而是通过一些正常的站内交互途径,例如发布评论,提交含有 JavaScript 的内容文本。

这时服务器端如果没有过滤或转义掉这些脚本,作为内容发布到了页面上,其他用户访问这个页面的时候就会运行这些脚本。

我把所有用户输入进行 HTML 转义输出是个不错的做法。似乎很多 Web 开发框架、模版引擎的开发者也发现了这一点,Django 内置模版和 Jinja2 模版总是默认转义输出变量的。

大多数 Web 开发者都了解 XSS 并知道如何防范,往往大型的 XSS 攻击都是由于疏漏。。

XSS 是实现 CSRF 的诸多途径中的一条,但绝对不是唯一的一条。一般习惯上把通过 XSS 来实现的 CSRF 称为 XSRF

CSRF
CSRF 并不一定要有站内的输入,因为它并不属于注入攻击,而是请求伪造。被伪造的请求可以是任何来源,而非一定是站内。

 

所以我们唯有一条路可行,就是过滤请求的 处理者

对于发布帖子这一类创建资源的操作,应该只接受 POST 请求,而 GET 请求应该只浏览而不改变服务器端资源。当然,

最理想的做法是使用 REST 风格 的 API 设计,

GET、POST、PUT、DELETE 四种请求方法对应资源的读取、创建、修改、删除。

现在的浏览器基本不支持在表单中使用 PUT 和 DELETE 请求方法,

我们可以使用 ajax 提交请求。也可以使用隐藏域指定请求方法,

然后用 POST 模拟 PUT 和 DELETE (Ruby on Rails 的做法)。这么一来,不同的资源操作区分的非常清楚

 

令牌方法
首先服务器端要以某种策略生成随机字符串,作为令牌(token), 保存在 Session 里。

然后在发出请求的页面,把该令牌以隐藏域一类的形式,与其他信息一并发出。

在接收请求的页面,把接收到的信息中的令牌与 Session 中的令牌比较,

只有一致的时候才处理请求,

否则返回 HTTP 403 拒绝请求

或者要求用户重新登陆验证身份。

 

 

CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)。

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

为浏览器限制访问A站点下的js代码对B站点下的url进行ajax请求

    比如说,前端域名是www.abc.com,

          那么在当前环境中运行的js代码,出于安全考虑,访问www.xyz.com域名下的资源,是受到限制的。

          现代浏览器默认都会基于安全原因而阻止跨域的ajax请求,这是现代浏览器中必备的功能,

          但是往往给开发带来不便。浏览器将CORS请求分成两类:

                简单请求(simple request)和非简单请求(not-so-simple request)。

只要同时满足以下两大条件,就属于简单请求。

1) 请求方法是以下三种方法之一:

  HEAD

  GET

  POST

 

2)HTTP的头信息不超出以下几种字段:

 

  Accept

  Accept-Language

  Content-Language

  Last-Event-ID

  Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

  对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。

  Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。

 

如果Origin指定的源,**不在许可范围内**,服务器会返回一个正常的HTTP回应。

如果这个回应的头信息没有包含Access-Control-Allow-Origin字段

就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200


如果Origin指定的域名**在许可范围内**,服务器返回的响应,会多出几个头信息字段。

   1)Access-Control-Allow-Origin
    该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
(2)Access-Control-Allow-Credentials
    该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。

    默认情况下,Cookie不包括在CORS请求之中。

    设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,

    如果服务器不要浏览器发送Cookie,删除该字段即可。
(3)Access-Control-Expose-Headers
    该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法

    只能拿到6个基本字段:

      Cache-Control、

      Content-Language、

      Content-Type、

      Expires、

      Last-Modified、

      Pragma。

    如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader('FooBar')可以返回FooBar字段的值。

 

非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。

浏览器发现,这是一个非简单请求,就自动发出一个”预检”请求,要求服务器确认可以这样请求。

“预检”请求用的请求方法是OPTIONS,表示这个请求是用来询问的。头信息里面,关键字段是Origin,表示请求来自哪个源。
除了Origin字段,”预检”请求的头信息包括两个特殊字段。
(1)Access-Control-Request-Method
  该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT。

(2)Access-Control-Request-Headers
  该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,如:X-Custom-Header。

  HTTP回应中,关键的是Access-Control-Allow-Origin字段,表示http://api.bob.com可以请求数据。该字段也可以设为星号,表示同意任意跨源请求。

  否定了”预检”请求,会返回一个正常的HTTP回应,但是没有任何CORS相关的头信息字段。

  这时,浏览器就会认定,服务器不同意预检请求,因此触发一个错误,被XMLHttpRequest对象的onerror回调函数捕获。

 

posted @ 2019-03-21 15:45  jason&li  阅读(122)  评论(0编辑  收藏  举报