怎么编写用户注册/登录服务

看似简单的注册登录功能,如果想考虑完善,并且做到极致体验和良好的安全性,并不是一件容易的事情。本篇文章就结合我们公司的登录体系来分析一下怎么去做好一个用户注册与登录功能。

密码设置与传输:

用户在注册的时候最好对密码的强度做验证,防止弱密码。其次切记不能将密码明文传输,一般的做法是前对对密码做一次Md5加密,后端再做一次Md5加密然后出到DB中。

请求参数签名与验签:

现在主流的开发模式是前后端分离,那么前端再对参数加密的时候,怎么管理盐值?盐值怎么在请求中传递?服务端怎么在不侵入业务的方式下做到验签?
接下来主要讲讲Token(CrsfToken/UserToken)在请求加解密中的使用方式:
  • UserToken是通过用户基本信息和CrsfToken进行AES加密生成,并存储到用户的Cookie中,每次请求的时候浏览器自动会携带Cookie进行数据请求,这样服务端就可以从request中获取到Cookie对象。UserToken的主要作用是进行验签。
  • CrsfToken的作用是防止CRSF攻击,传统的做法是在form表单中加入此参数,后端验证crsfToken的有效性,但是这种方式对业务有侵入性,比较好的做法是无业务侵入就完成预防Crsf的功能。我们采用的方式是用户登录成功后将CrsfToken存储在浏览器的localStorage中,每次请求的时候使用CrsfToken作为盐值对参数进行Md5签名,网关从请求的Cookie中取出userToken并AES解密出CrsfToken,再进行验签。用户退出或者userToken时效的时候都会主动从LocalStorage中清除CrsfToken,从cookie中清除Token和用户信息,任何需要访问用户登录态的数据因为都需要加密,所以首先会判断CrsfToken是否存在,不存在直接跳登录页了。

下图为JS方式使用CrsfToken对请求参数进行加密处理:
js-url-param-sign
下图为页面服务请求时Request中Cookie携带的userToken信息:
user-token-cookie
总结:
这就相当于把加密使用的盐值超出在用户的浏览器中,盐值并不会在每次请求中传递,只用来加密使用,每次在请求中传递的是使用盐值+用户的基本信息进行AES加密生成的秘钥Token,网关系统从此秘钥Token中反解密出CrsfToken来验证请求的合法性。这种实现方式在攻击者未拿到localStorage中的CrsfToken时是无法生成正确的签名值的,所以就在一定程度上解决了CRSF攻击问题。假设攻击者劫持了用户登录请求,就可以拿到CrsfToken,就有可能被CRSF攻击,所以在Web端简单处理办法是用户每次重新登录都会更新CrsfToken和userToken。当然,如果网站上了HTTPS的话,攻击者就无法获取到CrsfToken了。
其次,通过自主管理Cookie的生命周期,也可以完成用户登录态的维护。
那你肯定会问App端如何存储CrsfToken,如何通过Cookie传递用户登录态,如何在多设备上同时登录?

图片/短信验证码:

现在大部分的网站注册基本都使用的是手机号注册的方式,那手机号注册为了验证手机号的正确性,一般都会使用手机验证码,考虑到短信成本,在下发手机验证码前为了防止机器攻击,会加上图片验证码。
那怎么选择有效的图片验证码服务?如果你随便从网上找一段生成验证码的代码,很不幸告诉你,你找的很可能会被破解,现在图片验证码识别的技术还是也算比较成熟,回想一下12306的图片验证码吧。如果图片验证码做的太复杂,干扰元素太多,那么又会降低用户体验,直接影响是用户注册率。怎么寻找一个体验好的图片验证码方案呢?
目前我认为有两种选择,第一,自主编写一套服务,在用户体验和安全性上寻求一个平衡,我们目前使用的是Captcha,体验还不错。第二,采用三方图片验证服务,比如类似于极验的厂商。
fqht-regist
geetest-captcha
目前图片验证码的服务实现一般分为两部分,一部分是通过sessionId生成图片验证码,一部分是使用sessionId校验用户输入的验证码的正确性,验证完毕后就会从服务端清楚缓存的sessionId对应的图片验证码。
短信验证码:
短信验证由于一定的延迟性,基本会考虑60s下发一次,服务端也要控制一下同一来源短信下发的次数,做好一定的风控防范。短信下发中好的用户体验的几项考核指标是短信下发送达率、送达时效、多网支持度等,试想,你兴致傲然的注册一家网站,结果半天收不到短信,试了N次未果,这是怎么样的糟糕体验,所以选择一家优质的短信提供商很有必要。
短信验证业务实现原理:
上面讲到了图片验证码,在下发短信钱强制图片验证码必填,这个时候用户点击获取短信验证码的时候首先验证图片验证码的有效性,如果图片验证码有效,在验证用户是否符合下发短信的限制条件,为什么要这部分呢,因为在一些恶意攻击情况下,防止短信成本增加,是需要对恶意攻击进行风控的,其次,就算不是恶意攻击,也需要配合前段做60s限制,最后生成随机数缓存Redis,并调用短信服务商的短信发送接口。

多域登录:

其实我们这里阐述的方式是通过自主管理Cookie的生命周期来达到多系统共享登录态的,如果我们有fengqu.com 和 fengxiang.com两个域名,想公用登录体系,能否还利用Cookie的实现方式实现呢?答案是可以但稍微麻烦。因为对于Cookie,处于安全性考虑,它有一个作用域问题,这个作用域由属性Domain和Path共同决定的。也就是说,如果浏览器发送的请求不在此Cookie的作用域范围内,请求是不会带上此Cookie的。我们的网关就无法拿到Cookie中的userToken,也就无法做验签;怎么办呢,我们需要一个SSO,来做Cookie的中转操作,这部分晨悟同学在阿里做了不少SSO的工作,经验丰富。

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s