jwt身份认证

132 阅读3分钟

博学谷it学习技术支持

jwt是什么

JWT(JSON Web Token),本质就是一个字符串书写规范,如下图,作用是用来在用户和服务器之间传递安全可靠的信息。
主要用在前后端分离的项目中(还有服务器渲染的项目类型嘛),服务器当验证用户账号和密码正确的时候,给用户颁发一个令牌,这个令牌作为后续用户访问一些接口的凭证,后续访问会根据这个令牌判断用户时候有权限进行访问

主要组成

jwt分为三个部分:头部(Header)、载荷(Payload)、签名(Signature),并以.进行拼接。其中头部和载荷都是以JSON格式存放数据,只是进行了编码。\

头部(Header)

“typ”: “JWT”, 
“alg”: “HS256” 
} 

有效载荷(Playload)

	"role": [],
	"iss": "baidu",
	"exp": 1638841050,
	"userName": "管理员",
	"department": [],
	"iat": 1638840690,
	"userId": "1",
	"account": "admin"
}

签名(Signature)

将Header和Playload拼接生成一个字符串str=“eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjpbXSwiaXNzI”, 使用HS256算法和我们提供的密钥(secret,服务器自己提供的一个字符串)对str进行加密生成最终的JWT, 即我们需要的令牌(token),形如:str.”签名字符串”。

认证流程

  1. 用户使用账号和密码发出post请求;
  2. 服务器使用私钥创建一个jwt;
  3. 服务器返回这个jwt给浏览器;
  4. 浏览器将该jwt串在请求头中像服务器发送请求;
  5. 服务器验证该jwt;
  6. 返回响应的资源给浏览器。

JWT 特点

  • 体积小,因而传输速度快
  • 传输方式多样,可以通过URL/POST参数/HTTP头部等方式传输
  • 严格的结构化。它自身(在 payload 中)就包含了所有与用户相关的验证消息,如用户可访问路由、访问有效期等信息,服务器无需再去连接数据库验证信息的有效性,并且 payload 支持为你的应用而定制化。
  • 支持跨域验证,可以应用于单点登录

在express中简单使用

const bodyParser = require("body-parser")
const jwt = require("./utils/jwt-simple")
// 这里由于简单实现,所以使用一个数组简单存取一下用户
const USER = [];
// JWT签名的密钥,这个是可以自定义的
const SECRET = "ChenSir#$_!"
let app = express();
app.use(bodyParser.json())
// 定义一个注册的接口, 大家不用深究具体的逻辑
app.post('/reg', function(req, res, next){
    let user = req.body;
    USER.push(user)
    res.json({
        code: 0,
        msg: "ok"
    })
})
// 定义登录接口
app.post("/login", function(req, res, next) {
    let user = req.body;
    let id = USER.findIndex(item => {
        return item.username == user.username && item.password == user.password;
    });
    if(id != -1){
    	// 校验成功后使用jwt.encode()进行token获取, 需要传入payload和secret
        let token = jwt.encode({
            id,
            username: user.username
        }, SECRET)
        res.json({
            token
        })
    }else{
        res.json({
            code: -1,
            msg: "上传信息有误"
        })
    }
})
// 获取信息接口,添加中间件进行权限校验
app.get("/info", function (req, res, next){
    let authorization = req.headers["authorization"];
    if(authorization){
        let token = authorization.split(" ")[1];
        try {
        	// 对token信息进行解码校验,使用jwt.decode()处理token解析出用户信息
            let user = jwt.decode(token, SECRET)
            req.user = user;
            next();  // 成功取到用户
        }catch(e){
            res.status(401).send("Not Allowed");
        }
    }else{
        res.status(401).send("Not Allowed");
    }
}, function (req, res, next){
    res.json(req.user)
})

app.listen(8080, function(){
    console.log("server listening on 8080")
})

优缺点

优点:

json具有通用性,所以可以跨语言 组成简单,字节占用小,便于传输 服务端无需保存会话信息,很容易进行水平扩展 一处生成,多处使用,可以在分布式系统中,解决单点登录问题 可防护CSRF攻击

缺点:

payload部分仅仅是进行简单编码,所以只能用于存储逻辑必需的非敏感信息 需要保护好加密密钥,一旦泄露后果不堪设想 为避免token被劫持,最好使用https协议