【问题标题】:WebAPI & SignalR web application - Authenticating & AuthorizingWeb API 和 SignalR Web 应用程序 - 身份验证和授权
【发布时间】:2016-11-11 22:56:11
【问题描述】:

我有一个WebAPI 解决方案,我使用token authentication,所以流程如下:

  • 用户尝试使用usernamepassword 登录
  • 如果凭据正确,他将获得一个令牌,以便在以下请求中使用(放置在AJAX 请求的标头中)。

现在SignalR 开始发挥作用了。由于它使用WebSockets,因此您无法传递标头。 在寻找解决方案时,我遇到了以下问题:

  1. 实际上将标头传递给SignalR - 这不是一个选项,因为它强制SignalR 使用longPolling

$.signalR.ajaxDefaults.headers = { Authorization: "Bearer " + token };

  1. 将用于验证WebAPI 调用的token 传递为query string/或将其存储在SignalR 的cookie 中,然后创建一个提供程序,以某种方式将令牌解包并扩展为身份。 I followed this blog post 但我似乎遗漏了什么。

  2. 再次将令牌作为 query string/或 cookie 传递,但这次创建自定义 Authorize AttributeAuthorize SignalR 集线器或方法。 Again a blog post about this. 这个解决方案的问题在于令牌上的Unprotect 方法。

  3. 最后也是最简单的解决方案是同时启用cookie authentication,继续使用bearer token authentication 进行WebAPI 呼叫,并让OWIN Middleware 授权集线器上的呼叫。 (这个解决方案确实有效)。

现在,问题是使用WebAPI 应用程序的默认模板和Individual User Accounts(因此使用令牌身份验证),每当我向API 发送AJAX 请求时,它也会发送cookie。

public partial class Startup
    {
        public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

        public static string PublicClientId { get; private set; }

        // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
        public void ConfigureAuth(IAppBuilder app)
        {
            // Configure the db context and user manager to use a single instance per request
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

            app.UseCookieAuthentication(new CookieAuthenticationOptions());


            PublicClientId = "self";
            OAuthOptions = new OAuthAuthorizationServerOptions
            {
                TokenEndpointPath = new PathString("/Token"),
                Provider = new ApplicationOAuthProvider(PublicClientId),
                AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
                AllowInsecureHttp = true
            };

            app.UseOAuthBearerTokens(OAuthOptions);

        }
    }



public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        // Configure Web API to use only bearer token authentication.
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

即使我这样做了:

    config.SuppressDefaultHostAuthentication();
    config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

Authorization: Bearer 2bTw5d8Vf4sKR9MNMqZsxIOPHp5qtXRTny5YEC_y7yWyrDLU0__q8U8Sbo7N7XBjPmxZXP18GRXjDVb3yQ9vpQnWXppRhVA8KDeGg2G5kITMxiOKvGMaKwyUGpORIeZ0UHyP9jA2fX9zPwzsCqHmq-LoGKls0MQNFjXgRGCCCvro5WPMAJcLs0kUoD_2W_TOTy9_T-koobw-DOivnazPo2Z-6kfXaIUuZ1YKdAbcSJKzpyPR_XrCt4Ma2fCf-LcpMPGo4gDFKfxWdId0XtfS9S-5cXmmOmGM4Y6MkAUK8O9sZlVrpmpvV0hjXF2QwfLtQViPyEctbTr1vPBNn014n60APwGSGnbUJBWMvJhqcjI5pWoubCmk7OHJrn052U_F3bDOi2ha1mVjvhVY1XMAuv2c3Pbyng2ZT_VuIQI7HjP4SLzV6JjRctfIPLEh67-DFp585sJkqgfSyM6h_vR2gPA5hDocaFs73Qa22QMaLRrHThU0HM8L3O8HgFl5oJtD
Referer: http://localhost:15379/index.html
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,ro;q=0.6
Cookie: .AspNet.Cookies=E71BnnTMv8JJ4hS9K46Y2yIbGMQCTS4MVBWBXezUYCSGXPbUPNZh98Q0IElQ0zqGyhB7OpYfdh10Kcy2i5GrWGSiALPPtOZUmszfAYrLZwG2JYiU5MSW80OGZVMY3uG2U1aqvvKJpv7eJwJSOoS4meD_3Qy8SwRzTg8feZArAE-REEXSsbPfq4jQBUUbxfDAyuPVRsLNfkn4oIAwZTs85IulRZI5mLnLqOS7VLejMGIWhkuyOWvvISu1pjsP5FMDXNwDkjv2XCaOpRzZYUxBQJzkcdpDjwW_VO2l7HA263NaG_IBqYpLqG57Fi-Lpp1t5Deh2IRB0VuTqAgrkwxifoBDCCWuY9gNz-vNjsCk4kZc8QKxf7el1gu9l38Ouw6K1EZ9y2j6CGWmW1q-DobaK9JXOQEPm_LGyaGPM5to2vchTyjuieZvLBAjxhLKnXdy34Z7MZXLVIwmpSmyPvmbIuH9QzOvTWD-I1AQFJyCDw8

您是否看到使用令牌身份验证来验证SignalR 的更简单方法?最后一种方法(如果我设法通过请求抑制 cookie 的发送)在生产中可行吗?

【问题讨论】:

标签: asp.net authentication cookies asp.net-web-api signalr


【解决方案1】:

在处理那个特定项目时,我最终只使用了 cookie 身份验证和 CSRF,但我仍然有兴趣了解如何使用不记名令牌身份验证对 WebApi 和 SignalR 进行身份验证。

For a working sample, please see this GitHub repository.

我最终创建了一个 OAuthBearerTokenAuthenticationProvider 类来尝试从 cookie 中检索令牌。

public class OAuthBearerTokenAuthenticationProvider : OAuthBearerAuthenticationProvider
    {
        public override Task RequestToken(OAuthRequestTokenContext context)
        {
            var tokenCookie = context.OwinContext.Request.Cookies["BearerToken"];

            if (!String.IsNullOrEmpty(tokenCookie))
                context.Token = tokenCookie;

            return Task.FromResult<object>(null);
        }
    }

这是Startup 类中处理身份验证的方法:

    public void ConfigureOAuth(IAppBuilder app)
    {
        OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = new AuthorizationServerProvider()
        };

        app.UseOAuthAuthorizationServer(OAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
        {
            Provider = new OAuthBearerTokenAuthenticationProvider()
        });

    }

For a working sample, please see this GitHub repository.

希望这在某些时候可以帮助某人。

【讨论】:

  • 您的仓库的链接已损坏。你能添加一个工作链接吗?
猜你喜欢
  • 2016-01-12
  • 2012-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多