什么是token

客户端发送HTTP请求携带的“令牌”,用来鉴权、身份验证(服务器可以知道是谁在请求)

token传输中放在哪里

1、放在url里:

叫“bearer token”票据携带者,简单,不需要前端存储,但是不安全,只适用于一些临时登录的场景。

2、放在hearder的cookie中:

cookie 的维护严重依赖浏览器行为。内存小,限制 4KB。

  • cookie 是怎么种上的?是浏览器看到 response header 中的 set-cookie 然后记录下来的。这个过程无需其他人干预。

  • cookie 是怎么管理有效期的?是浏览器看到 set-cookie 里的 age 属性然后管理的。这个过程也无需其他人干预。

  • cookie 是怎么附带在请求上的?是浏览器在发请求的时候自动附加在请求上的。这个过程还是无需其他人干预。

前端构造 ajax 请求的时候虽然可以手动设置 cookie 这个 header,但实际上请求发出去的时候会被浏览器覆盖掉,所以你想干预都干预不了。

甚至对于具有 http-only 属性的 cookie,浏览器全权托管,禁止 js 访问,他们对前端来说就是透明的(transparent)。

其实 cookie 被发明之初并不是用来做认证的,只不过大家一看,好家伙,浏览器这么贴心什么都帮你做好了,这不省事儿嘛,所以大家就把 token 放到 cookie 里了。

没错,使用 cookie 方案最大的好处就是简单,省心,浏览器帮你做完了,但最大的问题就是你得是在浏览器环境里,如果你是在 android、ios 原生应用或者小程序里面,不好意思,有关 cookie 的那一堆破事儿就得你自己打补丁做了。

cookie 方案另外一个问题是,出于安全考虑,浏览器对 cookie 有很多限制,比如同源限制,same-site 限制,跨域限制等等,有时候这些限制会让你很难受,比如明明开发测试环境都是好的,发布到生产环境就坏了,你得去检查这些环境有关 cookie 的限制以及配置是否都是一致的。

cookie方案是后端方案,后端设置响应头的cookie项,浏览器自动实现,前端不用写代码。

什么场景是 cookie 无能为力的呢?禁用 cookie 这种就不提了,有一种常见的支持不了的场景是登录隔离。比如你需要在浏览器中同时登录好多账号进行操作。因为 cookie 是根据域名绑定的,而且同名 cookie 只能保存一个,也就意味着 cookie 里面只能保留一个最新的 token,不同账号的登录状态会相互覆盖。不过有时候这反倒是一个优势。。比如你就是不想让用户多开,那么这种方式可以稍微提高一些用户多开的成本(用不同浏览器或者不同电脑仍然是可以多开的)。

容易收到CSRF攻击:Cross Site Request Forgery,跨站域请求伪造。

3、放在header的自定义字段中:

登录后后端返回token前端存储到localstorage或者sessionstorage中,在发送ajax请求时在header中加上。没有跨域限制。

什么场景是 header 无能为力的呢?不受前端代码影响的请求就没辙。比如 img 标签、link 标签、script 标签发出的 GET 请求,这些都是浏览器自己发出去的,无法注入 header 在这上面。再比如当用户在浏览器中输入一个 url 并按下回车的时候,这个 url 实际上是向后端请求了一个 html 文件,而这个请求也是无法注入 header 的。再比如使用原始的 form 表单提交的时候,表单提交的那个 post 请求也是浏览器发出去的,所以也不能注入 header。非 ajax 请求无法使用 header 方案。

当用户访问某个页面的时候:

  • 如果是 cookie 方案,那么在请求 html 的时候,后端就已经可以根据 cookie 验证当前用户是谁,是否需要登录,如果不需要登录就自动跳转到登录页面。

  • 如果是 header 方案,因为 html 请求无法携带 header,只能等 html 返回以后,浏览器解析 js,js 再发出一个 ajax 请求到后端,后端才可以得知当前用户是谁,是否需要登录。如果还未登录,再由前端 js 跳转到登录页面(因为 ajax 请求无法让页面跳转)。会让登录校验过程变得前后端耦合在一起,而且整个流程变得很长,耗时长。

  • 另一个受影响的场景是灰度访问。如果你是需要根据用户的身份信息来决定用户打开的是 A 版本还是 B 版本,那么基于 header 的认证方案就无法对 html 做灰度,也就是说 html 永远只能是一个版本。

4、放在body中:

很少见,基本没人用。

首先 GET 请求是没有 body 的,这意味放在 body 的方式无法支持 GET 请求的认证。

其次 body 通常是用来传输数据的,格式五花八门,有 json、text、form,甚至还可能是二进制,怎么跟数据共存是个蛋疼问题。

总之,通常没人会把 token 放 body 里,除非是有一些非常特殊的情况。

token存储在哪里

如果使用3方案,token需要前端存储在浏览器本地,一般是localStorage和sessionStorage中:

localStorage与sessionStorage

数据大小一般都是:5MB
sessionStorage 和 localStorage 的编程接口是一样的。
sessionStorage 和 locatlStorage 区别在于 数据存在时间范围 和 页面范围。

sessionStorage: 数据只保存到存储它的窗口或标签关闭时,数据在构建它们的窗口或标签内也可见

localStorage: 数据的生命周期比窗口或浏览器的生命周期长,数据可被同源的每个窗口或者标签共享,如果一个浏览器同时打开两个tab,localstorage和cookie是共享的,sessionstorage是不共享的

localStoragese:常用于长期登录(+判断用户是否已登录),适合长期保存在本地的数据。sessionStorage:敏感账号一次性登录。

注意:
localstorage,sessionstorage在浏览器无痕模式下会存在丢失问题
 

 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