4

我有一个 ASP.NET MVC 应用程序,它是一个带有 ADFS 2.0 的被动 RP。此应用程序将所有未经授权的用户重定向到 ADFS。成功登录后,用户将使用包含其声明的令牌重定向回 Web 应用程序。这里没有什么新东西。

我现在要做的是使用已颁发的令牌调用 WCF 服务,因此该服务不需要返回 ADFS 并再次进行所有安全握手。

经过数小时的研究,我终于能够调用该服务,但是,当我在我的服务中使用以下代码时,我的用户仍未通过身份验证:

public string GetName()
{
    var user = Thread.CurrentPrincipal.Identity as ClaimsIdentity;
    if (user != null && user.IsAuthenticated)
    {
        return user.FindFirst(x => x.Type == ClaimTypes.NameIdentifier).Value;
    }
    return "Unable to find your username. Something went wrong .... sorry!";
}

我知道这个主题有成百上千的文章和其他 stackoverflow 问题,但我没有运气找到为什么我的用户没有通过身份验证,即使我可以成功调用我的服务。

您可能需要一些其他代码和配置详细信息来帮助解决此问题:

网络应用

服务电话

var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.IssuedKeyType = SecurityKeyType.BearerKey;
binding.Security.Message.EstablishSecurityContext = true;
binding.Security.Message.IssuerAddress = new EndpointAddress("https://fs.server.com/adfs/services/trust");

var endpoint = new EndpointAddress("https://" + "localhost/service" + "/user.svc");

var factory = new ChannelFactory<IUser>(binding, endpoint);
factory.Credentials.SupportInteractive = false;
factory.Credentials.UseIdentityConfiguration = true;

var context = (BootstrapContext)((ClaimsIdentity)Thread.CurrentPrincipal.Identity).BootstrapContext;
var channel = factory.CreateChannelWithIssuedToken(context.SecurityToken, endpoint);

ViewBag.Username = channel.GetName();
((IServiceChannel)channel).Close();

return View();

网页配置

 <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>
  <appSettings>
    <add key="webpages:Version" value="2.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="PreserveLoginUrl" value="true" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    <add key="ida:FederationMetadataLocation" value="https://fs.server.com:49160/FederationMetadata/2007-06/FederationMetadata.xml" />
    <add key="ida:Issuer" value="https://fs.server.com:49160/adfs/ls/" />
    <add key="ida:ProviderSelection" value="productionSTS" />
  </appSettings>
  <system.identityModel>
    <identityConfiguration saveBootstrapContext="true">
      <audienceUris>
        <add value="https://localhost/rp_poc" />
      </audienceUris>
      <issuerNameRegistry type="System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, System.IdentityModel.Tokens.ValidatingIssuerNameRegistry">
        <authority name="https://fs.server.com/adfs/services/trust">
          <keys>
            <add thumbprint="723C3A29732FC61F3BE96487E8560F749D1D8256" />
          </keys>
          <validIssuers>
            <add name="http://fs.server.com/adfs/services/trust" />
          </validIssuers>
        </authority>
      </issuerNameRegistry>
    </identityConfiguration>
  </system.identityModel>
  <system.identityModel.services>
    <federationConfiguration>
      <cookieHandler requireSsl="true" />
      <wsFederation passiveRedirectEnabled="true" issuer="https://fs.server.com:49160/adfs/ls/" realm="https://localhost/rp_poc" requireHttps="true" />
    </federationConfiguration>
  </system.identityModel.services>  
  <system.web>
    <authentication mode="None" />
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" requestValidationMode="4.5" />
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
      </namespaces>
    </pages>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <handlers>
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
    <modules>
      <remove name="FormsAuthentication" />
      <add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 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>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-1.3.0.0" newVersion="1.3.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

WCF 服务

网页配置

<configuration>
  <configSections>
    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
  </configSections>
  <system.identityModel>
    <identityConfiguration saveBootstrapContext="true">
      <issuerNameRegistry type="System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, System.IdentityModel.Tokens.ValidatingIssuerNameRegistry">
        <authority name="https://fs.server.com/adfs/services/trust">
          <keys>
            <add thumbprint="723C3A29732FC61F3BE96487E8560F749D1D8256" />
          </keys>
          <validIssuers>
            <add name="http://fs.server.com/adfs/services/trust" />
          </validIssuers>
        </authority>
      </issuerNameRegistry>
      <audienceUris>
        <add value="https://localhost/rp_poc" />
      </audienceUris>
    </identityConfiguration>
  </system.identityModel>
  <system.serviceModel>
    <bindings>
      <ws2007FederationHttpBinding>
        <binding>
          <security mode ="TransportWithMessageCredential">
            <message issuedKeyType ="BearerKey" establishSecurityContext="true">
              <issuer address ="https://fs.server.com/adfs/services/trust"
                      binding ="ws2007HttpBinding" />
            </message>
          </security>
        </binding>
      </ws2007FederationHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="DefaultBehaviour" >
          <serviceSecurityAudit auditLogLocation="Application" serviceAuthorizationAuditLevel="Failure" messageAuthenticationAuditLevel="Failure" suppressAuditFailure="true" />
          <serviceMetadata httpGetEnabled="true" />
          <serviceCredentials useIdentityConfiguration="true">
            <serviceCertificate findValue="74 0A FE 19 E9 F0 53 9C 46 D9 F2 D6 56 A7 0C E8" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySerialNumber">
            </serviceCertificate>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service name="POC.Security.ServiceClient.User" behaviorConfiguration="DefaultBehaviour" >
        <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
        <endpoint contract="POC.Security.ServiceClient.IUser" binding="ws2007FederationHttpBinding" address=""/>
      </service>
    </services>
    <diagnostics>
      <messageLogging maxMessagesToLog="25000" logEntireMessage="true"
                      logMessagesAtServiceLevel="false"
                      logMalformedMessages="true" logMessagesAtTransportLevel="true">
        <filters>
          <clear/>
        </filters>
      </messageLogging>
    </diagnostics>
  </system.serviceModel>
  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
          switchValue="Error, Warning, ActivityTracing" propagateActivity="true" >
        <listeners>
          <add name="xml" />
        </listeners>
      </source>
      <source name="System.ServiceModel.MessageLogging" switchValue="Error, Warning">
        <listeners>
          <add name="xml" />
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add name="xml" type="System.Diagnostics.XmlWriterTraceListener" initializeData="C:\Temp\ServicesLog.svclog" />
    </sharedListeners>
  </system.diagnostics>
</configuration>
4

1 回答 1

2

尝试将 serviceAuthorization 行为添加到您的 WCF 服务 - principalPermissionMode = always。

此外 - 如果您希望行为是“默认”的 - 您通常会删除 name 属性。否则,您必须从服务元素中显式引用它。

请参阅 http://leastprivilege.com/2012/11/16/wcf-and-identity-in-net-4-5-external-authentication-with-ws-trust/

于 2013-07-10T06:32:50.733 回答