ASP.NET标识:修改声明后不更新cookie

时间:2017-01-31 16:09:24

标签: c# asp.net asp.net-mvc asp.net-identity

我在.Net 4.6.2 / MVC5中更新ASP.Net Identity 2.2.1的声明时遇到问题。 更新声明后,它通常会向浏览器发送更新的cookie,一切正常,但有时没有设置cookie标头发送到浏览器。

我无法确定何时发生任何模式,而不是在发生故障时,服务器正在发送

Persistent-Auth: true

会话中每个响应的http标头值。我不知道导致此标头值设置的原因,有时会出现在会话中间,一旦开始发送,它将在会话的剩余时间内发送,尝试更新声明将永远不会再次工作该会议。

据我所知,我在每次调用ASP.Net标识时都将isPersistent参数硬编码为false,我看不到任何可能与此标题相关的内容。

我用于更新声明的代码是

public static void UpdateClaims(List<Claim> claims)
{
    var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
    var newIdentity = new ClaimsIdentity(HttpContext.Current.User.Identity);

    foreach (Claim claim in claims)
    {
        Claim oldClaim = newIdentity.FindFirst(claim.Type);
        if (oldClaim != null && oldClaim.Type != "")
        {
            newIdentity.RemoveClaim(oldClaim);
        }
        newIdentity.AddClaim(claim);
    }
    authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant
          (new ClaimsPrincipal(newIdentity), new AuthenticationProperties { IsPersistent = false });
}

这是从MVC操作方法调用的。

有没有人有任何可能出错的建议,甚至只是在哪里寻找起点?我不知道是什么导致了持久性身份验证标头,但它看起来与问题有关;无论是问题的原因还是症状,我都不知道。

我使用ASP.Net Identity 2.2.1和.Net 4.6.2。 我在Windows Server 2012R2上运行,问题似乎发生在IE11,Chrome和Firefox上。 我使用Fiddler 4.6.3查看http标头/响应。

更新: 我注意到只有在启用Windows身份验证时才会出现问题。我的服务器有一个允许用户名/密码,Windows身份验证或两者的设置(用户可以选择使用用户名/密码以其他用户身份登录)。当使用windows auth时,我最初使用Windows对用户进行身份验证,然后设置一个cookie,然后我将其用于会话中的所有未来请求。 如果禁用了Windows身份验证,则更新此类声明始终有效。如果启用了Windows身份验证,则更新声明通常有效。

4 个答案:

答案 0 :(得分:14)

首先,你将两种不同的东西混为一谈,虽然这是可以理解的,因为它们的名字相似。 IsPeristent设置确定cookie是会话cookie还是持久cookie。换句话说:它确定在浏览器关闭时或在某个预定时间,无论浏览器是否关闭,cookie是否会过期。

Persistent-Auth标头是一个优化标头,通知客户端它不一定需要授权每个请求。它与IsPersistent标志无关。

声明在登录时设置。期。如果您需要更新声明,则必须签署用户并重新签名。这可以通过编程方式完成(即无需用户干预),但必须完成。换句话说,如果您需要更改声明,并且您需要在下一个请求中提供该更改,那么请按照以下步骤进行:

身份2.0

AuthenticationManager.SignOut();
await SignInManager.SignInAsync(user);

Identity 3.0

await SignInManager.RefreshSignInAsync(user);

答案 1 :(得分:4)

而不是

MyParserClass

你应该使用

authenticationManager.AuthenticationResponseGrant = 
    new AuthenticationResponseGrant(new ClaimsPrincipal(newIdentity), 
    new AuthenticationProperties { IsPersistent = false });

答案 2 :(得分:1)

我发现了问题。它在尝试更新声明时使用了错误的标识。在我的场景中,有两个身份对象,一个用于Windows身份验证,另一个用于cookie身份验证。在大多数情况下,Pod获取cookie身份验证对象(具有声明的那个)但偶尔会给我一个Windows身份验证对象,因此当我尝试更新声明时,它没有做任何事。

问题通过替换

解决了
HttpContext.Current.User.Identity

var newIdentity = new ClaimsIdentity(HttpContext.Current.User.Identity);

现在似乎可以稳定地工作而无需再次退出/退回。

我想当OWin认为Windows身份验证是主要身份时,会发送ClaimsIdentity oldIdentity = claimsPrincipal.Identities.FirstOrDefault(i => i.AuthenticationType == "ApplicationCookie"); var newIdentity = new ClaimsIdentity(oldIdentity); http标头,这就是为什么它的存在与无法更新声明相关的原因。

答案 3 :(得分:0)

我认为在我们的案例中,这是ApplicationUserManager的错误/长期IoC生命周期/“作用域”,而且角色管理器也可能是相同的。