1

写在前面

时间:2017-05-29  7:30

距离上篇文章发布已经一个多月了,本来自己的计划是一周一记,怎么就变成月记了呢?最近工作的事情忙的焦头烂额,当然也不能排除我懒的要死的因素,有时间追择天记怎么就不能写篇博客呢?暗暗自责一分钟...

今天是端午节小长假的第二天,第一天约好和舍友逛颐和园的计划被帝都36度的高温打回来了,于是乎这帮哥们又抱着手机开黑到深夜。昨天虚度了一天,今儿一早起来雄心满满的要继续昨天的计划,无奈这几个老年人又不起床。我善心作祟,想着打扰人家美梦太不礼貌,那就,写篇博客吧,理一理一个多月来乱七八糟的事情,要不然,月记也得成年记了。

对了,在这之前,首先要祝大家端午节快乐!嘎嘎

正文

切入正题。回顾这一个多月乱七八糟的事情,其实就是一个传统的PHP程序员,拿着一套没有做用户登录状态的App接口,在考虑如何利用session建立用户会话,在接口服务端保存用户信息和登录状态。

这里要吐槽一下ci框架,奇葩的重写session机制,搞得我在postman中就是获取不到session的值,浪费不少时间。所以同志们,选择框架要慎重啊!

我拿到的API接口,是没有做任何请求验证的,就是任何人拿到接口地址就可以直接调用,这是极不安全的。我在考虑要做验证的时候,首先想到的就是传统的cookie+session机制。但是一般的API又会在请求参数或者请求头中加一个token。所以我的方案是:当用户登录验证通过之后,在服务端session中保存用户信息和一个与之匹配的token,然后将该token返回客户端,表示登录成功。接下来用户的每一次请求操作,都需要将该token带到请求头中。

这样做相当于加了两层验证。第一层就是session验证,传统的web后台验证方式。第二层是将请求头中token与session中的token匹配,全部通过,才可以去跑接口中的逻辑。

安全性做到了,下面要接客户端了。其实在接入之前,我就有点范嘀咕,客户端不会拿不到session吧?果然怕什么来什么,安卓那边告诉我session错误,取不到值。

其实这很正常,web开发中session用起来简单快速,那是因为浏览器帮我们做了很多事情。比如在session创建的时候,浏览器返回的响应头中会有Set-Cookie的选项,帮我们在浏览器本地创建cookie来保存上一步session创建时所生成的sessionid,然后下一次请求的时候又会在请求头中带上这个cookie,通过 cookie 中的 sessionid 找到对应的session数据。就好比 session 是一张用户表,cookie 中的 sessionid 就是用户表的主键 id,浏览器获取 session 数据的过程就好比是通过主键 ID 查找数据表的某条数据的过程。

但是在API中,虽然可以接收到响应头中的 set-cookie, 却不会在下一次的请求头中自动添加 cookie。没有发送sessionid,自然找不到 session 数据。所以在API中,发送请求头中的cookie,需要我们手动完成。

和安卓那边沟通,他们表示框架中可以模拟浏览器行为,实现 cookie 的自动发送。但是这套接口不光给app用,pc网页端也在用。如果要在 php curl 请求接口时手动去找 cookie 并发送,无疑会增加接口的负重,而且麻烦的很。思虑再三,我们决定放弃这种验证方式。

我纠结的是,如果不用session,那么在调用获取用户信息接口的时候,至少要将user_id作为参数传过去,但是session模式对于这种方式是不认可的,因为用户信息要在登录之后从session获取,而不是通过客户端直接传递,这会有风险。同时session最关键的还是保存用户登录状态,如果没有session,如何知道当前用户是谁?是否在登录状态?是否登录过期?

转不过弯来,于是就去查百度,逛论坛,翻来覆去,最后发现一句话很关键:API是无状态的。

对,API是无状态的,至少 restful 是这样!

API无状态,开始不理解,可是它的合理性又在慢慢得到证实。如果api无状态,那么状态只能是存在app客户端。事实上确是如此,web中用户状态存在服务器,而app存在客户端。

还有一种状况,就是现在流行的前后端分离架构,用户状态又该存到哪?我记得之前看过相关的文章,解决方案是在前端与API之间加一个 node 作为中间层。我一直不知道这层 node 是用来干嘛的,不过按照现在理解,这层 node 负责请求API,然后创建和维护 session 会话。我就是按照这种方式去做,目前看来是可行的。

所以,扯了这么多,疑问满满,牢骚满满。如果你觉得web开发和api开发的区别就是前者渲染页面,后者输出数据,那么 session 会是你绕不开的梗。session机制不是笔试题上表述session和cookie区别的答案那么弱智,你至少需要补充 http 的知识,理解请求和响应。

回到标题,api下是否使用session?标题的结尾是个问号,所以自己考虑喽。如果你没有session情结,或许,jwt是你更好的选择。

本文由 杨成功 原创,更多原创内容请到专栏 杨成功的全栈之路


杨成功
3.9k 声望12k 粉丝

分享小厂可落地的前端工程与架构