Windows内网环境下.NET Core SignalR的negotiate请求返回401错误
1. 配置IIS站点允许OPTIONS请求匿名访问
Windows身份验证场景下,CORS预检OPTIONS请求默认不带身份凭证,IIS会直接拦截请求返回401,这是代码配置一致但站点表现不同的核心原因,大概率是故障站点的IIS规则未放行OPTIONS请求。
在站点根目录的web.config中添加如下配置即可:
<configuration> <system.webServer> <security> <authentication> <anonymousAuthentication enabled="true" /> <windowsAuthentication enabled="true" /> </authentication> <authorization> <add accessType="Allow" verbs="OPTIONS" users="?" /> <add accessType="Deny" users="?" /> </authorization> </security> </system.webServer> </configuration>
如果通过IIS管理器操作,顺序为:找到目标站点→认证→同时开启匿名认证和Windows认证→进入授权规则→先添加允许匿名用户访问OPTIONS动词的规则,再添加拒绝匿名用户访问所有内容的规则,两条规则顺序不能调换。
2. 完善SignalR适配的JWT令牌提取逻辑
SignalR建立WebSocket连接时,令牌默认放在查询参数中,你当前的JWT配置没有适配该场景,需要在AddJwtBearer配置块中补充查询参数令牌提取逻辑:
options.Events = new JwtBearerEvents { OnMessageReceived = context => { var accessToken = context.Request.Query["access_token"]; var path = context.HttpContext.Request.Path; if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/ibjahub")) { context.Token = accessToken; } return Task.CompletedTask; } };
3. Angular端显式开启凭证携带
Windows身份验证场景下SignalR连接必须显式指定携带凭证,修改你的Angular连接代码:
const hubConnection = new signalR.HubConnectionBuilder() .withUrl(hd.hubURL, { withCredentials: true // 新增该行配置 }) .build();
4. 核对跨域来源配置
确认appsettings.json中apiAllowedOrigins的值完全匹配Angular前端的访问地址,包含协议(http/https)、域名、端口,末尾不能带斜杠,例如前端地址为http://localhost:4200就直接填写该值,不要写http://localhost:4200/。
5. 对比两个站点的IIS配置
直接比对正常站点和故障站点的IIS配置项:认证规则、授权规则、CORS配置、应用池.NET版本,重点检查故障站点是否存在URL重写规则拦截了SignalR的请求。
内容的提问来源于stack exchange,提问作者Grussles
相关产品推荐
相关产品推荐

