自动摘要
正在生成中……
看了两天 restful api
和csrf,我觉得slim3
的csrf中间件设计得太过度了,带来了不必要的麻烦。
1. 是生成机制,生成的csrf token
值要用随机字符串可以理解,为什么生成的key也要用随机字符串,而这个随机字符串的key
所起的作用只是存储token value
的一个键,而为了检验这个key
,客户端不但要提供csrf token
值的字段,还要额外提供一个key
的隐藏字段,完全没必要搞得那么复杂 ;
2. 是csrf token
验证过一次后,立刻销毁并且重新生成,也就是说token
是一次性有效,貌似是更安全了,可这也带来了其他的问题,在普通的网页请求中没有问题,问题在于使用ajax
请求时,同一个页面可以发起多个请求,就意味着第一个请求后,csrf token
被销毁,后面再用这个token
就无效了,解决方法是一个请求成功后,在响应的数据中返回一组新的token
,在后续的请求append这个token
。或者新增一个专门获取csrf token
接口,我看到有篇文章提到这个方案,他是把Django
的csrf token
机制改成一次性的,但我可以想到这样做的一些安全隐患,如果接口被跨域,比如支持CORS
,或者用flash
主动请求这个接口就可以在站外获得一组 token
,再配合构造一个提交页面,就可以通过csrf
验证。不过我又想到如果用其他方式,只要支持cors
和用flash
请求,依然可以通过其他接口获得token
,好像只能说明不恰当地配置cors
危害很大,至于 flash
我不太了解,存疑。
我依然认为没有必要做一次性的csrf token
,同时可以简化csrf
的结构,目前的结构是哈希数组 比如:[{hash_key1:hash_token1},{hash_key2:hash_token2}]
,这意味着客户端必须提交两个输入值,我觉得只要放在一个普通的有序数组就可以了比如 [ hash_token1, hash_token2 ]
,而还有一点,这个中间件只能从请求体获取token,不会从请求头取得,在做ajax请求时又是不舒服的,于是我继承这个Guard类自己实现了一个新的子类,并暴露出一些给twig用的助手函数。
还有一些关于jwt
的思考,我在考虑做api的用户认证时看到的。如果用传统的session
或者cookie
的方式,必须提供一组csrf token
,没有问题,WordPress Rest API
默认就使用这种方式 ,而对jwt ,有些误解认为这个天然防CSRF
,这分两种情况,取决于jwt
的验证机制,客户接收到jwt之后,可以存储在cookie
或者local storage
,如果将token
存储在cookie
里的,那么请求接口时会自动带上cookie
,如果服务端只对cookie
验证jwt
,这样依然会被csrf ,这种情况还是要附上csrf token
追加保护;如果存储在local storage
,请求的时候附在请求头,如
Authorization: Bearer <token>
这样确实可以防 csrf
,因为local storage
不能跨域读取,所以可以认为这个操作是安全的。
阮一峰这篇 JWT 入门的文章写得很不错, 文章讲到传统的session
机制存在的一个缺点,很难支持两个站点同时登录,jwt
似乎是可以解决这个问题,但具体的流程文章没有详述,我模拟一下这个过程,用户在A站点登录后,获得一个jwt
,这时用这个token
向B站点请求,把token
放在请求头,如果是浏览器环境,B站点首先应该支持cors
, 但如果支持cors
,用传统的session/cookie
也能做到同步登录,不过服务器需要配置session
的跨站点校验,比如用redis
管理共同的seesion
,不过能做到不代表容易做,用jwt
确实更简单一些,不过我认为jwt
的意义可能更多在手机app、支持跨域的小程序,浏览器扩展等,这仍然是一个值得使用的技术。