Chrome调试时的net::ERR_BLOCKED_BY_CLIENT错误
在用Chrome做调试时,发现始终不能GET某个.js
资源。
在“Network”里,发现对这个.js
的GET请求没有显示任何status code(不是常见的404错误)。
在Console里,发现有如下的报错:
GET http://foo.com/bar.js net::ERR_BLOCKED_BY_CLIENT
最后发现是Chrome的AbBlock插件引起的问题。 因为bar.js里有一些弹框的代码,所以AbBlock为了阻止弹框广告,阻止了对它的请求和执行。 在域上禁用AbBlock后,就一切正常了。
Session Management Cheat Sheet
Session Management Cheat Sheet
OWASP出品的关于session的非常详细的cheat sheet。 重点讲了如何安全地管理session。 session做为一种和用户名&密码等效的认证手段,session管理的安全性是很重要的。
JSON Web Token和Cookie的比较
Cookies vs Tokens: The Definitive Guide
JSON Web Token (JWT)和基于cookie的认证机制的比较。
基于cookie的authentication需要在服务端记状态。 而JWT是stateless的,这样服务的水平扩展性更好(不用考虑类似session replication这样的问题)。 不像cookie,JWT可以cross domain。 使用JWT后,API的使用者可以不局限于浏览器,这样对mobile app更友好。 session机制需要一些服务端查找,相比而言可能JWT的性能会好点。
想起了Rails的EncryptedCookieStore。 EncryptedCookieStore和JWT一样也是完全存在于client端。 和JWT的一个不同点是EncryptedCookieStore会加密内容,JWT不会(JWT只是sign)。
基于cookie的session机制可以在服务端让session失效。 JWT则需要在客户端做失效。
安全地存储用户密码
Storing User Passwords Securely: hashing, salting, and Bcrypt
在存储密码的数据库被攻破的前提下,破解密码的成本越高则密码的安全性就越高。 一般来说,密码在存储到数据库前都经过hash加密。 需要考虑hash函数的性能对密码安全性的影响。 比如对于SHA256来说,当前的普通计算机能在一秒内计算数百万的hash值,定制的计算机则可以提供每秒数十亿次的hash运算。 在这种情况下,很多密码安全的设计都变得不再安全。
首先,最不安全的方式是明文存储密码。 其次,对密码明文进行sha1加密、对密码明文进行sha1加密时加上固定的salt值、为每个用户分配不同的salt值都是不安全的。
推荐使用bcrypt加密密码。
bcrypt相比sha1等来说更慢,这意味着破解密码的cpu成本更高。
比如log_rounds
值设为10时,大概需要100毫秒来计算hash值。
还可以通过增加log_rounds
值来抵消未来计算机运算能力的提高。
一些bcrypt实现还原生支持per-user-salt。
Dropbox也主要采用了per-user-salt加bcrypt来存储用户密码。 Dropbox在用bcrypt hash之前,会先用SHA512对密码做预处理——把密码hash成512 bit的定长字符串。 预处理有两个作用:一是对于很短的密码,提高它的entropy(熵);二是防止输入密码过长造成潜在的DoS attacks风险(bcrypt很“慢”)。 Dropbox还引入了global pepper(既有“盐”又有“胡椒粉”)——对bcrypt的hash值再用AES256做进一步的加密。 pepper存储在数据库之外的地方。AES256是对称加密,方便未来更新pepper值。
Ruby on Rails框架的历史
Rails从0.9.3版本开始到当前版本的所有Changelogs。 自“底”向“上”过一遍这些Changelogs,可以了解一个web框架(该有)的功能和演化。
Changelog(总)是了解一个软件(新)功能的最佳文档。
Cross-Site Scripting (XSS)
来自Ruby on Rails Security Guide的一个章节,内容基本上是和特定web框架无关的,推荐一读。
Encode String before Put It into URL
在实现、测试OneFeed的tag功能时,发现tag c++
不能正常工作,
<a href="<%= '/posts?tag=' + t.name %>" class="..."><%= t.name %></a>
请求/posts?tag=c++
到达server端后,params[:tag]
的值为c
,导致数据库查询没有返回正确的结果。
原因是构造href
时没有对tag的name做encode,而+
恰好是URL规范里的特殊字符,它代表一个空格。
Within the query string, the plus sign is reserved as shorthand notation for a space. Therefore, real plus signs must be encoded.
所以,在把一个字符串拼接到URL里前,要先把它encode一下。
毕竟,不是每次测试时都有足够运气使用像c++
这样测试数据,提前发现bug。
在Rails里可以通过下面的方法来encode一个字符串,
URI.encode 'c++ java'
# => "c++%20java" 空格被encode,URL规范的特殊字符“+”没有被encode
ERB::Util.url_encode 'c++ java'
#=> "c%2B%2B%20java" 所有字符都被encode,包括像"+", "/", "?"这样的保留字符
<!-- fix: u是url_encode的alias -->
<a href="<%= '/posts?tag=' + u(t.name) %>" class="..."><%= t.name %></a>
关于URL decode,大部分web框架都会自动decode。
注意⚠️,“URL”也包括同一页面内的anchor
<a href="#need-to-encode-too">about</a>
<div id="need-to-encode-too">About us...</div>
另外,在准备测试数据时,别忘了中文;中文也是需要encode的。