jwt实现注册与登陆系统

前言

自己用react+koa实现了一个包含登陆和注册功能的网址,在这里记录一下实现过程
项目地址:github地址
预览地址:预览地址


注册

注册其实没什么好说的,就是要注意不要明文保存密码,否则数据库泄露后,密码会被其他人用来撞库使用。
前台加密主要是为了防止post请求明文传递密码,本来我想在前端加密,然后数据库直接保存加密的密码到数据库,登陆时传递加密后的密码进行登陆,但是前端使用的加密工具加密同一个密码每次都生成不同的结果,导致每次查询都是密码不正确,我只能在后端先解密前端密码,然后换用了一个加密工具,加密同一个密码生成相同的结果,这样查询密码才会正确。



登陆

传统的登录系统是通过cookiesession做的登录,这种登录需要后端记录session,当在线用户很多时,会增加服务器压力,这里我使用JSON Web Token (JWT)更好的方式来做登录(后端不需要记录任何东西)。关于cookie、session、token的概念我简单的总结过,具体可以参考这里

简述登录流程:

  1. 用户使用账号密码登录
  2. 后台验证账号密码是否正确,正确则生成token并发送给前台。
  3. 前台存储token并在下次访问传递给后台
  4. 后台验证前台传过来的token是否正确,不正确则返回错误给前台,让他重新登录

实际上我们需要解决以下问题就可以实现一个登陆:

  1. 后台如何生成token?
  2. 前台如何保存token,并传递给后台?
  3. 既然后台不保存任何信息,后台如何验证token?如何知道token不是伪造的

举个简单的例子:
我有个箱子要送出去,我自己不记录我送了哪些箱子,别人送回来的时候我怎么知道这是我的箱子?
很简单,我给箱子上把锁,别人还回来的时候,我用我自己的钥匙打开,能打开就是我的箱子,否则就不是。
生成token时,我们可以将用户名通过某种加密算法加密生成一个串字符串,解密时再用加密算法还原,如果可以还原就证明这个token有效,否则无效。

jsonwebtoken

我自己使用jsonwebtoken来生成和解析token,下面是一个简单的使用

const jwt = require('jsonwebtoken');

const secert = 'secert_key'                   //相当于钥匙,这个钥匙不要让其他人知道,否则别人会拿这个生成有效token

//加密,根据secert加密生成token
const token = jwt.sign({username:'zzh'},secert)   
console.log('token',token)

//解密,如果token正确会还原,否则会抛出错误
try {
    const result = jwt.verify(token,secert)     
    console.log(result)
} catch (error) {
    console.log(error)
}

上面就是一个加密和解密的过程,这就实现token的验证。我们在登录正确时,将用户名或id用上面的方法加密生成token,并返回给前台,前台用某种方式存储(SessionStorage、LocalStorage),然后前端可以放在请求头中传递给后台,后台再验证token是否正确。

koa-jwt

直接使用上面的jsonwebtoken太麻烦了,我们需要自己对接口进行token验证和验证失败的处理。可以使用koa-jwt中间件来帮我们完成这些功能,我只需要会用即可。

//app.js
...
var jwt = require('koa-jwt');

app.use(jwt({ secret: 'secert_key' }).unless({ path: [/^\/public/] }));

当我们使用koa-jwt中间件后,app会自动去验证token,当token不存在或token失效时,会抛出401错误。另外我们要注意几点:

  • 生成token时还是用的jsonwebtoken进行加密的(koa-jwt自带jsonwebtoken依赖)
  • 加密和解密的secret必须一样(不要泄露)
  • koa-jwt默认是从请求头的Authorization中寻找token,如果需要以其他方式传递token则自行根据官网设置。Authorization:'Bearer ’ + token
  • 要设置不需要验证token的接口,比如登陆接口是不需要验证token的(通过unless设置)

关于koa-jwt的使用可以看github文档或这个demo

下面几个问题可以思考
token存在前端什么位置合适?
可以存在SessionStorage、LocalStorage、cookie中。

前端根据什么判断是否登录?
当登陆成功时存储token到cookie中,然后判断cookie中是否有token

如何防止token被盗,然后绕过登陆的问题?
这样有个问题,我可以通过浏览器的调试工具拿到token,然后在其他地方不登录,在浏览器的调试工具手动设置token到cookie或storage中去,这样就绕过了登录。这其实是jwt的一个弊端,只要是一个正确的token,服务器都认为是有效的。解决的方法可以用https或者将token有效时间缩短。

cookie的httpOnly只能防止前端读取cookie,但是不能限制前端设置cookie

如何在退出登录时使token失效?
可以将用过的token加入黑名单,这样不管是退出登录还是窃取别人的token使用都不会登录成功

如何防止同个账号同时登录?

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值