将ADFS令牌从客户端发送到WCF服务

时间:2011-09-07 10:34:21

标签: .net silverlight wcf azure adfs2.0

我有一个要求,我的Silverlight应用程序需要通过中间WCF服务连接到WCF服务以获取数据,该服务与Silverlight位于同一域中。也就是说,Silverlight将调用中间服务,中间服务将IssuedToken与请求一起附加并将其发送到主WCF客户端。主WCF服务将从Thread.Principal检索声明。

    var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
    binding.Security.Message.EstablishSecurityContext = false;

    var factory = new ChannelFactory<IMyService>(binding, new EndpointAddress("https://myservice.cloudapp.net:4432/MyService.svc"));
    var channel = factory.CreateChannelActingAs(((ClaimsIdentity)((ClaimsPrincipal)HttpContext.Current.User).Identity).BootstrapToken);

    var data = channel.GetData();

但是这段代码失败了。我无法找到有关如何实现此目标的属性文档。任何人都可以帮助我。

谢谢,

1 个答案:

答案 0 :(得分:1)

你需要: 1.在ADFS STS服务对面进行身份验证以获取SecurityToken 2.使用“CreateChannelWithIssuedToken”使用频道查询您的服务,内容如下:

        var token = GetToken();

        string uri = SERVICE_URL;

        EndpointAddress address = new EndpointAddress(uri);

        var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
        binding.Security.Message.EstablishSecurityContext = false;

        _factory = new ChannelFactory<IService>(binding, address);
        _factory.ConfigureChannelFactory<IService>();
        _factory.Credentials.SupportInteractive = false;

        _service = _factory.CreateChannelWithIssuedToken<IService>(token);

GetToken的代码如下所示:

    public static SecurityToken GetToken(string username, string password, EndpointAddress federationServiceProxyAddress, EndpointAddress relyingPartyIdentifier)
    {
        var binding = new UserNameWSTrustBinding
        {
            SecurityMode = SecurityMode.TransportWithMessageCredential
        };

        var factory = new WSTrustChannelFactory(binding, federationServiceProxyAddress)
        {
            TrustVersion = System.ServiceModel.Security.TrustVersion.WSTrust13,
        };

        factory.Credentials.SupportInteractive = false;
        factory.Credentials.UserName.UserName = username;
        factory.Credentials.UserName.Password = password;

        try
        {
            var requestSecurityToken = new RequestSecurityToken
            {
                RequestType = WSTrust13Constants.RequestTypes.Issue,
                AppliesTo = relyingPartyIdentifier
            };

            var channel = factory.CreateChannel();
            return channel.Issue(requestSecurityToken);//, out requestSecurityTokenResponse);
        }
        catch (MessageSecurityException exception)
        {
            // Invalid username or password
            throw new MessageSecurityException(exception.Message, exception);
        }
        catch (Exception exception)
        {
            // Unknown error
            throw new Exception(exception.Message, exception);
        }
        finally
        {
            try
            {
                if (factory.State == CommunicationState.Faulted)
                {
                    factory.Abort();
                }
                else
                {
                    factory.Close();
                }
            }
            catch (Exception) { }
        }
    }

希望这会有所帮助......