Owin Web 角色不会解密 Owin MVC 应用程序提供的 cookie

Owin web role will not decrypt cookie provided by Owin MVC Application

MVC Web 应用程序

我有一个以前使用 FormsAuthentication 的 MVC 5 网站,此后我已切换到 OWIN 身份验证。使用 OWIN 登录和退出网站工作正常。这是启动配置。

public partial class Startup
{
    // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
    public void ConfigureAuth(IAppBuilder app)
    {
        // Enable the application to use a cookie to store information for the signed in user
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/LogOn")
        });
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
    }

它在登录时有一些基本的声明设置...

    public void SignIn(string username, bool remember, string userData)
    {
        var claims = new List<Claim>();

        var user = JsonConvert.DeserializeObject<VastIdentity>(userData);
        // create *required* claims
        claims.Add(new Claim(ClaimTypes.NameIdentifier, user.UserId.ToString()));
        claims.Add(new Claim(ClaimTypes.Name, username));

        // custom – serialised user state
        claims.Add(new Claim("userState", userData));

        var identity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);

        AuthenticationManager.SignIn(new AuthenticationProperties()
        {
            AllowRefresh = true,
            IsPersistent = remember,
            ExpiresUtc = DateTime.UtcNow.AddDays(7)
        }, identity);
    }

一切正常,用户可以使用适当的 cookie 登录和退出 MVC 应用程序。

SignalR Web 角色

我有一个单独的 Azure Web 角色来托管信号器。它具有以下启动...

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        //GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => new CustomUserIdProvider());

        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            AuthenticationMode = AuthenticationMode.Active,
            CookieName = ".AspNet.ApplicationCookie",
            Provider = new CustomAuthProvider()
        });

        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        // Branch the pipeline here for requests that start with "/signalr"
        app.Map("/signalr", map =>
        {
            // Setup the CORS middleware to run before SignalR.
            // By default this will allow all origins. You can 
            // configure the set of origins and/or http verbs by
            // providing a cors options with a different policy.
            map.UseCors(CorsOptions.AllowAll);
            var hubConfiguration = new HubConfiguration
            {
                // You can enable JSONP by uncommenting line below.
                // JSONP requests are insecure but some older browsers (and some
                // versions of IE) require JSONP to work cross domain
                // EnableJSONP = true
            };
            // Run the SignalR pipeline. We're not using MapSignalR
            // since this branch already runs under the "/signalr"
            // path.
            map.RunSignalR(hubConfiguration);
        });
    }
}

问题 1: 当连接到 SignalR 集线器并调用 OnConnected 时,Context.User.Identity 是一个空的 GenericPrincipal,不包含来自网站的声明曲奇饼。这就是我要实施自定义身份验证提供程序并自己设置身份的原因。不过好像没用

public class NotificationHub : Hub
{
    // snip

    public override Task OnConnected()
    {
        string name = Context.User.Identity.Name;

        _Connections.Add(name, Context.ConnectionId);

        return base.OnConnected();
    }
  }

当我检查上下文中的 cookie 时,我可以看到加密的 .AspNet.ApplicationCookie 随请求一起传递。但是我不知道如何让 OWIN 解密它并使用可用的声明。

问题 2: 自定义身份验证提供程序永远不会 运行。当我在其中设置断点时,它永远不会进入任何一种方法。

public class CustomAuthProvider : CookieAuthenticationProvider
{
    public override void ResponseSignIn(CookieResponseSignInContext context)
    {
        // do some custom stuff here
        base.ResponseSignIn(context);
    }

    public override Task ValidateIdentity(CookieValidateIdentityContext context)
    {
        // do some custom stuff here
        return base.ValidateIdentity(context);
    }
}

我对 OWIN 身份验证没有太多经验。任何人都可以看到信号器网络角色 cookie 身份验证可能出了什么问题吗?

拔掉头发后,我重新检查了 owin nugget 包的版本,发现 Web 应用程序使用的是 3.0.1,而 SignalR Web 角色使用的是 2.x。

解决方案是确保 owin 库在应用程序之间的版本相同。 owin 似乎无法解密从不同版本生成的 cookie。


编辑:由于解密 cookie 的问题与版本不匹配有关,因此不需要自定义身份验证提供程序和 cookie 名称。

这导致以下简单的 owin 在 web 角色中初始化...

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            AuthenticationMode = AuthenticationMode.Active,
        });

        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        // Branch the pipeline here for requests that start with "/signalr"
        app.Map("/signalr", map =>
        {
            // Setup the CORS middleware to run before SignalR.
            // By default this will allow all origins. You can 
            // configure the set of origins and/or http verbs by
            // providing a cors options with a different policy.
            map.UseCors(CorsOptions.AllowAll);
            var hubConfiguration = new HubConfiguration
            {
                // You can enable JSONP by uncommenting line below.
                // JSONP requests are insecure but some older browsers (and some
                // versions of IE) require JSONP to work cross domain
                // EnableJSONP = true
            };
            // Run the SignalR pipeline. We're not using MapSignalR
            // since this branch already runs under the "/signalr"
            // path.
            map.RunSignalR(hubConfiguration);
        });
    }
}