2017-08-15 61 views
0

在我的项目设置中,我没有身份提供者,而是使用我们内部系统设置的一个cookie值进行身份验证和转换价值观作为索赔身份。会话cookie无法读取ASP.NET MVC APP中的MachineKeySessionSecurityTokenHandler SessionSecurityToken APP

一旦创建了声明标识,我打算使用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或声明标识。任何帮助阅读这个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并在随后的请求中对其进行验证。

回答

0

最后,我找到了一个解决方案,以获得声明身份为我的方案工作。

这是配置WIF 4.5混合您的自定义或表单身份验证,而无需设置身份提供商(STS),您的ASP.NET MVC应用程序RP将设置身份验证并将其用于WebFarm场景的后续请求。

想添加答案,以便任何有类似需求的人都可以使用它。在我转到代码部分之前,我会添加对预期结果非常重要的配置。

在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> 

添加以下CONFIGS设立机因为我正在使用MachineKeySessionSecurityTokenHandler进行WebFarm场景,并在System.Web部分中包含SessionAuthenticationModule,以使其在本地主机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> 

以下CONFIGS是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> 

一旦CONFIGS的设置,现在它的简单访问设置索赔身份,声明主体,认证,安全令牌和Cookie。如下所示,

如果在Web应用程序中为CORS使用防伪令牌,则需要定义UniqueClaimTypeIdentifier集,告诉防伪造令牌生成器使用机器密钥加密的唯一标识符部分,否则防伪造将无法工作与索赔身份。

在Global.asax中

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

将下面的代码片段在登录方法或者你开始踢任何验证的代码路径,

// 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上的Claim Principal和Claims Identity标识设置以及后续请求中存储的Cookie中的Thread。您可以随时在请求管道中访问它,当您向Identity添加更多声明时,请注意cookie的大小。

我想感谢桑德他的博客文章https://itq.nl/mixing-forms-authentication-with-claims-based-authorisation-in-asp-net/,它帮助我设置了访问令牌的后续部分..