【问题标题】:Handling REST SWT tokens in WCF WIF pipeline is not working在 WCF WIF 管道中处理 REST SWT 令牌不起作用
【发布时间】:2013-02-13 23:57:42
【问题描述】:

我在主题行中提到的设置上苦苦挣扎,想知道是否有人可以帮助我。

本质上,我拥有的是 WCF 服务,我想实现用户可以使用自定义登录页面对 ACS 进行身份验证(使用带有 ACS 所需信息的 javascript)。

完成此操作后,用户应使用提供的 SWT 令牌重定向到 WCF 服务。我使用 SimpleWebTokenHandler 作为 SWT 令牌处理的基础,但我不确定它在其中扮演什么角色。

这是我正在运行的 Web.config

<configuration>
    <configSections>
        <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, Version=4.0.0.0, Culture=neutral" />
    </configSections>
    ...
    <system.serviceModel>
        <diagnostics>
        </diagnostics>
        <services>
            <service name="WcfWifSwtAcs.Service1">
                <endpoint address="xmlService" binding="webHttpBinding" bindingConfiguration="" behaviorConfiguration="restPoxBehaviour" name="xmlServiceEndpoint" contract="WcfWifSwtAcs.IService1" />
            </service>
        </services>
        <behaviors>
            <endpointBehaviors>
                <behavior name="restPoxBehaviour">
                    <webHttp helpEnabled="true" />
                </behavior>
            </endpointBehaviors>
            <serviceBehaviors>
                <behavior>
                    <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                    <serviceCredentials useIdentityConfiguration="true">
                        ...
                    </serviceCredentials>
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <protocolMapping>
            <add scheme="http" binding="ws2007FederationHttpBinding" />
        </protocolMapping>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
        <bindings>
            <ws2007FederationHttpBinding>
                <binding name="">
                    <security mode="Message">
                        <message 
                            issuedTokenType="http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0">
                            <issuerMetadata address="https://xxxx.accesscontrol.windows.net/v2/wstrust/13/certificate/mex" />
                        </message>
                    </security>
                </binding>
            </ws2007FederationHttpBinding>
        </bindings>
    </system.serviceModel>
    <system.webServer>
    ...
    </system.webServer>
    <system.identityModel>
        <identityConfiguration>
            <audienceUris>
                <add value="http://localhost:56782/Service1.svc" />
            </audienceUris>
            <issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
                <trustedIssuers>
                    <add thumbprint="XXX" name="xxx.accesscontrol.windows.net" />
                </trustedIssuers>
            </issuerNameRegistry>
        <issuerTokenResolver type="SimpleWebToken.CustomIssuerTokenResolver, WcfWifSwtAcs" />
            <securityTokenHandlers>
                <clear/>
                <add type="SimpleWebToken.SimpleWebTokenHandler, WcfWifSwtAcs"/>
            </securityTokenHandlers>
        </identityConfiguration>
    </system.identityModel>
</configuration>

现在我可以看到,身份验证发生并且浏览器被重定向到服务主体。我还可以看到 SimpleWebToken 处理程序已实例化,并且正在请求令牌类型 URI。但这几乎就是所有发生的事情。没有实际的令牌处理验证,并且正在发生任何事情。

这是发送到服务的令牌(解析后)。

wa=wsignin1.0&
wresult=
<t:RequestSecurityTokenResponse 
xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<t:Lifetime>
    <wsu:Created 
        xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2013-02-13T23:14:30.159Z</wsu:Created>
    <wsu:Expires
        xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2013-02-13T23:24:30.159Z</wsu:Expires>
</t:Lifetime>
<wsp:AppliesTo 
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
    <EndpointReference
        xmlns="http://www.w3.org/2005/08/addressing">
        <Address>http://localhost:56782/Service1.svc</Address>
    </EndpointReference>
</wsp:AppliesTo>
<t:RequestedSecurityToken>
    <wsse:BinarySecurityToken 
        wsu:Id="uuid:58e2fb15-dd1a-40bd-8ff0-ae24e22e6efe" 
        ValueType="http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0"
        EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
        xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"          xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
        BASE64 DATA==
    </wsse:BinarySecurityToken>
</t:RequestedSecurityToken>
<t:TokenType>http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0</t:TokenType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>
</t:RequestSecurityTokenResponse>

服务本身非常简单,带有以下签名。

