好久没有写了,写个登录授权的系统规划吧
A、背景:
每个系统都分为两种方式来访问,
一种是游客访问,可能有些功能是受限的
另一种是登录访问,需要用户名和密码构成该用户的登录内容
B、一个登录授权系统,应该包括如下几个模块:
1、用户名密码登录模块
2、token授权模块
3、缓存模块
4、对外远程调用接口
5、其他可能有的设计
C、同时应包含至少如下三张表的数据库设计
1、login表,用于存放用户登录的用户名,密码,token,最后登录时间等
2、user表,用于存放用户的基础信息,也用于找回密码
3、login_log表,用于存放登录记录,包括IP,使用密码,登录设备号等
4、异常信息表
D、大概的数据库设计如下:
1、login表:
login_name: 登录用户名
password: 登录密码
user_id: user表id
real_name: 真实姓名
wx_name: 微信登录名
zfb_name: 支付宝登录名
login_phone: 手机号登录名
login_email: 邮箱登录名
token: 鉴权码
login_at: 最后登录时间
login_equ_type: 登录设备类型
login_equ_mac: 登录设备号
login_equ_name: 登录设备名称
status: 账户登录状态
version: 数据版本
2、user表
略
3、login_log表
略
4、异常信息表
略
E、注册
注册应当使用用户名或密码注册,对于使用其他方式授权登陆的,如微信,依然应当注册完善信息,应完善的信息包括用户名,密码,电话号码,真实姓名,至少包括这些内容
注册后应计算出token,并且写入当前登陆的时间,status状态,version为1
接口和参数,返回值设计如下:
①获取数据库连接
②查询用户名或微信名等记录
③评定记录是否存在
④若存在,则返回已存在的报错
⑤若不存在,则创建用户
⑥创建token,应为userId对10取余的整数作为前缀+32位uuid,其中前缀用于分库分表使用,也可以不使用,数据量不超过500w可以不使用
⑦返回创建的用户,不包括userId
⑧写入缓存
F、写入缓存
用户基础登录信息,应当是写入缓存的,这个并不会十分占用空间,可以尝试插入大量数据,加载进缓存试一下看看何时会达到瓶颈
写入缓存的内容,主要是用户授权登陆的信息。
用户在同一个浏览器,或同一个设备登陆的时候,是持有上一次发放的token的,此时的token应当写入缓存,需要对外开放接口,以token查询当前的用户信息
包括用户的id,上次登陆时间等
这些信息用于获取授权,获取业务数据
这里的缓存,可以用很多形式,但是是因为使用token查询获取用户的id,这个缓存最好采用分级的策略,或者使用树形的map,比如TreeMap
由于token生成的时候,是带有固定的前缀的,这个前缀可以用来做区分,减少查询的总量
G、自动登录
根据token查询到userId,即,
①前端业务请求发送token给登录授权系统
②登录授权系统根据token查询缓存
若查询到,则返回userId给业务数据库,不应当直接返回给前端
若没有查询到,则返回错误给业务数据库,同时记录此异常信息,记录请求的token,时间,IP等信息,并且将此异常的ip和mac记录到另一个异常查询缓存中
若异常缓存中已经出现的时间比较近,比如一分钟十次以上,则应当拒绝访问,将ip和mac信息写入拒绝缓存中,即本次服务器的拦截器interceptor都应当拒绝此访问
同时返回值要求其重新手动登录
缓存数据结构设计大概如下:
userCache=[
cache01:[
{token:userId},
......
],
...
]
H、手动登录
根据传递过来的参数,确定是以什么登录,如使用登录名,还是微信,还是支付宝,还是手机号来登录的
①如果使用的登录名,则鉴定密码是否符合规范,若符合,则根据用户名获取login表数据,获取到密码,对请求参数密码进行md5加密,和数据库已加密密码进行比对,是否相等
②如果使用wx登录,支付宝登录,则使用第三方接口,获取其唯一参数,从数据库中查询该参数是否存在
③如果使用手机号登录,则请求第三方接口,获取验证码,并发送给用户,将其验证码放入缓存,同时放入过期时间,等待取用
④如果使用邮箱登录,和登录名要求相同
⑤手动登录后,将生成一个新的token,将token作为返回值返回给客户端,让其做本地保存
I、找回密码
找回密码,可以使用登录信息+历史密码找回,或发送邮件找回,或手机找回,一般使用一种方式即可保证安全了
J、拦截器
拦截器用于短时间内将频繁的后端请求加入到和名单,限制一定时间内访问,节约controller线程
比如,从缓存中查询到某个访问token不存在,则作为攻击记录,查询攻击缓存,若此缓存中存储的记录已经大于5个,则应当计算最早时间和最晚时间,如果此时间间隔在1分钟之内,则拒绝,此时修改此5条记录,为1条,然后添加状态为拒绝状态
缓存数据结构设计大概如下
InterceptorMao={
checkIp:{
[
checkMac:{
status:'able\disabled',
at:'time'
},
...
]
}
}
大概就这样吧,有空把这个代码写了