[英]How to configure WCF BasicHttpBinding with Basic Authentication for usage in Adobe Flex?
I have a simple example web service that exposes two operations by ServiceContract and OperationContract, nothing fancy. 我有一个简单的示例Web服务,它公开了ServiceContract和OperationContract的两个操作,没有什么幻想。 This service should be consumed by an Adobe Flex 4 client.
该服务应由Adobe Flex 4客户端使用。 Unfortunately Flex can just handle SOAP 1.1 (and not SOAP 1.2), so I have to use the BasicHttpBinding on WCF side.
不幸的是, Flex只能处理SOAP 1.1 (而不是SOAP 1.2),因此我必须在WCF端使用BasicHttpBinding 。 To secure the access to the web service I've to use Basic Authentication, because it's the only authentication method both sides ( WCF and Flex ) understand.
为了保护对Web服务的访问,我必须使用基本身份验证,因为这是双方( WCF和Flex )都理解的唯一身份验证方法。 Basic Authentication goes along with SSL to encrypt the transport.
基本身份验证与SSL一起对传输进行加密。 I run the service in IIS Express with Visual Studio 2012.
我在带有Visual Studio 2012的IIS Express中运行该服务。
Web.config Web.config
<system.serviceModel>
<services>
<service name="UserAuthentication.AuthenticationService"
behaviorConfiguration="AuthenticationServiceBehavior">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="AuthenticationBinding"
contract="UserAuthentication.IAuthenticationService" />
<endpoint contract="IMetadataExchange"
binding="mexHttpBinding"
address="mex" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="AuthenticationBinding" maxReceivedMessageSize="65536">
<!-- Use SSL (Transport) and MessageCredential by Username (referencing behaviors/serviceBehaviors/behavior/serviceCredentials) -->
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None" />
<message clientCredentialType="UserName" />
</security>
<readerQuotas maxArrayLength="65536" maxBytesPerRead="65536" maxStringContentLength="65536"/>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="AuthenticationServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<!-- Use Custom DistributorValidator for Basic Authentication -->
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="UserAuthentication.DistributorValidator,UserAuthentication"/>
<!--<serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />-->
</serviceCredentials>
<!-- For Debug purpose: @see http://intrepiddeveloper.wordpress.com/2008/08/07/security-event-logging-auditing/ -->
<serviceSecurityAudit auditLogLocation="Application" serviceAuthorizationAuditLevel="Failure" messageAuthenticationAuditLevel="Failure" suppressAuditFailure="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
DistributedValidator.cs DistributedValidator.cs
Should be used to authenticate the user by username and password from Basic Authentication. 应该用于通过基本身份验证中的用户名和密码对用户进行身份验证。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
namespace UserAuthentication
{
public class DistributorValidator : UserNamePasswordValidator
{
/* Throw exeption to deny access for user */
public override void Validate(string userName, string password)
{
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
throw new SecurityTokenException("Username and password required");
if( userName.Equals("user") == false || password.Equals("secretpwd") == false)
throw new FaultException(string.Format("Wrong username ({0}) or password ", userName));
}
}
}
Start service with SSL in IIS Express 在IIS Express中使用SSL启动服务
Connect to web service as described in the Adobe documentation . 按照Adobe文档中的说明连接到Web服务。 This works fine so far and the service has been created in the Data/Services panel of the Flash Builder.
到目前为止,此方法运行良好,并且已在Flash Builder的“ 数据/服务”面板中创建了该服务 。
Test the web service through the Test Operation panel in the Flash Builder, the result is the HTML source code from https://localhost:44301/AuthenticationService.svc
and not an expected SOAP message. 通过Flash Builder中的“ 测试操作”面板测试Web服务,结果是来自
https://localhost:44301/AuthenticationService.svc
的HTML源代码,而不是预期的SOAP消息。
Trying the same web service and operation with the free version of SoapUI , the result is this SOAP envelope: 使用免费版本的SoapUI尝试相同的Web服务和操作,结果是此SOAP信封:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:InvalidSecurity</faultcode>
<faultstring xml:lang="de-AT">An error occurred when verifying security for the message.</faultstring>
</s:Fault>
</s:Body>
</s:Envelope>
In addition a MessageSecurityException is logged to the Windows Event Viewer : 另外,MessageSecurityException 记录到Windows事件查看器中 :
Message authentication failed.
Service: https://localhost:44301/AuthenticationService.svc
Action: http://tempuri.org/IAuthenticationService/GetData
ClientIdentity:
ActivityId: <null>
MessageSecurityException: Security processor was unable to find a security header in the message. This might be because the message is an unsecured fault or because there is a binding mismatch between the communicating parties. This can occur if the service is configured for security and the client is not using security.
In both cases (Flex and SoapUI) the custom DistributorValidator is never touched, so the problem is placed deeper in the magic of WCF. 在这两种情况(Flex和SoapUI)中,都从未触及自定义DistributorValidator,因此,将问题放在WCF的魔力中更为深刻。
Is there any possibility to run a WCF service with BasicHttpBinding and Basic Authentication that play nicely together with Adobe Flex? 有没有可能与Adobe Flex一起很好地运行带有BasicHttpBinding和Basic Authentication的WCF服务?
You need to mess with the headers to get basic HTTP auth to work with HTTPService. 您需要弄乱标题,以获取与HTTPService一起使用的基本HTTP身份验证。
It would look something like this when making the call from Flex... 从Flex拨打电话时看起来像这样...
var encoder:Base64Encoder = new Base64Encoder();
encoder.insertNewLines = false; // or else your header may fail...
encoder.encode("user_name:user_pass");
service.headers = {Authorization:"Basic " + encoder.toString()};
service.send(); //where servie is an instance of HTTPService
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.