如何利用Laravel 8生成的令牌在Express.js中安全获取元素?
Laravel 8 与 Express.js 安全传递令牌并获取资源实现方案
Laravel 8 端操作:生成并发送令牌
1. 生成安全令牌
根据需求选择两种实现方式:
方式一:自定义签名加密令牌(轻量,适合内部服务)
利用Laravel内置加密工具生成不可篡改的令牌,包含资源标识和过期时间:
use Illuminate\Support\Facades\Crypt; // 构造令牌承载的数据(按需添加字段) $tokenPayload = [ 'user_id' => auth()->id(), 'target_resource_id' => 456, // 要获取的元素ID 'expires_at' => now()->addMinutes(30)->timestamp // 30分钟过期 ]; // 加密生成令牌 $token = Crypt::encryptString(json_encode($tokenPayload));
方式二:Laravel Passport 个人访问令牌(适合用户级授权)
先完成Laravel Passport的安装配置,再生成带权限的用户访问令牌:
// 已配置Passport的前提下 $user = auth()->user(); // 创建带指定权限的访问令牌 $token = $user->createToken('express-integration', ['view-resources'])->accessToken;
2. 向Express服务发送令牌
使用Laravel的Http门面发起HTTPS请求,将令牌放在Authorization请求头中(推荐):
use Illuminate\Support\Facades\Http; $expressApiUrl = 'https://your-express-domain/api/fetch-resource'; $response = Http::withHeaders([ 'Authorization' => "Bearer {$token}", 'Content-Type' => 'application/json' ])->post($expressApiUrl); // 处理Express返回的响应 if ($response->successful()) { $targetResource = $response->json(); // 后续业务逻辑 } else { $error = $response->json('error'); // 处理请求失败情况 }
Express.js 端操作:接收并验证令牌,返回资源
场景一:验证Laravel自定义加密令牌
- 安装依赖:需要
crypto-js解析Laravel的AES加密
npm install crypto-js
- 编写路由与验证逻辑:
const express = require('express'); const router = express.Router(); const CryptoJS = require('crypto-js'); // 从Laravel的.env中复制APP_KEY,注意去掉前缀`base64:` const LARAVEL_APP_KEY = 'your-laravel-app-key-without-base64-prefix'; router.post('/api/fetch-resource', (req, res) => { // 提取请求头中的令牌 const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ error: '无效的授权头' }); } const token = authHeader.split(' ')[1]; try { // 解析Laravel加密的IV(令牌前32位是IV的十六进制字符串) const iv = CryptoJS.enc.Hex.parse(token.substring(0, 32)); // 解密令牌主体 const decryptedData = CryptoJS.AES.decrypt( token.substring(32), CryptoJS.enc.Base64.parse(LARAVEL_APP_KEY), { mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7, iv: iv } ); const payload = JSON.parse(decryptedData.toString(CryptoJS.enc.Utf8)); // 验证令牌是否过期 if (Date.now() / 1000 > payload.expires_at) { return res.status(401).json({ error: '令牌已过期' }); } // 根据payload中的resource_id查询对应元素 const resource = fetchResourceById(payload.target_resource_id); // 替换为你的实际查询逻辑 res.json(resource); } catch (err) { return res.status(401).json({ error: '令牌无效' }); } }); // 示例资源查询函数 function fetchResourceById(id) { // 这里写从数据库/缓存获取资源的逻辑 return { id: id, title: '目标资源', content: '对应内容' }; } module.exports = router;
场景二:验证Laravel Passport JWT令牌
- 安装依赖:用
jsonwebtoken和jwks-rsa验证Passport的RSA签名令牌
npm install jsonwebtoken jwks-rsa
- 编写路由与验证逻辑:
const express = require('express'); const router = express.Router(); const jwt = require('jsonwebtoken'); const jwksClient = require('jwks-rsa'); // 配置Laravel Passport的公钥端点 const client = jwksClient({ jwksUri: 'https://your-laravel-domain/oauth/public-key' }); // 获取Passport的公钥用于验证签名 function getSigningKey(header, callback) { client.getSigningKey(header.kid, (err, key) => { const signingKey = key.getPublicKey(); callback(null, signingKey); }); } router.post('/api/fetch-resource', (req, res) => { const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ error: '未提供有效授权令牌' }); } const token = authHeader.split(' ')[1]; // 验证JWT令牌 jwt.verify(token, getSigningKey, { algorithms: ['RS256'] }, (err, decoded) => { if (err) { return res.status(401).json({ error: '令牌无效或已过期' }); } // decoded中包含用户信息,比如decoded.sub是Laravel用户ID,按需查询资源 const resource = fetchResourceByUserId(decoded.sub); // 替换为你的实际逻辑 res.json(resource); }); }); module.exports = router;
安全与效率优化要点
- 强制HTTPS:所有服务间通信必须用HTTPS,防止令牌被窃听或篡改
- 短过期时间:令牌过期时间设置在15-60分钟之间,降低泄露风险
- 权限校验:Express端验证令牌后,必须额外校验用户是否有权限访问目标资源
- 速率限制:给Express路由添加速率限制(如
express-rate-limit),防止恶意请求 - 日志监控:记录令牌验证失败的请求,便于排查授权问题
内容的提问来源于stack exchange,提问作者Alzubair Mhmoud
相关产品推荐
相关产品推荐

