You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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();
    }
  }
}

全局中间件验证(推荐)

通过中间件统一处理所有接口的认证,避免重复代码:

  1. 编写认证中间件:
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;
    }
  }
}
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 10:12:13