1. 引言
在进行 Web 开发时,我们通常需要进行用户验证来识别用户身份。为了保证用户的信息安全性,常用的做法是使用 Token(令牌)验证。
2. 什么是 Token?
Token(令牌)是一种由服务器生成的加密字符串,它被用来验证用户的身份和权限。在用户登录后,服务器会返回一个 Token,用户在后续请求中需要携带这个 Token,才能访问需要认证的资源。
2.1 Token 的类型
Token 可以分为两种类型:
无状态 Token:这种 Token 仅包含用户的身份信息,服务器不存储任何与 Token 相关的信息。
有状态 Token:这种 Token 包含了用户的身份信息以及与之相关的一些元数据,服务器可以根据 Token 的元数据判断用户是否合法。
2.2 Token 的生成方式
Token 的生成方式有很多种,最常用的是使用 JSON Web Token(JWT)。
JWT 是一种标准化的、基于 JSON 格式的令牌,在令牌中可以存储一些与用户相关的信息,并对令牌进行数字签名以防伪造。
// 一个 JWT 的例子
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9
lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
JWT 可以明文传输,因为其中包含了数字签名以保证它的真实性。
3. 如何获取 Token?
获取 Token 通常需要用户提供一些身份认证信息,比如用户名和密码,一般步骤如下:
用户向服务器发送登录请求,提供用户名和密码
服务器验证用户名和密码,如果验证通过,则生成一个 Token
服务器将 Token 返回给客户端,客户端在后续的请求中需要携带这个 Token
3.1 通过用户名和密码获取 Token
在 Web 应用中,通常需要实现一个登录页面,用户在该页面上输入用户名和密码,然后将其提交给服务器进行验证。
下面是一个使用 Node.js 和 Express 框架的例子:
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
// 登录接口
app.post('/login', (req, res) => {
const username = req.body.username;
const password = req.body.password;
// 验证用户名和密码是否正确
if (username !== 'admin' || password !== '123456') {
res.status(400).json({ message: '用户名或密码错误' });
return;
}
// 生成 Token
const token = jwt.sign({ username }, 'secret', { expiresIn: '1h' });
res.json({ token });
});
// 其他需要认证的接口
app.get('/api/hello', (req, res) => {
const token = req.headers.authorization.split(' ')[1];
try {
const decodedToken = jwt.verify(token, 'secret');
res.json({ message: `Hello ${decodedToken.username}` });
} catch (err) {
res.sendStatus(401);
}
});
app.listen(3000);
上面的例子中,当用户登录时,服务器通过 jwt.sign() 方法生成一个 Token,并将其返回给客户端。在后续的请求中,客户端需要在请求头中添加一个 Authorization 字段,其中包含了 Token。
服务器在接收到请求时,可以通过 jwt.verify() 方法对 Token 进行验证,如果验证通过,则说明当前用户已经登录,可以继续访问受保护的资源。
3.2 通过第三方登录获取 Token
除了通过用户名和密码获取 Token 之外,还可以使用第三方 OAuth2.0 协议(比如 Google、Facebook、GitHub 等)进行登录认证,获取 Token。
下面是一个使用 Passport.js、Google OAuth2.0 和 JWT 的例子:
const express = require('express');
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
const jwt = require('jsonwebtoken');
const app = express();
// 配置 Google OAuth2.0
passport.use(new GoogleStrategy({
clientID: 'your-client-id',
clientSecret: 'your-client-secret',
callbackURL: 'http://localhost:3000/auth/google/callback'
}, (accessToken, refreshToken, profile, done) => {
// 生成 Token
const token = jwt.sign({ sub: profile.id }, 'secret', { expiresIn: '1h' });
done(null, token);
}));
// 登录接口
app.get('/auth/google', passport.authenticate('google', { scope: ['profile'] }));
// 回调接口
app.get('/auth/google/callback', passport.authenticate('google', { session: false }), (req, res) => {
res.redirect(`/token/${req.user}`);
});
// Token 接口
app.get('/token/:token', (req, res) => {
const token = req.params.token;
// 对 Token 进行验证和解码
try {
const decodedToken = jwt.verify(token, 'secret');
res.json({ message: `Hello ${decodedToken.sub}` });
} catch (err) {
res.sendStatus(401);
}
});
app.listen(3000);
上面的例子中,当用户点击 Google 登录按钮时,服务器使用 passport.authenticate() 方法发起 Google OAuth2.0 认证流程。认证通过后,服务器通过 jwt.sign() 方法生成一个 Token,并将其重定向到 /token/:token 接口。
在 /token/:token 接口中,服务器需要对 Token 进行验证和解码,以确保 Token 是合法的,并从中提取出用户的信息。
4. 总结
Token 是一种用于验证用户身份和权限的机制。获取 Token 通常需要用户提供一些身份认证信息,比如用户名和密码,也可以使用第三方 OAuth2.0 协议进行登录认证。JWT 是一种常用的令牌格式,具有安全性高、易于使用等优点。