Web API 和 SignalR Web 应用程序 - 身份验证和授权

WebAPI & SignalR web application - Authenticating & Authorizing

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

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

  1. 实际上将 header 传递给 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 授权调用在集线器上。 (这个解决方案确实有效)。

现在,问题是每当我向 API 它也发送 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)在生产中是否可行?

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

For a working sample, please see this GitHub repository.

我最终创建了一个 OAuthBearerTokenAuthenticationProvider class 试图从 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 class 中处理身份验证的方法:

    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.

希望这在某些时候对某人有所帮助。