所以我基本上已经通过HTTPS使用自定义身份验证了wsHttpBindings和我的WCF服务。
我遇到的问题是使用customUserNamePasswordValidatorType:
<serviceCredentials>
<!-- Use our own custom validation -->
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="CustomValidator.CustomUserNameValidator, CustomValidator"/>
</serviceCredentials>
发现以下指示here我也创建了自定义类:
namespace CustomValidator
{
public class CustomUserNameValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (null == userName || null == password)
{
throw new ArgumentNullException();
}
if (!AuthenticateUser(userName, password))
throw new SecurityTokenValidationException("Invalid Credentials");
错误是“无法加载文件或程序集'CustomValidator'或其依赖项之一。系统找不到指定的文件。”,并引用customUserNamePasswordValidatorType的尾端 - “。 ..,CustomValidator“。
我不认为在我自己的命名空间和类中使用自定义验证器是一个问题,但是我看不出还有什么可以使它工作。
我在开始时尝试使用/不使用命名空间,交换等等 - 没有。
希望另一双眼睛可以选择它。
感谢。
修改 system.serviceModel
<system.serviceModel>
<bindings>
<!-- wsHttpBinding -->
<wsHttpBinding>
<binding name="wsHttpEndpointBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
<!-- webHttpBinding -->
<webHttpBinding>
<binding name="wsHttps" >
<security mode="Transport"/>
</binding>
</webHttpBinding>
<!-- Basic binding -->
<basicHttpBinding>
<binding name="TransportSecurity">
<security mode="Transport">
<message clientCredentialType="UserName"/>
<!-- transport clientCredentialType="None"/-->
</security>
</binding>
</basicHttpBinding>
<!-- customBinding>
<binding name="WebHttpBinding_IService">
textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
messageVersion="Soap12" writeEncoding="utf-8">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</textMessageEncoding>
<httpsTransport manualAddressing="false"/>
</binding>
</customBinding -->
<!-- Another custom binding -->
<customBinding>
<binding name="CustomMapper">
<webMessageEncoding webContentTypeMapperType=
"IndexingService.CustomContentTypeMapper, IndexingService" />
<httpTransport manualAddressing="true" />
</binding>
</customBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
<services>
<service behaviorConfiguration="ServiceBehavior" name="Service">
<!-- Service Endpoints -->
<!-- since we're hosting in IIS, baseAddress is not required
<host>
<baseAddresses>
<add baseAddress="https://mysslserver.com/Service.svc"/>
</baseAddresses>
</host>
-->
<endpoint address="https://mysslserver.com/Service.svc"
binding="wsHttpBinding"
bindingConfiguration="wsHttpEndpointBinding"
contract="IService"
name="wsHttpEndpoint">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<!--identity>
<dns value="https://mysslserver.com"/>
</identity-->
</endpoint>
<!-- endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/ -->
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<!-- Setup Security/Error Auditing -->
<serviceSecurityAudit auditLogLocation="Application"
suppressAuditFailure="false"
serviceAuthorizationAuditLevel="Failure"
messageAuthenticationAuditLevel="Failure" />
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"
httpsGetUrl="https://mysslserver.com/Service.svc"/>
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceCredentials>
<!-- Use our own custom validation -->
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="CustomValidator.CustomUserNameValidator, CustomValidator"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
<!-- serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpsGetEnabled="true"
httpsGetUrl="https://mysslserver.com/Service.svc" />
To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior-->
</behaviors>
</system.serviceModel>
答案 0 :(得分:14)
我决定给它另一个刺,并且不喜欢在另一个lib中使用我的自定义验证器。
所以我在App_Code中创建了一个新类,然后继续...
以下是实际修复它的内容,
="CustomValidator.CustomUserNameValidator, App_Code"
答案 1 :(得分:9)
当您使用值
引用自定义验证程序时="CustomValidator.CustomUserNameValidator, CustomValidator"
第一个值是类型名称,第二个值是程序集的名称 在哪里找到类型。所以我建议你在第一时间 您的服务实际上是在其他程序集中,例如MyService 在这种情况下,您确实需要配置文件来说明
="CustomValidator.CustomUserNameValidator, MyService"
我怀疑你为自己创建了新的类库 验证器,你已经调用你的项目CustomValidator(将 输出一个名为CustomValidator.dll的程序集,因此现在你的 配置将起作用(即它与独立的无关 类库 - 它恰好发生在程序集的命名上 web.config中的引用现在有效)
答案 2 :(得分:2)
似乎有点奇怪,但解决方案是创建一个单独的类库,并在我的WCF服务中引用它的DLL。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.ServiceModel;
/// <summary>
/// Summary description for CustomUsernamePasswordValidator
/// </summary>
namespace CustomValidator
{
public class CustomUserNameValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (null == userName || null == password)
{
throw new ArgumentNullException();
}
if (!AuthenticateUser(userName, password))
throw new SecurityTokenValidationException("Invalid Credentials");
else
{
// do nothing - they're good
}
}
public bool AuthenticateUser(string userName, string password)
{
if (userName != "userbill" || password != "passwordbill")
{
return false;
}
else
{
return true;
}
}
}
}
然后我添加了对System.IdentityModel和System.ServiceModel的引用。
现在,WCF服务的serviceCredentials部分已更改为:
<serviceCredentials>
<!-- Use our own custom validation -->
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="CustomValidator.CustomUserNameValidator, CustomValidator"/>
</serviceCredentials>
希望能有所帮助。
我尝试使用无效凭据,并希望看到我的“无效凭据”消息。相反,我得到“消息中至少有一个安全令牌无法验证。”
除此之外,这件事终于开始运转了!
答案 3 :(得分:0)
只是阅读本文,因为它对POC有帮助我必须快速前进。为了回应上面的 ELHaix ...这应该可以确保您的描述性自定义错误返回给客户端:
using System.ServiceModel
...
throw new FaultException("Invalid Credentials - Custom Error");