python中有个常用的关键字 with,一般大家习惯用在一些和io相关的地方,比如
|
|
|
|
python中有个常用的关键字 with,一般大家习惯用在一些和io相关的地方,比如
|
|
|
|
我们现在的B端管理网站,域名是sparrow.xxx.com 。 后端接口是 backend.xxx.com。 一直以来后端服务器都是允许跨域的,实现方式是django框架 + 包插件django-cors-headers。 惊觉为什么这样还是安全的呢?!拉上前端小伙伴大家认真重新复习了一下跨域,又动手试了试怎么能攻击到 backend.xxx.com 【捂脸】
跨域攻击的基本原理是,浏览器访问网站A,网站A登录信息等存在相应的cookie中(此处前端小伙伴说,cookie,storage等都是和域名相关的,只有访问同域名的时候才能获取到)。这时候用户在另一个页卡打开了网站Z,假如网站Z是一个恶意网站,植入了恶意js脚本,这个时候这段恶意脚本就可以带着篡改过的数据,访问网站A,并带上之前的cookie中A的登录信息等。如果A是银行网站,Z执行的恶意攻击可能就是访问A并把用户的钱转账给其他不法账户。
如果上述A网站服务器不允许跨域,Z的ajax请求访问A的时候,因为不同源(必须同样的协议比如https,同样的域名包括二级域名都要相同,同样的端口比如80),A服务器就不会响应Z的请求,也就保障了安全。
目前我们项目的配置是,普通用户只能访问网站 sparrow.xxx.com(纯前端node应用) ,sparrow里ajax访问backend.xxx.com,登录backend的方式是token认证,然后token存在浏览器。sparrow服务器是不允许跨域的(后续大家讨论允许跨域也还是安全的),backend服务器是允许跨域的,返回header里 Access-Control-Allow-Origin: * . 这样为什么是安全的呢?
这里就不得不引入另一个现实情况了——backend.xxx.com 的后端实现是django+drf。也就是提供服务端渲染的页面,可以用session的方式登录。于是又脑洞大开,那如果在浏览器第一个tab里,先用session的方式登录backend,然后在另一个tab访问恶意网站Z,由于backend是允许跨域的,Z是不是就可以用cookie里的session访问backend了,是不是就会有问题了?
Access-Control-Allow-Origin: *。 我之前一直质疑写*不是很不安全么,为什么不只写sparrow.xxx.com不是感觉更安全么。实际并不是这样。 当浏览器请求服务器,第一次option请求的时候,服务器返回response header Access-Control-Allow-Origin: * ,只有当值是*的时候,是不允许携带cookie的。回到上面假想的访问backend的时候用session的登录方式,会不会不安全?答案是安全的,因为Access-Control-Allow-Origin: * 要不就同源访问,要是非同源的话是不允许带cookie的。
HttpOnly cookies。在第一次option访问backend的时候,response header里会指明 Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly。然后这种cookie就被浏览器保护起来了,没有任何js可以直接访问这个cookie。此cookie只能在访问backend的时候被浏览器自己控制放入request header中。所以再一次保证了不被Z挟持。(这里如果想了解更多可以看看 XSS 跨域脚本攻击)
是不是感觉清楚多了,完全明白了现在的服务器允许跨域为什么是安全的了。
小伙伴们又问了,为什么现在都流行用token比如JWT取代session的方式登录呢?
作为一个后端,我认为token对后端的改进是比较大的,因为如果用session的话,数据库里需要存session表,根据前端发来的session_id查表才能获取到用户。而token比如JWT,分发之后就不需要再储存了,校验的时候只需要用secret加盐校验是自己分发出去的有效token,再从token payload 取出用户id就可以了。而对前端来说,存session_id和token,都是两个字符串,感觉没什么区别。
不过我再一次naive了。实际上token在前端对比session_id还有另一个好处,就是顺便解决了csrf跨站请求伪造问题。当浏览器通过form表单提交服务器的时候,cookie是被自动带上的,且不遵循同源原则。也就是说,如果恶意网站Z的js通过form提交网站A的服务器,且篡改了提交数据,且登录A是通过session_id存cookie的方式,就可以达到文章开头提到的转钱给不法账户的效果。这个时候通常的解决方法是通过form携带csrf token,也就是表单每次提交的时候,都需要携带A服务器分发的一个csrf token,后端会校验csrf token是否有效。这样就能避免csrf攻击了,因为Z的js是无法自己获取到一个新的有效的csrf token的。那么,如果不是用session的登录方式,而是用token authorization的方式,表单提交的时候自动带上的cookie就没用了。原理其实就类似csrf token,请求需要把JWT token从local storage取出来放在请求header里。这样流程就回到了文章上述的各流程中,也就避免了csrf攻击。所以即使对前端来说,token登录方式也比session的登录方式更有优势。
最后再看一下服务器允许跨域是怎么实现的。首先在settings.py 里配置 CORS_ORIGIN_ALLOW_ALL = True 表示允许跨域。然后查看代码 corsheaders/middleware.py 中 CorsMiddleware 中
|
|
可以看到,如果设置允许跨域,response[ACCESS_CONTROL_ALLOW_ORIGIN] = “*“ 这段代码会设置header中的ACCESS_CONTROL_ALLOW_ORIGIN为*,和我们实际查看的response header对应上了。
之前听说过一致性哈希这个概念,但是没理解应用场景。最近重新看分布式系统才发现,其实很早以前就思考过一个分布式缓存系统的问题:当有多个缓存服务器,如果用户请求的响应内容缓存在缓存服务器A,但是这次请求访问到了缓存服务器B,怎么办呢?要保证所有缓存服务器都能命中,岂不是所有数据都要冗余一份么。
当时的疑问卡在那儿,就没继续想。现在看到一致性哈希恍然大悟,一致性哈希正是可以解决分布式缓存的问题。
1.设计一个环形结构,分隔成 2^32=16384 份(slots),来源任何一个key值(暂且简单叫key值,实际上是一个用户请求内容),把key哈希,然后把哈希值对16384取模,找到这个模值在环形上的位置(slot)。如下图
2.同样的方式,把缓存浏览器的ip地址(暂时简单叫 node)也都哈希,然后把哈希值对16384取模,也找到这个模值在环形上的位置(slot)。如下图
3.key命中node的方式是,延环形架构顺时针找到最近的node,即这个请求就访问到这个缓存服务器。
这样做的好处显而易见,尤其是这种设计的单调性。当然还有一些其他特性
大家看到这里已经会发现了,那如果缓存节点的ip哈希映射到环形结构的时候,分布恰好非常不均匀,从而导致大量数据都映射在了某几个节点上,怎么办呢?
解决办法是,我们可以根据每个真实的缓存节点ip,创造一些与之对应的虚拟ip,也加入环形,使得数据分配到各真实缓存节点ip的时候基本是均衡的。
参考文献:
https://blog.csdn.net/cywosp/article/details/23397179
https://www.jianshu.com/p/49e3fbf41b9b
tag:
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true