繁体   English   中英

ADFS SSO SAML Windows集成身份验证不起作用

[英]ADFS SSO SAML Windows Integrated authentication does not work

我们现在正在使用的项目是使用SAML令牌通过ADFS进行单点登录。
该项目应遵循的基本规则如下:
1.代理使用其凭据登录Windows。
2.代理登录Web应用程序(依赖方)
3. Web应用程序应重定向到ADFS中的STS(Active Directory是身份提供程序),并使用代理在其Windows身份验证(无缝身份验证)中使用的凭据进行登录。
4.因此, 不应出现 STS登录页面,并且应对用户进行身份验证
5.之后,应收到索赔和安全令牌,以便我们授权代理

实际结果:
1.首次完成重定向,并再次进行身份验证(IE身份验证页面和Firefox \\ Chrome身份验证页面)。
在此输入图像描述
在此输入图像描述

  1. 可以对所有类型的域用户进行身份验证,而不仅仅是经过Windows身份验证的用户。
  2. 首次登录sts登录页面后,不再需要进行身份验证。 但是,我们不希望第二次身份验证。 仅在Windows登录时(仅适用于IE)。

配置环境:
1.同一台机器上的域控制器+ ADFS服务器3.0(Win2k12R2)
2. Web应用程序机器(Win2k12 + IIS8.5)
3.这些机器在同一个域上

ADFS配置:

在此输入图像描述
在此输入图像描述
在此输入图像描述

依赖方配置:

在此输入图像描述 在此输入图像描述
在此输入图像描述

IE配置:
在此输入图像描述
在此输入图像描述
在此输入图像描述

Web App配置:
验证:

在此输入图像描述 ASP.Net项目:
Web配置文件:

<?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=169433
  -->
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <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>
  <connectionStrings>
    <add name="DefaultConnection" providerName="System.Data.SqlClient" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-TestApp-20150730141753;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-TestApp-20150730141753.mdf" />
  </connectionStrings>
  <location path="FederationMetadata">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>
  <system.web>
    <authorization>
      <deny users="?" />
    </authorization>
    <authentication mode="None" />
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
    <pages>
      <namespaces>
        <add namespace="System.Web.Optimization" />
      </namespaces>
    <controls><add assembly="Microsoft.AspNet.Web.Optimization.WebForms" namespace="Microsoft.AspNet.Web.Optimization.WebForms" tagPrefix="webopt" /></controls></pages>
    <!--<authentication mode="Forms">
      <forms loginUrl="~/Account/Login" timeout="2880" defaultUrl="~/" />
    </authentication>-->
    <profile defaultProvider="DefaultProfileProvider">
      <providers>
        <add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" />
      </providers>
    </profile>
    <membership defaultProvider="DefaultMembershipProvider">
      <providers>
        <add name="DefaultMembershipProvider" type="System.Web.Providers.DefaultMembershipProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
      </providers>
    </membership>
    <roleManager defaultProvider="DefaultRoleProvider">
      <providers>
        <add name="DefaultRoleProvider" type="System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" />
      </providers>
    </roleManager>
    <!--
            If you are deploying to a cloud environment that has multiple web server instances,
            you should change session state mode from "InProc" to "Custom". In addition,
            change the connection string named "DefaultConnection" to connect to an instance
            of SQL Server (including SQL Azure and SQL  Compact) instead of to SQL Server Express.
      -->
    <sessionState mode="InProc" customProvider="DefaultSessionProvider">
      <providers>
        <add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" />
      </providers>
    </sessionState>

  </system.web>
  <system.webServer>
    <modules>
      <!--<add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />-->
      <add name="FixedWSFederationAuthenticationModule" type="TestApp.FixedWSFederationAuthenticationModule, TestApp" preCondition="managedHandler" />
      <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
    </modules>
  </system.webServer>
  <system.identityModel>
    <identityConfiguration saveBootstrapContext="true">
      <!-- The identity configuration. No name means default configuration which is always used for passive federation scenarios. see federationConfiguration element -->
      <audienceUris>
        <add value="https://ccsp12.pj12.loc/testapp" />
      </audienceUris>
      <issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <trustedIssuers>
          <add thumbprint="91992FCF8B03FF9BD98A259FE93B92620E9DD89A" name="http://sts.pj12.loc/adfs/services/trust" />
        </trustedIssuers>
      </issuerNameRegistry>
      <certificateValidation certificateValidationMode="None" />
    </identityConfiguration>
  </system.identityModel>
  <system.identityModel.services>
    <federationConfiguration> <!-- Configures the WSFederationAuthenticationModule (WSFAM) and the SessionAuthenticationModule (SAM) when using federated authentication through the WS-Federation protocol -->
      <cookieHandler requireSsl="false" />
      <!-- passiveRedirectEnabled true means that a relaying party (test app) instead of having its own login page, it will redirect to the sts issuer for authentication and the sts will reply to the relaying party -->
      <!-- Due to WSFederationAuthenticationModule bug, the relaying party address must be with '/' at the end -->
      <wsFederation passiveRedirectEnabled="true" issuer="https://sts.pj12.loc/adfs/ls/" realm="https://ccsp12.pj12.loc/testapp/" reply="https://ccsp12.pj12.loc/testapp/" requireHttps="true" />
    </federationConfiguration>
  </system.identityModel.services>
  <!--<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="DotNetOpenAuth.Core" publicKeyToken="2780ccd10d57b246" />
        <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="DotNetOpenAuth.AspNet" publicKeyToken="2780ccd10d57b246" />
        <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.1.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>-->
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
  </entityFramework>
