如何将自定义标头添加到SignalR的Typescript客户端?

时间:2020-01-08 18:58:09

标签: c# angular typescript signalr

我正在尝试在标头中传递承载令牌以授权客户端连接。 SignalR集线器通过从标头中获取承载令牌来授权客户端。我无法修改SingalR集线器代码以使用查询字符串来获取令牌,也不能使用内置的JWT令牌功能。

如何向SignalR Typescript客户端添加自定义标头?

我唯一想做的就是重写HttpClient以添加标头,但是我不确定这是否可行或如何执行。

我正在Angular 8中使用@ microsoft / signalr和最新的@ microsoft / signalr软件包。

4 个答案:

答案 0 :(得分:4)

建立连接时,可以在选项中添加自定义HttpClient。

它看起来像这样:

class CustomHttpClient extends HttpClient {
  public send(request: HttpRequest): Promise<HttpResponse> {
    request.headers = { ...request.headers, "customHeader": "value" };
    // ... http call
  }
}

let hubConnection = new HubConnectionBuilder()
    .withUrl(url, { httpClient: new CustomHttpClient() })
    .build();

可能可以从DefaultHttpClient继承,并在您的发送中调用DefaultHttpClient的send,因此您无需自己实现Http调用。

https://github.com/dotnet/aspnetcore/issues/14588正在跟踪一流的支持。

答案 1 :(得分:2)

如果这只是传递承载令牌,则无需做自定义标头,传递访问令牌,您可以使用带有IHttpConnectionOptions的withUrl重载,该接口具有accessTokenFactory,可以这样使用:

<input type="button" value="Report" onclick="window.open('@Url.Action("GetPdf", "PrintList", new { listId = Url.RequestContext.RouteData.Values["id"], ddlAbb = [selectedValue]})')" />

不要忘记在中心服务器中启用cors策略,以允许JS客户端起源

答案 2 :(得分:2)

我需要的东西与@Brennan的答案完全一样。

我只是填补了一些空白,这些空白需要更多副本和更贴切的答案。我正在使用它,它可以工作,谢谢@Brennan

import * as signalR from "@aspnet/signalr";

// You can create a factory which signalR will used to generate an access token on each request
const getBearerToken = () => "MY TOKEN GETTING FUNCTION"

// This is a custom method which creates all the headers I need for my authentication
const getAuthHeaders = () => ({ collection: "", of: "", headers:""})

// As per @Brennan's answer I used his advice and extened the default one
class CustomHttpClient extends signalR.DefaultHttpClient {
  constructor() {
    super(console); // the base class wants an signalR.ILogger, I'm not sure if you're supposed to put *the console* into it, but I did and it seemed to work
  }

  // So far I have only overriden this method, and all seems to work well
  public async send(request: signalR.HttpRequest): Promise<signalR.HttpResponse> {
    var authHeaders = getAuthHeaders(); // These are the extra headers I needed to put in
    request.headers = { ...request.headers, ...authHeaders };
    // Now we have manipulated the request how we want we can just call the base class method
    return super.send(request);
  }
}

 let connection = new signalR.HubConnectionBuilder()
    .withUrl(`${apiUrl}/web-sockets/stripeHub`, {
        accessTokenFactory: getBearerToken, // I also needed this, but you may not need it
        httpClient: new CustomHttpClient(), // This is the CustomClient we defined above which adds the headers to each request going out
     }) 
    .build();

答案 3 :(得分:0)

在创建集线器连接构建器时有一个名为 headers 的选项。并且此选项仅在您使用 @microsoft/signalr npm 包时可用。这是 signalr 的活动存储库,旧的 (@aspnet/signalr) 已存档。

所以使用新的 npm 包,你可以像下面这样

let connection = new signalR.HubConnectionBuilder()
.withUrl("/chat", { 
 headers: { 
   "custom-header-name": "value" 
 },
 withCredentials: (true/false) // if you dont mention this value (if undefined by default it will set to true (which i didnt wanted in my case)
})
.build();

注意:请记住,默认情况下自动重新连接为 false,因此添加 withUrl().withAutomaticReconnect() 如果你愿意。

更多关于options interface