登录后,“ User.Identity.Name”为null,但使用Sustainsys.Saml2.Mvc集成时,“ IsAuthenticated”为true

时间:2018-12-20 18:47:11

标签: c# asp.net-mvc forms-authentication sustainsys-saml2

我有一个ASP.NET MVC 5应用程序,并且需要支持SAML 2.0身份验证。我正在评估Sustainsys.Saml.Mvc。我的控制器中的User.Identity.Name属性是一个空字符串,而User.Identity.IsAuthenticated属性是true,并且我一生都无法理解。

在安装Sustainsys.Saml2.Mvc NuGet软件包时,我必须做以下事情:

  1. .NET框架从4.5.1升级到4.6.1
  2. 安装Sustainsys.Saml2.Mvc v2.2.0
  3. 将Microsoft.AspNet.Mvc程序包从5.2.3升级到5.2.7
  4. 根据Sustainsys.Saml2 documentation
  5. 调整了Web.config设置
  6. 从其演示MVC应用程序中下载了.cert和.pfx文件

Web.config的内容:

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=301880
  -->
<configuration>
  <configSections>
    <sectionGroup name="elmah">
      <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
      <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
      <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
      <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
    </sectionGroup>
    <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" />
    <section name="sustainsys.saml2" type="Sustainsys.Saml2.Configuration.SustainsysSaml2Section, Sustainsys.Saml2" />
  </configSections>
  <connectionStrings>
    ...
  </connectionStrings>
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  </appSettings>
  <!--
    For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367.

    The following attributes can be set on the <httpRuntime> tag.
      <system.Web>
        <httpRuntime targetFramework="4.6.1" />
      </system.Web>
  -->
  <system.web>
    <customErrors mode="Off" />
    <compilation debug="true" targetFramework="4.6.1" />
    <httpRuntime targetFramework="4.6.1" requestValidationMode="2.0" />
    <authentication mode="Forms">
      <forms loginUrl="~/Saml2/SignIn" />
    </authentication>
    <membership defaultProvider="ABC">
      <providers>
        <clear />
        <add name="ABC" type="System.Web.Security.ActiveDirectoryMembershipProvider" connectionStringName="ADConnectionString" attributeMapUsername="sAMAccountName" />
      </providers>
    </membership>
    <httpModules>
      <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
      <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
      <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
    </httpModules>
  </system.web>
  <system.webServer>
    <handlers>
      <add name="UrlRoutingHandler" type="System.Web.Routing.UrlRoutingHandler, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" path="Authorization/Permissions/*" verb="GET,POST" />
    </handlers>
    <staticContent>
      <remove fileExtension="eot" />
      <remove fileExtension="otf" />
      <remove fileExtension="woff" />
      <remove fileExtension="woff2" />
      <remove fileExtension="ttf" />
      <remove fileExtension="json" />
      <mimeMap fileExtension="eot" mimeType="application/vnd.ms-fontobject" />
      <mimeMap fileExtension="otf" mimeType="application/x-font-opentype" />
      <mimeMap fileExtension="woff" mimeType="application/x-font-woff" />
      <mimeMap fileExtension="woff2" mimeType="application/font-woff2" />
      <mimeMap fileExtension="ttf" mimeType="application/x-font-ttf" />
      <mimeMap fileExtension="json" mimeType="application/json" />
    </staticContent>
    <validation validateIntegratedModeConfiguration="false" />
    <modules>
      <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
      <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
      <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
      <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    </modules>
    <httpErrors errorMode="Detailed" />
  </system.webServer>
  <sustainsys.saml2 entityId="http://localhost/MyMvcApp/Saml2" returnUrl="http://localhost/MyMvcApp/">
    <identityProviders>
      <add entityId="https://stubidp.sustainsys.com/Metadata" signOnUrl="https://stubidp.sustainsys.com/" allowUnsolicitedAuthnResponse="true" binding="HttpRedirect">
        <signingCertificate fileName="~/App_Data/stubidp.sustainsys.com.cer" />
      </add>
    </identityProviders>
    <!--<federations>
      <add metadataLocation="http://localhost:52071/Federation" allowUnsolicitedAuthnResponse="true"/>
    </federations>-->
    <serviceCertificates>
      <add fileName="~/App_Data/Sustainsys.Saml2.Tests.pfx" />
    </serviceCertificates>
  </sustainsys.saml2>
  <system.identityModel.services>
    <federationConfiguration>
      <cookieHandler requireSsl="false" />
    </federationConfiguration>
  </system.identityModel.services>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
        <bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.5.0.0" newVersion="3.5.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Oracle.DataAccess" publicKeyToken="89b483f429c47342" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.121.2.0" newVersion="4.121.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <system.net>
    <mailSettings>
      <smtp deliveryMethod="SpecifiedPickupDirectory" from="foo@mycompany.com">
        <network host="smtp.mycompany.com" port="25" defaultCredentials="true" />
        <specifiedPickupDirectory pickupDirectoryLocation="..." />
      </smtp>
    </mailSettings>
  </system.net>
  <elmah>
    <!--
        See http://code.google.com/p/elmah/wiki/SecuringErrorLogPages for
        more information on remote access and securing ELMAH.
    -->
    <security allowRemoteAccess="true" />
    <errorLog type="Elmah.MemoryErrorLog, Elmah" size="50" />
  </elmah>
  <location path="elmah.axd" inheritInChildApplications="false">
    <system.web>
      <httpHandlers>
        <add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
      </httpHandlers>
      <!--
        See http://code.google.com/p/elmah/wiki/SecuringErrorLogPages for
        more information on using ASP.NET authorization securing ELMAH.-->
      <authorization>
        <allow users="..." />
        <deny users="*" />
      </authorization>
    </system.web>
    <system.webServer>
      <handlers>
        <add name="ELMAH" verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" preCondition="integratedMode" />
      </handlers>
    </system.webServer>
  </location>
