Fuck me on GayHub

认证平台思考

做了这么久的后台,发现有的东西是重复在劳动,例如CRUD操作,权限系统,认证系统。这里我主要想思考关于认证系统的问题。

之前每做一个系统,就需要实现一个登录认证系统,例如我做了消防系统的登陆认证功能,体育局的登录认证功能,美丽阅读的文章编辑后台的登录认证,书籍审查的登录认证,这个动作不知道要持续多久。

海叔给我讲过他的想法,他想把公司内部的登陆认证分离出来,这样所有的客户端以后使用统一的登陆认证,我觉得这个想法有点像谷歌的认证,豆瓣的认证,阿里巴巴的认证等。当一个公司有越来越多的产品系统时,就需要把公共的部分抽象实现出来,这样后续的项目就可以简洁明了了。所以现在建立认证平台对美丽阅读来说是一个好的时机。

那么如何逻辑上实现现有的认证平台呢?首先建立一个系统,实现用户的CRUD操作,这样就可以相应的实现注册,登录,登出功能了。若登陆成功,返回JWT的token,并且设置超时为3600秒。以后客户端需要访问其它的系统的API就带上这个JWT token即可访问,这样其它系统就不用担心认证相关问题,而专注与自己的业务逻辑了。若是客户端的JWT token失效,则可以重新登录获取新的token或者使用认证系统返回的refresh token刷新当前token。如此反复。

token模式作为用户名密码的后续模式,如何标识一个用户呢?在JWT token的payload里面我们可以添加我们自己的任何想要的内容,所以可以在这里里面填写用户信息,那么这个token就表示了当前的用户。由于所有的token统一由认证平台签发,所以这些token所标识的客户端是可信的。

唯一标识客户端后,刷新token如何做到继续保持原有的对用户的标识呢?若是原有的token有效,即在有效期以内更新,可以先解析原有的token,得到里面的payload,然后根据payload里面的refresh id和客户端提供的refresh id是否相同来刷新并返回新的token。若不相同,则报错返回。这里面的refresh id放置了两个地方,一个是在JWT token内部的payload,另一个作为返回的数据给客户端。所以大概认证平台返回的Json数据如下:

1
2
3
4
5
6
7
8
9
10
{
err: false,
msg: 'Successful',
data: [
{
jwt: 'fafdsaafasf.dsfjldsfsdaf.fjdslafsdf322',
refreshid: '2dyfhfds42fsaflds99283203829332'
}
]
}

客户端认证后需要保存jwt和refreshid这两个字段,以保证后续的访问能正常进行。若客户端没有在规定的时间内(3600秒)刷新jwttoken,那么客户端将丢失掉访问系统其它api的权限,只能重新使用用户名和密码登陆了。

在客户端获取到JWT token后,有两种方式提交token到后端进行验证,一是通过url参数,如https://passport.beautifulreading.com?jwt=fdsjalfdsafs.fdyidf3232jfds.893743djdfsdf,另一种是将jwt放置到http请求的header里面,设置Authentication为jwt字符串。一般来说,比较倾向与使用后一种方案。

颁发jwt的方式有了,那么在哪里验证jwt呢?例如用户访问了music.beautifulreading.com的api时候,哪里验证jwt的有效性呢?为了能使每个系统专注于做自己的事情,所以这个验证不能在请求到达music.beautifulreading.com后验证,必须在请求到达music.beautifulreading.com之前就验证其有效性。所以这个时候需要一个API Gateway,将所有的请求都先发往认证平台,认证平台处理没有问题,在返回给实际的系统处理。一般来说,这个API Gateway就显得尤为重要了。Kong是Mashpe开发的API Gateway,并且开源,实际上使用Nginx搭配Lua对进来的请求做转发等逻辑操作。根据实际请求的URL,Nginx Lua提取token先判断其有效性,若有效将请求发往实际系统进行处理,若不符合要求直接返回错误数据。

当每个请求都要被Nginx截取并处理的时候,会不会减缓访问速度?理论上是会慢的,但是慢多少就值得商榷了。若为了系统的模块化,简洁性,建议将认证平台与API Gateway独立出来,若为了极致的速度,可以将认证系统实现在API Gateway当中,这样就只是慢了一个API Gateway的本地处理速度。

对于API Gateway的相关问题,我现在还是不那么完全清楚,有待调查。不过将认证平台独立,对于后续功能的完善是个不错的选择,例如实现Oauth2.0协议等等。

带有API Gateway的认证系统和其它系统要求其URL都有一定的规则性,这样Gateway就可以很方便清晰的处理。

对于使用token方式的系统来说,没有了会话的概念,怎样获取像当前登录用户等一些信息呢?一种方式是在存储中记录登录的用户信息等。另一种方式则是使用日志系统来记录每次请求,若要统计在线人数,则可以去日之中进行统计。哦,这里又引出了一个日志系统。