最近选用了 React + React-Router 的技术栈,天然而然走了 SPA 的路线,下面总结下在所谓的 SPA 下的一些技术点的坑。前端
现有方案
登陆页面发起 Ajax 请求得到用户 token,把 token 存放在 localStorage 里面,而后经过前端路由跳转到用户主页。随后用户相关的请求都会在 http head 里面带上这个 token。服务器端只负责验证每次请求中 token 的合法性(譬如:是否过时)。git
遇到的问题
把 token 保存在 localStorage 中主要考虑用户打开浏览器多个 tab 页能够维持登录态。可是存储在 localStorage 里面的 token 面临以下问题:github
被串改的风险比较大,一旦被篡改,能够跨用户操做。redux
多帐号登陆相互覆盖 localStorage 中 token 的问题。后端
解决方案
针对多帐号登陆相互覆盖的问题,现有采起的方案是在登陆后分别在内存和 localStorage 里面保存一份 token,每次要用到 token 的时候都去对比一下,若是检测到不同则提示用户关闭当前窗口防止串号。这么作的目的一来防止用户本身被多个帐号误导,二来若是关闭了检测到串号的窗口,不影响后登陆的那个帐号使用(固然若是前一个窗口不关闭也没有问题,js 使用的始终是内存中的 token)。<br/>浏览器
可是当同一个用户开多个窗口,那么新开的窗口中的 token 第一次获取就只能从 localStorage 里面获取。这时就有 token 被篡改能够跨用户操做的风险。针对这个风险我预想了解决方案(须要用到 session 存储 token):服务器
1. 在已经登陆一个帐号的状况下,不容许开新浏览器窗口进行其余帐户的登陆,即若是检测到当前已是登陆态则不容许用户停留在登陆页。  2. 在已经登陆一个帐号的状况下,容许开新浏览器窗口进行其余帐户的登陆。 
这种状况下若是登陆了第二个帐户,第一个窗口(第一个帐号)要再进行任何操做,传回的 token 就和 server session 中的 token 不匹配,server 就能够返回状态码让前端把用户登出。session
若是多路由之间有相关的业务数据,那么为了减小请求,提升用户体验,最好把多路由相关的数据共同抽象到一个地方,譬如 redux 的 store 里面。这样一个路由改了数据,当切换到另外一个路由就不须要从后台再拉一遍数据的最新状态。这点对于单人开发没有问题,可是对于多人协做就须要提早设计数据存放结构,约定接口。一边作一边改就容易出现沟通问题,数据架构也不容易统一。架构
针对有异步任务的状况就要考虑状态更新的问题。由于页面提交了一个请求修改数据,可是数据被修改的最新状态没法当即体如今当前界面上,那么就会有以下问题:异步
页面如何处理中间态即处理中的状态提示。
页面是否须要接入服务器推送,等异步任务完成后把结果推送到页面来更新状态。
异步任务尚未完成,用户刷新了页面并又提交了相同的任务如何处理。
问题1若是中间态存储在前端,一旦用户刷新页面或者新开页面就转换成问题3了,因此后台必定要作好验证,前端没法严格维持状态。还有一种状况就是后端存储中间态,那么不管是刷新仍是新开页面用户都可以看到中间态也会避免提交重复请求,可是这种方案就增长了后端的复杂度,须要根据项目的需求自行决定。
问题2涉及两个方面:一来是接入推送服务增长复杂度的问题,须要酌情考虑。二来是提升用户体验的问题若是最新的状态须要及时通知到用户,那么推送方案就要在技术选型时考虑在内。
这个问题最典型的就是项目管理工具,针对同一个任务两我的同时开着界面,若是一我的认领了,那么另外一我的通常状况下是没法知道的,可能会形成“误操做”。这个时候增长推送功能能极大的提升用户体验。