[OperationContract]
[WebInvoke(UriTemplate = "/GetData/{id}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
string GetData(string id);

有什么想法吗?我一直在验证 uri、主机名、指纹等是否都有效。此外,服务跟踪并没有真正显示与令牌处理或令牌验证中的异常相关的任何内容。

不知何故,令牌似乎甚至没有传递给处理程序。至少缺少所有声明和其他身份验证信息(null)。

如果有人指出我可以在哪里调试或者我遗漏了一些非常明显的东西(可能总是这样),我将不胜感激。

附:我知道我可以使用自定义身份验证模块来实现它,无论如何,我宁愿让它与 WIF 一起运行(它变得越来越重要,因为我已经花了更多时间在这上面,因为我真的很想要,而且我很固执:p)。

【问题讨论】:

  • 你从哪里得到你正在使用的 SimpleWebTokenHandler?请记住,当 ACS 通过 XML 协议(如 WS-Trust)发出 SWT 时,它会将其包装在 元素中,您使用的令牌处理程序必须了解该元素。如果我不得不猜测,您使用的处理程序不会将其识别为 SWT。
  • 嗨,我一直在使用这里的示例 code.msdn.microsoft.com/vstudio/Custom-Token-ddce2f55 现在有趣的部分是实际用于将令牌内容与令牌处理程序进行比较的 URI 是什么返回。 t:TokenType 和 ValueType 都会让我认为它是 schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0 ,我正在使用它。我也无法获得任何与令牌相关的跟踪或调试:(

标签: wcf rest azure wif acs


【解决方案1】:

Soo,奉献精神会带来解决方案。虽然我最初认为这不能做到,但很明显它实际上可以。我会把解决方案放在这里,因为也许其他人觉得它有用。

首先,WCF REST 服务使用webHttpBinding,根据 MS 文档,它不支持 Windows Identity Foundation 和管道中的声明处理。实际上确实如此。不在 WCF 管道中,而是作为 Web 身份验证流程中的 IIS 模块。

首先,您需要将以下模块添加到 Web.config 文件中。

<system.webServer>
    <modules runManagedModulesForAllRequests="true">
        <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>

有一个警告。你仍然需要我原始帖子中的&lt;configSections&gt;。问题是您需要在 VisualStudio 中将 System.IdentyModel* 程序集标记为 CopyLocal 项(在属性窗口中)。否则,您将得到一些无法为配置部分加载程序集的神秘异常。注意!仅当您正在加载这两个模块时才会发生这种情况,并且不会在未加载这些模块时发生。没有进一步调查那件事的意愿,也许有人知道那里的原因是什么。

接下来,如果您出于任何原因计划使用 MS WIF 代码中的 SWT 令牌处理示例,则需要修复一些错误,否则令牌解析将不会发生,或者您将获得无效签名令牌验证。

SimpleWebToken.cs 您需要修复 SwtBaseTime,因为它初始化不正确,之后安全令牌创建失败:

从 public static DateTime SwtBaseTime = new DateTime( 1970, 1, 1, 0, 0, 0, 0 ); // 每 SWT psec 到

public static DateTime SwtBaseTime = new DateTime( 1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc ); // per SWT psec

SimpleWebTokenHandler.cs需要修正以下值的大小写:

来自

const string BinarySecurityToken = "binarySecurityToken";
const string ValueType = "valueType";

const string BinarySecurityToken = "BinarySecurityToken";
const string ValueType = "ValueType";

CustomIssuerTokenResolver.cs 您需要修复使用 UTF8 字节初始化时创建的密钥,但实际上应该使用解码后的 Base64 字节进行初始化:

来自

key = new InMemorySymmetricSecurityKey(UTF8Encoding.UTF8.FromBase64String(base64Key));

key = new InMemorySymmetricSecurityKey(System.Convert.FromBase64String(base64Key));

在您解决所有这些问题后,一切都已就位。验证器和授权器被调用,瞧,突然你有一个 WCF 服务公开为 REST 端点,所有声明等也都在工作。

【讨论】:

    【解决方案2】:

    我认为您的问题可能与此示例中的 SWTTokenHandler 相关:http://code.msdn.microsoft.com/vstudio/Custom-Token-ddce2f55

    在 CanReadToken() 中,它检查令牌是否为 SWT 类型的 BinarySecurityToken:

    if ( reader.IsStartElement( BinarySecurityToken )
    && ( reader.GetAttribute( ValueType ) == SimpleWebTokenConstants.ValueTypeUri ) )
    

    但常量 BinarySecurityToken 定义为:

    const string BinarySecurityToken = "binarySecurityToken";
    

    注意小写的“b”。 XML 元素区分大小写,实际元素是带有大写 B 的“BinarySecurityToken”。这将导致处理程序在 CanReadToken() 中返回 false,从而导致 WIF 认为它没有为此令牌类型注册的处理程序。

    【讨论】:

    • 实际上,CanReadToken 甚至没有被调用。这是我的问题。我基本上断点了 SWT 处理程序中的所有函数,我可以看到构造函数、令牌类型请求和令牌类型 URI 请求被调用。所以我在想我没有做对的管道部分是什么。请求进入 - 检查,令牌处理管道初始化 - 检查,令牌验证 - 不发生,调用授权和身份验证组件 - 检查,调用 wcf 函数 - 检查。
    猜你喜欢
    • 2012-02-14
    • 2011-07-12
    • 1970-01-01
    • 2011-10-17
    • 1970-01-01
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多