</configuration>

我目前正在从笔记本电脑托管我的应用程序:

  • Windows 10企业版
  • 已安装最高4.6.1的.NET Framework
  • IIS 10.0.15063.0
  • IIS中的应用程序池设置:
    • .NET 4.0
    • 允许32位应用程序

它正在https://stubidp.sustainsys.com/

使用模拟身份提供程序

XML发布到/ MyApp / Saml2 / Acs:

<saml2p:Response Destination="http://localhost/MyApp/Saml2/Acs" ID="idb4440bf88fba449f8526760d4330dd53" Version="2.0" IssueInstant="2018-12-20T18:21:22Z" InResponseTo="idd9b8948ac5ac4c389bf65072169464ac"
    xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
    <saml2:Issuer
        xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://stubidp.sustainsys.com/Metadata
    </saml2:Issuer>
    <Signature
        xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
            <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
            <Reference URI="#idb4440bf88fba449f8526760d4330dd53">
                <Transforms>
                    <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                    <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                </Transforms>
                <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
                <DigestValue>...</DigestValue>
            </Reference>
        </SignedInfo>
        <SignatureValue>...</SignatureValue>
        <KeyInfo>
            <X509Data>
                <X509Certificate>...</X509Certificate>
            </X509Data>
        </KeyInfo>
    </Signature>
    <saml2p:Status>
        <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
    </saml2p:Status>
    <saml2:Assertion
        xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" ID="_d6ffcd18-44ec-45db-bd74-9cf48ea1cfa2" IssueInstant="2018-12-20T18:21:22Z">
        <saml2:Issuer>https://stubidp.sustainsys.com/Metadata</saml2:Issuer>
        <saml2:Subject>
            <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">JohnDoe</saml2:NameID>
            <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml2:SubjectConfirmationData NotOnOrAfter="2018-12-20T18:23:22Z" InResponseTo="..." Recipient="http://localhost/MyApp/Saml2/Acs" />
            </saml2:SubjectConfirmation>
        </saml2:Subject>
        <saml2:Conditions NotOnOrAfter="2018-12-20T18:23:22Z">
            <saml2:AudienceRestriction>
                <saml2:Audience>http://localhost/MyApp/Saml2</saml2:Audience>
            </saml2:AudienceRestriction>
        </saml2:Conditions>
        <saml2:AuthnStatement AuthnInstant="2018-12-20T18:21:22Z" SessionIndex="42">
            <saml2:AuthnContext>
                <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml2:AuthnContextClassRef>
            </saml2:AuthnContext>
        </saml2:AuthnStatement>
    </saml2:Assertion>
</saml2p:Response>

我还在控制器上设置了Options.Logger属性,这是我在调试输出中得到的:

[Saml2, DEBUG]: Http POST binding extracted message
<saml2p:Response Destination="http://localhost/MyApp/Saml2/Acs" ...>...</saml2p:Response>
[Saml2, DEBUG]: Signature validation passed for Saml Response Microsoft.IdentityModel.Tokens.Saml2.Saml2Id
[Saml2, DEBUG]: Extracted SAML assertion _a5ee9c7f-4ca5-4693-a7f7-301ae5e6d4a6
[Saml2, INFO]: Successfully processed SAML response Microsoft.IdentityModel.Tokens.Saml2.Saml2Id and authenticated JohnDoe

在调试应用程序时,我的MVC控制器中的User.Identity.Name属性为null。对该对象的进一步检查:

Screenshot of debug console in Visual Studio

成功声明SAML响应后,System.Web.Mvc.Controller.User.Identity.Name为什么为空?

3 个答案:

答案 0 :(得分:1)

您已正确完成身份验证。并且您有一个工作会话身份验证Cookie。

但是您没有的是与默认名称声明类型匹配的声明。您具有NameIdentifier声明(默认情况下,存根idp提供该声明)。但是您没有默认NameClaimType

的声明

Name的{​​{1}}属性实现为

ClaimsIdentity

因此,要获取return Claims.FirstOrDefault(c => c.Type == NameClaimType)?.Value; 属性的值,您需要更改Name(可以通过修改NameClaimType通知中创建的标识来完成)或将您的Idp提供类型为AcsCommandResultCreated的属性。您可以通过在stubidp表单的底部添加一个属性来做到这一点。

答案 1 :(得分:0)

我没有使用身份服务器,但存在相同的基本问题:

User.Identity.Claims下查看您的声明,并找到一个具有您的用户名的声明。

enter image description here

然后,无论您在哪里配置令牌验证,都必须将NameClaimType设置为上面看到的密码:

然后,当中间件对其进行验证时,它将把该声明复制到UserName中。我假设这是Windows身份验证的默认值[sic]。

   var tokenValidationParameters = new TokenValidationParameters
   {
            NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",

答案 2 :(得分:0)

对于Core 3.1,存在相同的问题:User.Identity.Name属性为null,而User.Identity.IsAuthenticated为true。但是您可以通过在控制器中使用HttpContectAccessor来获得名称:

private readonly IHttpContextAccessor _httpContextAccessor;

public MyController(IHttpContextAccessor httpContextAccessor)
{
   _httpContextAccessor = httpContextAccessor;
}

public void AnyMethod()
{
  var userId = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
  var user = _context.AspNetUsers.Find(userId);
  var name = user.UserName;
  ...
}

在Startup.cs中添加服务:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();