本文详细介绍了JWT开发的全过程,从JWT的基本概念和工作原理到开发环境的搭建和令牌的生成与验证,涵盖了JWT在实际项目中的应用及常见问题解答。JWT开发涉及生成、传输和验证令牌,确保安全性是关键。
JSON Web Token (JWT) 是一种开放标准 (RFC 7519),用于创建、传输和验证基于JSON的令牌。这些令牌通常用于在Web应用程序之间传递声明或信息。JWT通常用于实现用户身份验证和授权功能。
JWT的工作原理如下:
Authorization
字段中。JWT由三个部分组成:头部(Header)、有效载荷(Payload)和签名(Signature)。
头部(Header):包含令牌的类型(例如JWT)和所用的加密算法(例如HMAC SHA256或RSA)。示例代码如下:
{ "alg": "HS256", "typ": "JWT" }
有效载荷(Payload):包含有关用户或请求的声明。标准声明如sub
(主体)、iat
(签发时间)等可包含在内,自定义声明也可以根据需要进行设置。
开发JWT应用程序之前,确保安装了以下工具:
设置开发环境的具体步骤如下:
# 安装Node.js sudo apt-get install nodejs sudo apt-get install npm
mkdir my-jwt-project cd my-jwt-project npm init -y
npm install jsonwebtoken
npm install express
示例代码如下:
const jwt = require('jsonwebtoken'); const payload = { sub: '1234567890', name: 'John Doe', iat: Date.now() }; const secret = 'shhhhh'; const token = jwt.sign(payload, secret); console.log(token);
有效载荷包含有关用户或请求的详细信息。以下是一个示例,包括标准声明和自定义声明:
const payload = { sub: '1234567890', name: 'John Doe', iat: Date.now(), customClaim: 'This is a custom claim' };
使用jsonwebtoken
库可以对JWT令牌进行加密:
const jwt = require('jsonwebtoken'); const payload = { sub: '1234567890', name: 'John Doe', iat: Date.now() }; const secret = 'shhhhh'; const token = jwt.sign(payload, secret, { algorithm: 'HS256' }); console.log(token);
在验证JWT令牌之前,需要从客户端接收到令牌并进行解析:
const jwt = require('jsonwebtoken'); const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxhPB2322wwjK47h5l5FZ8eQZ31oWdGnQjwGmF'; const secret = 'shhhhh'; try { const decoded = jwt.verify(token, secret); console.log(decoded); } catch (error) { console.error('JWT验证失败:', error); }
使用jwt.verify
函数验证令牌的有效性并检查签名是否正确:
const jwt = require('jsonwebtoken'); const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxhPB2322wwjK47h5l5FZ8eQZ31oWdGnQjwGmF'; const secret = 'shhhhh'; try { const decoded = jwt.verify(token, secret, { algorithms: ['HS256'] }); console.log('JWT验证成功', decoded); } catch (error) { console.error('JWT验证失败:', error); }
如果令牌已过期或无效,jwt.verify
将抛出错误。可以捕获该错误并进行适当的处理:
const jwt = require('jsonwebtoken'); const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyMzkwMjJ9.SflKxhPB2322wwjK47h5l5FZ8eQZ31oWdGnQjwGmF'; const secret = 'shhhhh'; try { const decoded = jwt.verify(token, secret, { algorithms: ['HS256'] }); console.log('JWT验证成功', decoded); } catch (error) { console.error('JWT验证失败:', error); }
JWT可以用于创建安全的用户身份验证机制。下面是一个简单的用户认证示例:
const jwt = require('jsonwebtoken'); const express = require('express'); const app = express(); app.post('/login', (req, res) => { const user = { id: 1, name: 'John Doe' }; const token = jwt.sign({ id: user.id, name: user.name }, 'shhhhh', { expiresIn: '1h' }); res.json({ token }); }); app.use((req, res, next) => { const token = req.headers['authorization']; if (!token) { return res.status(403).json({ message: 'No token provided.' }); } jwt.verify(token, 'shhhhh', (err, decoded) => { if (err) { return res.status(500).json({ message: 'Failed to authenticate token.' }); } req.userId = decoded.id; next(); }); }); app.get('/protected', (req, res) => { res.json({ message: 'This is protected content.' }); }); app.listen(3000, () => { console.log('Server is running on port 3000'); });
JWT不仅用于身份验证,还可以实现基于角色的访问控制。下面是一个简单的权限控制示例:
const jwt = require('jsonwebtoken'); const express = require('express'); const app = express(); app.post('/login', (req, res) => { const user = { id: 1, name: 'John Doe', role: 'admin' }; const token = jwt.sign({ id: user.id, name: user.name, role: user.role }, 'shhhhh', { expiresIn: '1h' }); res.json({ token }); }); app.use((req, res, next) => { const token = req.headers['authorization']; if (!token) { return res.status(403).json({ message: 'No token provided.' }); } jwt.verify(token, 'shhhhh', (err, decoded) => { if (err) { return res.status(500).json({ message: 'Failed to authenticate token.' }); } req.user = decoded; next(); }); }); app.get('/admin', (req, res) => { if (req.user.role !== 'admin') { return res.status(403).json({ message: 'Access denied.' }); } res.json({ message: 'This is admin content.' }); }); app.get('/user', (req, res) => { res.json({ message: 'This is user content.' }); }); app.listen(3000, () => { console.log('Server is running on port 3000'); });
完整的示例代码和项目部署可以参考以下步骤:
mkdir jwt-project cd jwt-project mkdir server cd server touch app.js cd .. touch package.json npm init -y npm install express jsonwebtoken cors
编辑app.js:
const express = require('express'); const jwt = require('jsonwebtoken'); const app = express(); const PORT = 3000; app.post('/login', (req, res) => { const user = { id: 1, name: 'John Doe', role: 'admin' }; const token = jwt.sign({ id: user.id, name: user.name, role: user.role }, 'shhhh', { expiresIn: '1h' }); res.json({ token }); }); app.use((req, res, next) => { const token = req.headers['authorization']; if (!token) { return res.status(403).json({ message: 'No token provided.' }); } jwt.verify(token, 'shhhh', (err, decoded) => { if (err) { return res.status(500).json({ message: 'Failed to authenticate token.' }); } req.user = decoded; next(); }); }); app.get('/admin', (req, res) => { if (req.user.role !== 'admin') { return res.status(403).json({ message: 'Access denied.' }); } res.json({ message: 'This is admin content.' }); }); app.get('/user', (req, res) => { res.json({ message: 'This is user content.' }); }); app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); });
node server/app.js
localStorage
或sessionStorage
存储令牌,但更安全的方法是使用HTTP-only
cookies来存储令牌。AsyncStorage
中(React Native),或使用SharedPreferences
(Android)或UserDefaults
(iOS)。localStorage
、sessionStorage
或HTTP-only
cookies中。通过以上步骤和示例,你已经掌握了如何在项目中使用JWT进行用户身份验证和权限控制。希望本文能帮助你更好地理解和应用JWT技术。