3

最近选用了 React + React-Router 的技术栈,自然而然走了 SPA 的路线,下面总结下在所谓的 SPA 下的一些技术点的坑。

登录态的维持

  1. 现有方案
    登录页面发起 Ajax 请求获得用户 token,把 token 存放在 localStorage 里面,然后通过前端路由跳转到用户主页。随后用户相关的请求都会在 http head 里面带上这个 token。服务器端只负责验证每次请求中 token 的合法性(譬如:是否过期)。

  2. 遇到的问题
    把 token 保存在 localStorage 中主要考虑用户打开浏览器多个 tab 页可以维持登陆态。但是存储在 localStorage 里面的 token 面临如下问题:

    • 被串改的风险比较大,一旦被篡改,可以跨用户操作。

    • 多账号登录相互覆盖 localStorage 中 token 的问题。

  3. 解决方案
    针对多账号登录相互覆盖的问题,现有采取的方案是在登录后分别在内存和 localStorage 里面保存一份 token,每次要用到 token 的时候都去对比一下,如果检测到不一样则提示用户关闭当前窗口防止串号。这么做的目的一来防止用户自己被多个账号误导,二来如果关闭了检测到串号的窗口,不影响后登录的那个账号使用(当然如果前一个窗口不关闭也没有问题,js 使用的始终是内存中的 token)。<br/>

但是当同一个用户开多个窗口,那么新开的窗口中的 token 第一次获取就只能从 localStorage 里面获取。这时就有 token 被篡改可以跨用户操作的风险。针对这个风险我预想了解决方案(需要用到 session 存储 token):

1. 在已经登录一个账号的情况下,不允许开新浏览器窗口进行其他账户的登录,即如果检测到当前已经是登录态则不允许用户停留在登录页。
![singleuser](https://cloud.githubusercontent.com/assets/631198/20826318/fbc8f078-b8a4-11e6-9401-ede5ff1294b1.png)
2. 在已经登录一个账号的情况下,允许开新浏览器窗口进行其他账户的登录。
![multiuserlogin](https://cloud.githubusercontent.com/assets/631198/20826352/3971b34c-b8a5-11e6-9082-47515404346d.png)

    这种情况下如果登录了第二个账户,第一个窗口(第一个账号)要再进行任何操作,传回的 token 就和 server session 中的 token 不匹配,server 就可以返回状态码让前端把用户登出。

多路由模块共享数据同步问题

如果多路由之间有相关的业务数据,那么为了减少请求,提高用户体验,最好把多路由相关的数据共同抽象到一个地方,譬如 redux 的 store 里面。这样一个路由改了数据,当切换到另一个路由就不需要从后台再拉一遍数据的最新状态。这点对于单人开发没有问题,但是对于多人协作就需要提前设计数据存放结构,约定接口。一边做一边改就容易出现沟通问题,数据架构也不容易统一。

异步任务的状态问题

针对有异步任务的情况就要考虑状态更新的问题。因为页面提交了一个请求修改数据,但是数据被修改的最新状态无法立即体现在当前界面上,那么就会有如下问题:

  1. 页面如何处理中间态即处理中的状态提示。

  2. 页面是否需要接入服务器推送,等异步任务完成后把结果推送到页面来更新状态。

  3. 异步任务还没有完成,用户刷新了页面并又提交了相同的任务如何处理。

问题1如果中间态存储在前端,一旦用户刷新页面或者新开页面就转换成问题3了,所以后台一定要做好验证,前端无法严格维持状态。还有一种情况就是后端存储中间态,那么无论是刷新还是新开页面用户都能够看到中间态也会避免提交重复请求,但是这种方案就增加了后端的复杂度,需要根据项目的需求自行决定。

问题2涉及两个方面:一来是接入推送服务增加复杂度的问题,需要酌情考虑。二来是提高用户体验的问题如果最新的状态需要及时通知到用户,那么推送方案就要在技术选型时考虑在内。

多人操作同份数据

这个问题最典型的就是项目管理工具,针对同一个任务两个人同时开着界面,如果一个人认领了,那么另一个人一般情况下是无法知道的,可能会造成“误操作”。这个时候增加推送功能能极大的提高用户体验。


Bernie维尼
388 声望21 粉丝

引用和评论

0 条评论