![](/img/trans.png)
[英]“An error occurred when verifying security for the message” exception when authenticating to ADFS
[英]WCF Authentication - An error occurred when verifying security for the message
我在使用clientCredentialType="UserName"
连接到我的 WCF 服务时遇到问题。
当我运行下面的代码时,出现错误
FaultException: 验证消息的安全性时出错。
在使用一些绑定值时,我也得到Access is denied.
.
Fiddler 说没有授权标头,我也无法在请求中找到用户名或密码。
以下是我的配置的摘录:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<services>
<service name="InventoryServices.MobileAPI" behaviorConfiguration="customBehaviour">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding"
contract="InventoryServices.IMobileAPI"/>
<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="customBehaviour">
<serviceSecurityAudit auditLogLocation="Application" serviceAuthorizationAuditLevel="Failure" messageAuthenticationAuditLevel="Failure" suppressAuditFailure="true" />
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpsGetEnabled="true"/>
<!-- 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"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="InventoryLibrary.Helpers.UserAuthentication,InventoryLibrary"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic" proxyCredentialType="Basic" realm="MyRealm"/>
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
我的用户名/密码验证器如下所示:
public class UserAuthentication : UserNamePasswordValidator {
public override void Validate(string userName, string password) {
EntitiesContext db = new EntitiesContext();
db.Logs.Add(new DomainModels.Log() {
DateLogged = DateTime.Now,
Message = "hit auth",
Type = DomainModels.LogType.Info
});
db.SaveChanges();
try {
if (userName == "test" && password == "test123") {
Console.WriteLine("Authentic User");
}
}
catch (Exception ex) {
throw new FaultException("Unknown Username or Incorrect Password");
}
}
}
我将此作为对我的服务的简单测试:
[OperationContract]
[XmlSerializerFormat]
void Test();
[PrincipalPermission(SecurityAction.Demand, Name = "test")]
public void Test() {
}
我的服务器上有一个自签名 SSL 证书,我可以访问我的服务/元数据。
然后我在控制台应用程序中添加了一个服务引用,并尝试使用以下代码连接到服务:
class Program {
static void Main(string[] args) {
Stuff.InitiateSSLTrust();
BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.Security.Transport.Realm = "MyRealm";
ServiceReference1.MobileAPIClient serviceProxy = new ServiceReference1.MobileAPIClient(binding, new EndpointAddress("https://xx.xx.xx.xx/InventoryServices.MobileApi.svc"));
serviceProxy.ClientCredentials.UserName.UserName = "test";
serviceProxy.ClientCredentials.UserName.Password = "test123";
try {
var a = serviceProxy.Login("a", "b");
}
catch (Exception ex) {
var ex2 = ex;
}
}
}
public class Stuff {
public static void InitiateSSLTrust() {
try {
//Change SSL checks so that all checks pass
ServicePointManager.ServerCertificateValidationCallback =
new RemoteCertificateValidationCallback(
delegate { return true; }
);
}
catch (Exception ex) {
}
}
}
我检查了服务器上的事件查看器,每个请求都会出现此错误:
MessageSecurityException:安全处理器无法在消息中找到安全标头。 这可能是因为消息是不安全的错误,或者因为通信双方之间存在绑定不匹配。 如果服务配置为安全并且客户端未使用安全,则可能发生这种情况。
您指定客户端使用BasicHttpSecurityMode.Transport
而服务需要BasicHttpSecurityMode.TransportWithMessageCredential
。 这是一个问题,因为服务正在 SOAP 消息头中查找客户端凭据,并且客户端不会使用以这种方式配置的绑定发送它们。
因此,这就是您所看到的消息头中不存在用户名/密码对的原因。 所以事件查看器是正确的,通信方之间存在绑定不匹配。
ClientCredentialType
客户端上的ClientCredentialType
设置为BasicHttpMessageCredentialType.UserName
以实现Message
级别的安全性。 默认情况下BasicHttpBinding
使用None
,它们是匿名客户端。
这是描述上述更改的代码片段:
var basicHttpBinding = new BasicHttpBinding(
BasicHttpSecurityMode.TransportWithMessageCredential);
basicHttpBinding.Security.Message.ClientCredentialType =
BasicHttpMessageCredentialType.UserName;
这也可能是由于客户端和服务器之间的时间不同步造成的。 如果证书或签名令牌基于时间无效,则An error occurred when verifying security for the message.
相同An error occurred when verifying security for the message.
消息可能会被退回。
添加服务引用后只需编辑 .csproj 文件并将这些依赖项从 4.4.* 指向 4.6.*
<ItemGroup> <PackageReference Include="System.ServiceModel.Duplex" Version="4.6.*" />
<PackageReference Include="System.ServiceModel.Http" Version="4.6.*" />
<PackageReference Include="System.ServiceModel.NetTcp" Version="4.6.*" />
<PackageReference Include="System.ServiceModel.Security" Version="4.6.*" />
</ItemGroup>
并添加这个
binding.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.TransportWithMessageCredential;
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.