我正在尝试在标头中传递承载令牌以授权客户端连接。 SignalR集线器通过从标头中获取承载令牌来授权客户端。我无法修改SingalR集线器代码以使用查询字符串来获取令牌,也不能使用内置的JWT令牌功能。
如何向SignalR Typescript客户端添加自定义标头?
我唯一想做的就是重写HttpClient以添加标头,但是我不确定这是否可行或如何执行。
我正在Angular 8中使用@ microsoft / signalr和最新的@ microsoft / signalr软件包。
答案 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调用。
答案 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()
如果你愿意。