背景:
我有一个ASP.NET WebAPI项目 . 我正在使用Bearer Tokens来验证我的用户 . 我的一些控制器操作标有 [Authorized]
过滤器 . 在客户端,客户端通过调用 http://foo.bar/Token
获取其令牌,然后将该令牌作为 Authorization
标头添加到其请求中 .
到目前为止没有问题,我的 Startup.Auth.cs
类中的所有设置都应该正常工作:
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
现在我已经为我的项目添加了一些SignalR集线器,我也想验证集线器中的用户 . 还有一些其他问题涉及客户端如何向SignalR连接添加承载令牌 . 摘要:
-
一种方式是adding it as an ajax default header,由于the JS WebSocket API does not make it possible to set custom headers.这一事实而气馁 . 所以你回退到使用"Long Polling" . (不是我想要的)
-
另一种方式是creating a custom OAuth Provider and passing the token as query string . 这种方法也是不鼓励的,因为it can become a security issue . 但是我想要长轮询 .
我试过的:
所以我创建了这个类来从查询字符串中检索我的访问令牌 .
public class QueryStringOAuthBearerProvider : OAuthBearerAuthenticationProvider
{
public override Task RequestToken(OAuthRequestTokenContext context)
{
var value = context.Request.Query.Get("access_token");
if (!string.IsNullOrEmpty(value))
{
context.Token = value;
}
return Task.FromResult<object>(null);
}
}
然后在客户端,我这样做是为了传递我的访问令牌:
var connection = $.hubConnection();
var hub = connection.createHubProxy('fooHub');
connection.qs = { 'access_token': myAccessToken};
// Init connection
这是一个想法,但是当我想在 Startup.Auth.cs
类中注册我的 QueryStringOAuthBearerProvider
时会出现问题 .
以下是我更改Startup.Auth.cs类的方法:
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
// Enable the application to retrieve tokens from query string to authenticate users
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
{
Provider = new QueryStringOAuthBearerProvider()
});
所以我想我现在可以使用:
-
默认承载令牌,它位于我的WebAPI调用请求的标头中 .
-
我的SignalR Hub的查询字符串中的自定义访问令牌 .
结果:
当我连接到我的集线器时,我可以从查询字符串中检索访问令牌,并对用户进行身份验证 . 但是当我尝试调用WebAPI控制器操作时,我得到 System.InvalidOperationException
说 Sequence contains more than one element
. 我认为's because I' m注册了两种通过承载令牌验证我的用户的方法,OWIN不喜欢这样 .
问题:
我怎样才能有两种方法来获得持票人令牌?
- WebApi调用的默认行为(授权标头)
SignalR Hub的 QueryStringOAuthBearerProvider
(查询字符串) .
请注意,我不想将访问令牌作为查询字符串传递给我的WebApi操作,而只是传递给SignalR Hub .
2 回答
在盲目地寻找答案的同时,我遇到了一个类似于我的问题的 post ,在评论中有人说 mahmoud 说:
它适用于我的情况,现在我可以使用这两种方法获得持票人令牌 . 这是我修改过的
Startup.Auth.cs
类:我使用了逻辑,但在QueryStringOAuthBearerProvider类中做了一些更新,然后我得到了正确的结果..