会话cookie无法读取ASP.NET MVC APP中的MachineKeySessionSecurityTokenHandler SessionSecurityToken

时间:2017-08-15 16:35:19

标签: asp.net-mvc cookies session-cookies wif4.5

在我的项目设置中,我没有身份提供者,而是使用我们内部系统设置的cookie值之一进行身份验证,并将该值转换为声明身份。

创建声明标识后,我计划使用SessionAuthenticationModule和MachineKeySessionSecurityTokenHandler将标识写入应用程序的Session Cookie,如下所示。

                SessionSecurityToken token = new SessionSecurityToken(principal);
                        var handler = new MachineKeySessionSecurityTokenHandler(new TimeSpan(3, 30, 30));
                        var securityToken = handler.WriteToken(token);
                        SessionAuthenticationModule sam = new SessionAuthenticationModule();
                        sam.CookieHandler.RequireSsl = false; // This is required only for localhost to work
                        sam.CookieHandler.Write(securityToken, "Token", DateTime.Today.AddDays(1));

但是,在回读cookie设置时,我无法将其解析回SessionSecurityToken或Claims Identity。任何阅读此cookie并将其转换为声明的帮助都会有很大的帮助。

我使用以下代码片段来回读cookie,但是我在handler.ReadToken方法中遇到错误“ ID4008:'SecurityTokenHandler'未提供'ReadToken'的实现。“错误消息。

                //Check if the CGX session cookie is available
                SessionAuthenticationModule sam = new SessionAuthenticationModule();
                sam.CookieHandler.Name = "Token";
                sam.CookieHandler.RequireSsl = false;
                var securityToken = sam.CookieHandler.Read(filterContext?.HttpContext.ApplicationInstance.Context);

                if (securityToken != null)
                {
                    var handler = new MachineKeySessionSecurityTokenHandler(new TimeSpan(3, 30, 30));
                    var tokenString = Convert.ToBase64String(securityToken);
                    var token = handler.ReadToken(tokenString) as SessionSecurityToken;
                    if (token != null) sam.AuthenticateSessionSecurityToken(token, true);
                }

读取和验证从应用程序设置的cookie值的正确方法是什么。正如我所说,MVC应用程序负责创建cookie并在后续请求中验证它。

1 个答案:

答案 0 :(得分:0)

最后,我找到了一个解决方案,让我的方案可以使用声明标识。

这是为了配置WIF 4.5以进行自定义或表单身份验证,而无需设置身份提供程序(STS),ASP.NET MVC应用程序RP将设置身份验证并在WebFarm方案的后续请求中使用它。 / p>

想要添加答案,以便有类似需求的人可以使用此功能。在我转到代码部分之前,我将添加对于按预期实现结果至关重要的配置。

在web.config中添加以下配置。

这是为了设置与身份相关的配置,

<configSections>
<!--WIF 4.5 sections -->
<section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</configSections>

下面是一个用于定义安全令牌处理程序和Cookie处理程序的文件,

<system.identityModel>
<identityConfiguration>
  <securityTokenHandlers>
    <remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    <add type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  </securityTokenHandlers>
</identityConfiguration>
</system.identityModel>

<system.identityModel.services>
<federationConfiguration>
  <cookieHandler name ="YourTokenName" mode="Default" requireSsl ="false">
    <chunkedCookieHandler chunkSize="3000"/>
  </cookieHandler>
</federationConfiguration>
</system.identityModel.services>

添加以下配置以设置机器密钥,因为我正在使用适用于WebFarm场景的MachineKeySessionSecurityTokenHandler,并在system.web部分中包含SessionAuthenticationModule,以使其在编写此答案时在localhost IIS Express VS2015上工作。

<system.web>
     <machineKey decryptionKey="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" validationKey="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" />
     <httpModules>
         <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
     </httpModules>
</system.web>

以下配置适用于IIS 7.0或更高版本的Web场服务器

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
       <add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
       <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
    </modules>
</system.webServer>

设置完配置后,现在可以轻松访问设置声明标识,声明主体,身份验证,安全令牌和Cookie。如下,

如果在Web应用程序中为CORS使用防伪标记,则需要定义UniqueClaimTypeIdentifier set tell Anti-forgery token generator以使用机器密钥加密的唯一标识符部分,否则防伪不会与声明标识一起使用。

在Global.asax

// Set Unique identifier for Antiforgery Token Generator
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;

将以下代码段放在Login方法或启动身份验证的任何代码路径中,

// Step 1: Setup Identity
var appClaims = new List<Claim>{
         new Claim(ClaimTypes.Name, "Your name claim"),
         new Claim("UserId", "User ID claim"),
         new Claim(ClaimTypes.NameIdentifier, "Name Identifier Claim Must"),
  }
ClaimsIdentity identity = new ClaimsIdentity(appClaims,"Name Of Identity");
// Step 2: Setup Principal
ClaimsPrincipal principal = new ClaimsPrincipal(claimsIdentity);

//Step 3: The below code path sets the claims principal, using SessionAuthenticationModule, authenticates the principal and sets to httpcontext and current thread, sets the cookie in browser.
var authedCp = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager.Authenticate("Name", principal);
var token = FederatedAuthentication.SessionAuthenticationModule.CreateSessionSecurityToken(authedCp, "Issuer Name", DateTime.UtcNow, DateTime.UtcNow.AddHours(1), false);
// This is only for debug mode in localhost, to make cookie written for local http or for https set it true
FederatedAuthentication.SessionAuthenticationModule.CookieHandler.RequireSsl = false;    
FederatedAuthentication.SessionAuthenticationModule.AuthenticateSessionSecurityToken(token, true);

放置此代码段,您需要验证Cookie是否包含声明详细信息,并在后续请求中再次进行身份验证(可能是操作过滤器),

//Check if the session cookie is available
SessionAuthenticationModule sam = FederatedAuthentication.SessionAuthenticationModule;
sam.CookieHandler.Name = "Token Name";
sam.CookieHandler.RequireSsl = false; //for local host, https make it true
var securityToken = sam.CookieHandler.Read(filterContext?.HttpContext.ApplicationInstance.Context);

if (securityToken != null)
{
    SessionSecurityToken sessionToken = null;
    var readStatus = sam.TryReadSessionTokenFromCookie(out sessionToken);
    if (sessionToken != null)
    {
        sam.AuthenticateSessionSecurityToken(sessionToken, true);
    }
}

现在,您在HttpContext上设置了声明主体和声明标识,并在后续请求中存储了Cookie。您可以在请求管道中随时访问它,当您向Identity中添加更多声明时,请注意cookie大小。

我要感谢Sander的博客文章https://itq.nl/mixing-forms-authentication-with-claims-based-authorisation-in-asp-net/,它帮助我设置了以后访问令牌的内容..