几天以来,我一直在为我的单页应用程序寻找安全的身份验证和会话管理机制。从许多教程和博客文章中可以看出,关于SPA和身份验证,将JWT存储在localStorage或常规Cookie中似乎是最常见的方法,但it's simply not a good idea to use JWTs for sessions因此它不适用于此应用程序。使用HttpOnly基于cookie的身份验证和会话管理的单页应用程序
要求
- 登录应该是revokable。例如,如果在用户的帐户上检测到可疑活动,应该可以立即撤销该用户的访问权限并要求重新登录。类似地,密码重置等操作应撤销所有现有登录。
- 身份验证应通过Ajax进行。之后不应该发生浏览器重定向(“硬”重定向)。所有的导航应该在SPA内进行。
- 一切都应该跨域工作。 SPA将在www.domain1.com上,服务器将在www.domain2.com上。
- JavaScript应该无法访问服务器发送的敏感数据,例如会话ID。这是为了防止恶意脚本可以从常规cookie,localStorage或sessionStorage窃取令牌或会话ID的XSS攻击。
理想的机制似乎是使用HttpOnly
包含会话ID的基于cookie的身份验证。该流程的工作是这样的:
- 用户到达一个登录页面,并提交自己的用户名和密码。
- 服务器对用户进行身份验证,并将会话ID作为
HttpOnly
响应cookie发送。 - SPA随后将此cookie包含在对服务器进行的后续XHR请求中。这似乎可以使用
withCredentials
选项。 - 向受保护端点发出请求时,服务器查找cookie。如果找到,它会交叉检查该数据库表的会话ID以确保该会话仍然有效。
- 当用户注销时,会话将从数据库中删除。用户下次到达网站时,SPA会收到401/403响应(因为会话已过期),然后将用户带到登录屏幕。
由于cookie具有HttpOnly
标志,因此JavaScript将无法读取其内容,因此只要通过HTTPS传输它就可以避免攻击。
挑战
这里的具体问题,我碰上了。我的服务器被配置为处理CORS请求。认证用户之后,它正确地发送的cookie的响应:
HTTP/1.1 200 OK
server: Cowboy
date: Wed, 15 Mar 2017 22:35:46 GMT
content-length: 59
set-cookie: _myapp_key=SFMyNTYBbQAAABBn; path=/; HttpOnly
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
x-request-id: qi2q2rtt7mpi9u9c703tp7idmfg4qs6o
access-control-allow-origin: http://localhost:8080
access-control-expose-headers:
access-control-allow-credentials: true
vary: Origin
但是,浏览器不保存的Cookie(当我检查Chrome的本地饼干它不存在)。所以,当下面的代码运行:
context.axios.post(LOGIN_URL, creds).then(response => {
context.$router.push("/api/account")
}
和账户页面被创建:
created() {
this.axios.get(SERVER_URL + "/api/account/", {withCredentials: true}).then(response => {
//do stuff
}
}
此调用没有在标题中的cookie。因此服务器拒绝它。
GET /api/account/ HTTP/1.1
Host: localhost:4000
Connection: keep-alive
Accept: application/json
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Referer: http://localhost:8080/
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: en-US,en;q=0.8,tr;q=0.6
我是否需要做一些特殊的事情来确保浏览器在登录响应中收到cookie后保存cookie?我读过的各种人士称,浏览器保存响应cookie只有当用户被重定向,但我不希望任何“硬”重定向,因为这是一个SPA。
有问题的SPA是写在Vue.js,但我想它适用于所有的温泉。我想知道人们如何处理这种情况。
其他的东西,我对这个话题阅读:
- SPA best practices for authentication and session management
- Are HTTPOnly Cookies submitted via XmlHTTPRequest with withCredentials=True?
- Stop using JWT for sessions, part 2: Why your solution doesn't work
嗨PHP只是验证!你找到这个问题的原因吗? – Yuriy