在WCF中处理REST SWT令牌WIF管道不起作用

时间:2013-02-13 23:57:42

标签: wcf rest azure wif acs

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

基本上,我所拥有的是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)。

如果有人指出我可以在哪里调试,或者我错过了一些非常明显的事情(也可能总是如此),我将不胜感激。

P.S。我知道我可以使用自定义身份验证模块实现它,无论如何,我宁愿让它与WIF一起运行(因为我花了更多的时间在这上面,因为我真的很想要而且我非常顽固:p)。< / p>

2 个答案:

答案 0 :(得分: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>

有一个警告。您仍然需要我原始发布的<configSections>。问题是,在VisualStudio中,您需要将System.IdentyModel*程序集标记为 CopyLocal 项(在属性窗口中)。否则,你会得到一些神秘的例外,即无法为配置部分加载程序集。 NB!只有在加载这两个模块时才会发生这种情况,而在没有加载这些模块时则不会发生这种情况。没有任何意愿进一步调查这件事,也许有人知道那里的原因是什么。

接下来,如果由于任何原因您计划使用来自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端点,并且所有声明等也正在运行。

答案 1 :(得分:0)

我认为您的问题可能出在此示例中的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认为它没有为此标记类型注册的处理程序。 / p>