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

如何在C# Asp.Net服务中实现WebSocket连接的身份认证?

WebSocket 身份认证方案

仅靠 AllowedOrigins 限制完全无法抵御未授权访问,因为 Origin 请求头可被任意伪造,必须在握手阶段做身份校验才能保证仅合法用户可建立连接。由于浏览器原生 WebSocket API 不支持自定义请求头,主流方案是通过查询参数携带认证令牌实现校验,具体实现如下:

1. 前端请求改造

用户登录后拿到的认证令牌(如JWT)携带在WebSocket连接地址的查询参数中,注意要对令牌做URL编码避免特殊字符报错:

const authToken = localStorage.getItem('user_auth_token');
// 令牌需要做URL编码处理
const ws = new WebSocket(`wss://your-service-domain/ws?token=${encodeURIComponent(authToken)}`);

2. 服务端配置JWT支持查询参数取令牌

修改ASP.NET Core的JWT认证配置,新增规则:当请求路径为WebSocket端点时,从查询参数中读取令牌做校验:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.Events = new JwtBearerEvents
        {
            OnMessageReceived = context =>
            {
                var accessToken = context.Request.Query["token"];
                var requestPath = context.HttpContext.Request.Path;
                // 仅对WebSocket端点从查询参数取令牌
                if (!string.IsNullOrEmpty(accessToken) && requestPath.StartsWithSegments("/ws"))
                {
                    context.Token = accessToken;
                }
                return Task.CompletedTask;
            }
        };
        // 以下为你原有JWT校验配置,保持不变即可
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
        };
    });

3. 调整中间件顺序并添加握手校验

注意身份认证中间件必须放在WebSocket中间件之前,确保握手前完成身份校验:

// 顺序不能错:先认证、再授权、最后启用WebSocket
app.UseAuthentication();
app.UseAuthorization();

// 你原有的WebSocket配置保留
var webSocketOptions = new WebSocketOptions()
{
    KeepAliveInterval = TimeSpan.FromSeconds(120),
};
webSocketOptions.AllowedOrigins.Add("https://example.com");
webSocketOptions.AllowedOrigins.Add("https://www.example.com");
app.UseWebSockets(webSocketOptions);

// WebSocket端点处理逻辑新增身份校验
app.Map("/ws", async context =>
{
    // 未通过认证直接返回401拒绝连接
    if (!context.User.Identity.IsAuthenticated)
    {
        context.Response.StatusCode = StatusCodes.Status401Unauthorized;
        return;
    }
    // 可按需添加额外权限校验,比如校验用户角色、权限
    if (!context.User.IsInRole("valid_user"))
    {
        context.Response.StatusCode = StatusCodes.Status403Forbidden;
        return;
    }
    // 校验通过才接受WebSocket连接
    using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
    // 后续保持原有消息收发逻辑即可
});

安全优化建议

  • 必须使用 wss 加密协议传输,避免明文传输导致令牌被截获
  • 认证令牌设置较短的过期时间,降低泄露后的风险
  • 高安全级别的场景可使用一次性临时Ticket方案:前端先请求普通HTTP接口获取有效期1~2分钟的一次性Ticket,再携带Ticket建立WebSocket连接,服务端校验Ticket有效性后立即销毁,避免令牌复用风险
  • Origin限制可保留作为基础防护层,无需删除

内容的提问来源于stack exchange,提问作者Thomas Carlton

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 19:06:02