如何用Serverpod实现自定义JWT认证?请求头Token为空问题解决
Serverpod自定义JWT认证正确实现方案
先排查核心问题:请求头格式与CORS配置
- 确保客户端请求头格式正确:
Authorization头的值必须是Bearer <你的JWT Token>,不能只传Token字符串。比如Dio请求示例:dio.options.headers['Authorization'] = 'Bearer $jwtToken'; - 检查跨域配置:如果是前端跨域请求,需在Serverpod的
config/general.yaml中添加authorization到允许的请求头列表:cors: allowedOrigins: - http://localhost:8080 # 你的前端域名 allowedHeaders: - content-type - authorization
服务端获取Token的正确方式
单个接口内获取验证
在Endpoint方法中,通过session.context.request.headers提取Token,注意用标准HTTP头常量避免大小写问题:
import 'dart:io'; import 'package:serverpod/serverpod.dart'; class ExampleEndpoint extends Endpoint { Future<String> getProtectedData(Session session) async { // 提取Authorization头 String? authHeader = session.context.request.headers[HttpHeaders.authorizationHeader]; String? token; if (authHeader != null && authHeader.startsWith('Bearer ')) { token = authHeader.substring(7); // 去掉"Bearer "前缀 } if (token == null) { throw UnauthorizedException(); } // 验证Token并解析 payload try { var payload = Jwt.verify(token, Config.current.jwt.secret); int userId = payload['userId'] as int; // 后续业务逻辑... return 'Protected data for user $userId'; } catch (e) { throw UnauthorizedException(); } } }
全局中间件验证(推荐)
通过中间件统一处理所有接口的认证,避免重复代码:
- 编写认证中间件:
import 'dart:io'; import 'package:serverpod/serverpod.dart'; class AuthMiddleware extends Middleware { @override Future<void> handle(Session session, NextMiddlewareCallback next) async { String? authHeader = session.context.request.headers[HttpHeaders.authorizationHeader]; String? token; if (authHeader != null && authHeader.startsWith('Bearer ')) { token = authHeader.substring(7); } if (token == null) { session.response.statusCode = HttpStatus.unauthorized; return; } try { // 验证Token并将用户ID存入session var payload = Jwt.verify(token, Config.current.jwt.secret); session.auth.setUserId(payload['userId'] as int); await next(); // 继续执行后续接口逻辑 } catch (e) { session.response.statusCode = HttpStatus.unauthorized; return; } } }
- 在
server.dart中注册中间件:
import 'package:serverpod/serverpod.dart'; import 'src/generated/protocol.dart'; import 'src/generated/endpoints.dart'; import 'src/middleware/auth_middleware.dart'; void run(List<String> args) async { final pod = Serverpod( args, Protocol(), Endpoints(), middleware: [AuthMiddleware()], // 注册认证中间件 ); await pod.start(); }
关键注意事项
- 确保JWT密钥配置正确:在
config/general.yaml中设置jwt.secret,签名和验证必须使用同一密钥。 - 测试请求头是否真的发送:用Postman或浏览器开发者工具查看请求的Network面板,确认
Authorization头存在且格式正确。 - 避免大小写错误:使用
HttpHeaders.authorizationHeader常量获取请求头,而非手动写字符串,防止大小写不匹配导致的空值。
内容的提问来源于stack exchange,提问作者Siddhant Chauhan
相关产品推荐
相关产品推荐