</configuration>

C#代码:

namespace TestApp
{
    public partial class _Default : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // local variables
            string claimsTypes = string.Empty;
            string claimsValues = string.Empty;
            string claimsValueTypes = string.Empty;
            string claimsSubjectNames = string.Empty;
            string claimsIssuers = string.Empty;
            // initialize claims and identity
            ClaimsPrincipal claimsPrincipal = Thread.CurrentPrincipal as ClaimsPrincipal;
            ClaimsIdentity claimsIdentity = Thread.CurrentPrincipal.Identity as ClaimsIdentity;
            BootstrapContext bootstrapContext =
            ClaimsPrincipal.Current.Identities.First().BootstrapContext
                                                    as BootstrapContext;

            if (claimsPrincipal != null)
            {
                signedIn.Text = "You are signed in.";

                foreach (Claim claim in claimsPrincipal.Claims)
                {
                    claimsTypes = string.Concat(claimsTypes, "; ", claim.Type);
                    claimsValues = string.Concat(claimsValues, "; ", claim.Value);
                    claimsValueTypes = string.Concat(claimsValueTypes, "; ", claim.ValueType);
                    claimsSubjectNames = string.Concat(claimsSubjectNames, "; ", claim.Subject.Name);
                    claimsIssuers = string.Concat(claimsIssuers, "; ", claim.Issuer);
                }

                //claims principals
                claimType.Text = claimsTypes;
                claimValue.Text = claimsValues;
                claimValueType.Text = claimsValueTypes;
                claimSubjectName.Text = claimsSubjectNames;
                claimIssuer.Text = claimsIssuers;

                // ClaimsIdentity
                isUserAuthenticated.Text = claimsIdentity.IsAuthenticated.ToString();
                authenticationType.Text = claimsIdentity.AuthenticationType;
                claimName.Text = claimsIdentity.Name;

                // Token
                // known bug : http://stackoverflow.com/questions/13514553/wif-4-5-bootstrapcontext-security-token-null
                SecurityToken token = null;
                if (bootstrapContext.SecurityToken != null)
                {
                    token = bootstrapContext.SecurityToken;
                }
                else if (!bootstrapContext.Token.Equals(string.Empty))
                {
                    var handlers = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.SecurityTokenHandlers;
                    token = handlers.ReadToken(new XmlTextReader(new StringReader(bootstrapContext.Token)));
                }

                SamlSecurityToken sst = token as SamlSecurityToken;
                tokenId.Text = sst.Id;
                tokenAssertionId.Text = sst.Assertion.AssertionId;
                tokenIssuer.Text = sst.Assertion.Issuer;

            }
            else
            {
                signedIn.Text = "You are not signed in.";
            }
        }
    }  

任何帮助将不胜感激。

最后我能够实现无缝windows集成SSO!

我找到了一些名为“WIASupportedUserAgents”的ADFS属性。 这意味着:支持WIA(Windows集成身份验证)的浏览器。
在PowerShell中运行以下命令:

Set-ADFSProperties -WIASupportedUserAgents @("MSIE 6.0", "MSIE 7.0", "MSIE 8.0", "MSIE 9.0", "MSIE 10.0", "MSIE 11.0", "Trident/7.0", "MSIPC", "Windows Rights Management Client", "Mozilla/5.0")  

比重启ADFS服务。

为所有浏览器支持设置此属性后,无缝Windows身份验证SSO开始工作!
我现在没有获取凭据窗口,并且经过身份验证的Windows用户通过ADFS自动进行身份验证。

像魅力一样工作。

感谢所有人,特别是Wiktor Zychla,他非常愿意提供帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM