本文信息
- 本文创建于2018/03/22
- 2018/10/30 文章更名为
一个简单的用户登录与访问权限控制设计
前述
- 系统用户分为管理员用户、普通用户
- 管理员用户有且唯一
- 系统初始状态不存咋任何用户,首次使用需创建用户(admin)
前端界面显示控制
用户管理模块
根据本地credentials判断是否为管理员用户 => 显示/不显示用户管理模块
导航栏模块
- 功能页面显示导航栏;welcome/login不显示导航栏
- 动态控制导航栏的显示与隐藏
前端本地控制(进入页面前)-- 路由守卫
welcome/login页面
- 是否本地存在credentials(包含token及用户信息)(是否属于已登录状态) => 跳转至首页/Next
- 发送请求至后端 => 后端确认是否首次使用系统(系统有/无任何用户)=> welcome/login页面
功能页面
是否本地存在credentials(是否属于已登录状态) => 进入功能页面/跳转至login
Admin页面
- 是否本地存在credentials(是否属于已登录状态) => Next/跳转至login
- 本地credentials是否显示用户为管理员类型 => 进入Admin页面/跳转至404页面
前端向后端请求验证(进入页面后)-- http拦截器
请求发送处理
每个heep请求在请求头带上本地credentials中的token
请求响应处理
- 返回401状态码 => 删除本地credentials(如果有),跳转至login
- 否则,不做特殊处理
后端登录与鉴权
登录逻辑
- 后端接收到前端发送的用户信息
- 将前端发送的用户信息(密码需在后端做hash处理)与数据库用户信息比对
- 若匹配,Next。若不匹配,返回incorrect/权限到期
- 缓存是否存在用户登录code(若不存在则生成随机code并存入缓存)
- 签入token,将用户信息(id,type等)、code写入token的payload,并设定token有效期
- 返回用户信息及token至前端
用户身份一般鉴定
- token解码失败:包括无token、token过期、token的payload不包含需要的信息 => 返回401
- token解码 => 得到用户信息(包括id、code等) => 对比code与缓存code是否一致 => Next/返回401
- 根据token得到的用户信息判断是否为管理员 => 鉴定成功/Next
- 非管理员检测用户是否已被删除(用户删除只更改数据库状态而非数据库删除) => 返回401/鉴定成功
创建用户鉴权
- 创建的是系统第一个用户
后端接收到前端发送的创建的用户信息 => 请求头是否没有携带token或是否创建的用户类型为管理员 => Next/返回401
判断是否为首次使用系统 => 创建用户/返回401
-
创建的不是系统第一个用户
- 后端接收到前端发送的创建的用户信息 => 请求头携带token => 判断token本身是否过期 =>返回401/Next
- 解码token => 解码后拿到用户信息 => 用户是否为管理员且与缓存token比对 => Next/返回401
- 创建用户 => 创建用户是否成功 => 返回success/Next
- 是否已存在同名用户 => 返回已存在同名用户提示/返回fail
修改用户信息鉴权
- 用户身份一般鉴定
- 若鉴定用户为管理员,鉴权成功;否则,Next
- 鉴定需要修改的用户信息是否为用户自己 => Next/返回401
- 鉴定旧密码是否正确 => 鉴权成功/返回旧密码incorrect
删除用户鉴权
- 用户身份一般鉴定
- 鉴定用户为管理员 => 鉴权成功/Next
Tips
- 修改用户密码/删除用户成功后,删除对应用户的缓存里的登录code
- why not cookie => 无状态、防xss攻击、api多端共用
- 如何跨域共享用户登录状态
- 已经使用了jwt,为何还需loggedin-code => tips1即为原因
- 包含第三方登录的登录模块设计(OAuth协议)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。