[英]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.同一台機器上的域控制器+ ADFS服務器3.0(Win2k12R2)
2. Web應用程序機器(Win2k12 + IIS8.5)
3.這些機器在同一個域上
ADFS配置:
依賴方配置:
Web App配置:
驗證:
<?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.