鉴权、加密、HTTPS概念
登录鉴权流程
鉴权
- 基础鉴权
- session/cookie
- JWT
- Oauth等
算法加密
算法中的指令描述的是一个计算,当其运行时能从一个初始状态和初始输入(可能为空)开始,经过一系系列有限而清晰定义的状态最终产生输出并停止于一个终态。
数据加密的基本过程,就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码,通常称为“密文”。通过这样的途径,来达到保护数据不被非法人窃取、阅读的目的。
- Base64
- MD5
- SHA-1
- DES
- AES
- RSA
- ECC等
HTTPS
HTTPS
(HyperText Transfer Protocol Secure
)
本传输安全协议,常称为HTTP over TLS、HTTP over
SSL
或HTTP Secure
)是一种通过计算机网络进行安全通
信的传输协议。
- SSL
- HTTP劫持
- 数据篡改
- 敏感信息
- 中间人等
常见的鉴权方式及优缺点
Session/cookie
- 优点
- 较易拓展,简单
- 缺点
- 安全性低
- 性能低,服务端储存
- 多服务同步session困难
- 跨平台困难
JWT
- 优点
- 易扩展
- 支持移动设备
- 跨应用调用
- 安全
- 承载信息丰富
- 缺点
- 刷新与过期处理
- Payload不易过大
- 中间人攻击
Oauth
-
优点
- 开放
- 安全(QQ微信扫码等)
- 简单
- 权限指定(登录第三方,授权界面)
-
缺点
- 需要增加授权服务器
- 增加网络请求
使用JWT方式开发登录鉴权模块
登录流程
集成JWT
- 安装
npm i -S koa-jwt
-
使用
- 登录接口接口实现,在密码验证码通过时使用JWT生成token返回给前端
-
登录接口
import jsonwebtoken from 'jsonwebtoken'
async login (ctx) {
// 验证用户账户密码是否正确
// 返回token
// 1.接受用户数据
const {body} = ctx.request
const {sid, code, username, password} = body
console.log(sid, code, username)
// 2.验证图片验证码的时效性、正确性
if (checkCode(sid, code)) {
// 3.验证用户账户密码是否正确
let checkUserPassword = false
// mongoDB查库
const user = await UserModel.findOne({username: username})
console.log(user)
// bcrypt保存密码的时候用的是这个加密的,比较也需要用bcrypt
if (user.username === username && await bcrypt.compare(password, user.password)) {
checkUserPassword = true
}
if (checkUserPassword) {
// 4.验证通过返回token
const token = jsonwebtoken.sign({id: 'zhangsan'}, config.JWT_SECRET, {
expiresIn: '1d'
})
ctx.body = {
token,
code: 200,
msg: '登录成功'
}
} else {
// 用户 密码验证失败,返回提示
ctx.body = {
code: 404,
msg: '用户名或密码错误'
}
}
} else {
ctx.body = {
code: 401,
msg: '图片验证码不正确'
}
}
}
- 注册接口
async reg (ctx) {
// 1.接受客户端的数据
const { body } = ctx.request
const {code, username, password, name, sid } = body
console.log('code, username, password, name, sid', code, username, password, name, sid)
// 2.校验验证码的内容(时效性、有效性)
if (checkCode(sid, code)) {
// 3.查库,看username是否被注册
let check = true
const userDB_username = await UserModel.findOne({username: username})
console.log('userDB_username', userDB_username)
if (userDB_username && typeof userDB_username.username !== 'undefined') {
check = false
ctx.body = {
code: 401,
msg: '该邮箱已注册,可以通过邮箱找回密码'
}
}
const userDB_name = await UserModel.findOne({name: name})
// 4.查库,看name是否被注册
if( userDB_username && typeof userDB_name.name !== 'undefined') {
check = false
ctx.body = {
code: 401,
msg: '该昵称已存在!'
}
}
// 5.写入数据到数据库
if (check) {
let pwd = await bcrypt.hash(password, 5)
let user = new UserModel({
username,
name,
password: pwd,
created: moment().format('YYYY-MM-DD HH:mm:ss')
})
let result = await user.save()
ctx.body = {
code: 200,
data: result,
msg: '注冊成功'
}
}
} else {
ctx.body = {
code: 401,
msg: '图片验证码不正确'
}
}
}
总结
- 前端sid唯一标识使用的是
uuid
- 验证码的时效使用的是
redis
- 密码保存加密使用的是
bcrypt