我一直在跟随这个教程(链接)来实现我的WCF服务中的用户名认证和传输安全。但是该教程使用的是不可接受的
我的想法是在WCF服务中创建一个自定义的
我通过自定义行为实现了
顺便说一下,如果我使用IIS中内置的Basic身份验证模块而不是自定义模块,则在尝试
我愿意听取建议以及解决该问题的替代方法。谢谢。 更新 似乎在WCF服务代码后面正确读取了HTTP头。
经过一番研究,我得出结论,当Web浏览器收到HTTP状态码401时,它会向我呈现登录对话框,我可以在其中指定我的凭据。但是,WCF客户端仅引发异常,不想发送凭据。当在Internet Explorer中访问
basicHttpBinding
,我需要使用wsHttpBinding
。我的想法是在WCF服务中创建一个自定义的
BasicAuthenticationModule
,它将从HTTP请求中读取“Authorization”头并根据其内容执行身份验证过程。问题是,“Authorization”头丢失了!我通过自定义行为实现了
IClientMessageInspector
以操作输出消息并添加自定义SOAP头。我在BeforeSendRequest
函数中添加了以下代码: HttpRequestMessageProperty httpRequest = request.Properties.Where(x => x.Key == "httpRequest").Single().Value;
httpRequest.Headers.Add("CustomHeader", "CustomValue");
这应该可以行得通,根据许多网络资源的说法,它适用于basicHttpBinding
,但不适用于wsHttpBinding
。当我说“有效”时,我的意思是标题已成功被WCF服务接收。
这是检查WCF服务端接收到的HTTP消息的简化函数:
public void OnAuthenticateRequest(object source, EventArgs eventArgs)
{
HttpApplication app = (HttpApplication)source;
//the Authorization header is checked if present
string authHeader = app.Request.Headers["Authorization"];
if (string.IsNullOrEmpty(authHeader))
{
app.Response.StatusCode = 401;
app.Response.End();
}
}
此帖底部的文章显示,使用wsHttpBinding
不可能实现。我不想接受这个答复。顺便说一下,如果我使用IIS中内置的Basic身份验证模块而不是自定义模块,则在尝试
Roles.IsInRole("RoleName")
或`[PrincipalPermission(SecurityAction.Demand, Role = "RoleName")]`时会收到错误消息“参数'username'不能包含逗号。”,这可能是因为我的PrimaryIdentity.Name
属性包含证书主题名称,因为我正在使用基于证书的消息安全性的TransportWithMessageCredential
安全性。我愿意听取建议以及解决该问题的替代方法。谢谢。 更新 似乎在WCF服务代码后面正确读取了HTTP头。
(HttpRequestMessageProperty)OperationContext.Current.IncomingMessageProperties["httpRequest"]
包含我的自定义标头。但是,这已经是消息级别...如何将标头传递给传输认证例程?
更新2经过一番研究,我得出结论,当Web浏览器收到HTTP状态码401时,它会向我呈现登录对话框,我可以在其中指定我的凭据。但是,WCF客户端仅引发异常,不想发送凭据。当在Internet Explorer中访问
https://myserver/myservice/service.svc
时,我能够验证此行为。尝试使用此链接中的信息进行修复,但无济于事。这是WCF中的一个错误还是我遗漏了什么?
编辑
以下是我的system.servicemodel
(来自web.config
)的相关部分——我非常确定我已经正确配置了它。 <serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="ChainTrust" revocationMode="NoCheck" />
</clientCertificate>
<serviceCertificate findValue="server.uprava.djurkovic-co.me" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" />
</serviceCredentials>
<serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="AspNetSqlRoleProvider" />
</behavior>
</serviceBehaviors>
................
<wsHttpBinding>
<binding name="EndPointWSHTTP" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="20480000" maxReceivedMessageSize="20480000" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="20480000" maxStringContentLength="20480000" maxArrayLength="20480000" maxBytesPerRead="20480000" maxNameTableCharCount="20480000" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic" />
<message clientCredentialType="Certificate" negotiateServiceCredential="true" algorithmSuite="Default" />
</security>
</binding>
</wsHttpBinding>
............
<service behaviorConfiguration="ServiceBehavior" name="DjurkovicService.Djurkovic">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="EndPointWSHTTP" name="EndPointWSHTTP" contract="DjurkovicService.IDjurkovic" />
</service>
服务返回的异常是:
HTTP 请求未经授权,客户端身份验证方案为“匿名”。从服务器接收的身份验证标头为“Basic Realm,Negotiate,NTLM”。(远程服务器返回错误:(401) 未授权。)