本文信息
- 本文建立于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
判断是否为首次使用系统 => 建立用户/返回401api
-
建立的不是系统第一个用户跨域
- 后端接收到前端发送的建立的用户信息 => 请求头携带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协议)