简体   繁体   English

WCF身份验证-使用自定义验证程序的用户名密码-在我的机器上运行

[英]WCF Authentication - Username-Password using custom validator - Works on My Machine

I have a WCF service and a client, that uses a custom UserNamePasswordValidator for authentication. 我有一个WCF服务和一个客户端,该客户端使用自定义UserNamePasswordValidator进行身份验证。

I use a self-signed certificate, created by the following command line: 我使用由以下命令行创建的自签名证书:

makecert -sr LocalMachine -ss My -a sha1 -n CN=SelfSignedCertificate -sky exchange -pe

Calling methods in the service from the below client works fine on my machine :) But as soon as I deploy it to my server, I get this error message: The request for security token could not be satisfied because authentication failed. 从下面的客户端在服务中调用方法在我的机器上可以正常工作:)但是,一旦将其部署到服务器上,我就会收到此错误消息: The request for security token could not be satisfied because authentication failed.

I can browse the endpoint URL and see the WSDL for the service. 我可以浏览端点URL并查看该服务的WSDL。 I'm not sure, but I recall that I configured some Anonymous Authentication in IIS on my local machine, but it looks similar on the server as well. 我不确定,但是我记得我在本地计算机上的IIS中配置了一些匿名身份验证,但是在服务器上看起来也是如此。

My WCF service is hosted in IIS 7.0, using this configuration: 我的WCF服务使用以下配置托管在IIS 7.0中:

<system.serviceModel>
    <bindings>
        <wsHttpBinding>
            <binding name="secured">
                <security mode="Message">
                    <message clientCredentialType="UserName" />
                </security>
            </binding>
            <binding name="unsecured">
                <security mode="None" />
            </binding>
        </wsHttpBinding>
        <basicHttpBinding>
            <binding name="secured">
                <security mode="TransportWithMessageCredential">
                    <message clientCredentialType="UserName" />
                </security>
            </binding>
            <binding name="unsecured">
                <security mode="None" />
            </binding>
        </basicHttpBinding>
        <webHttpBinding>
            <binding name="unsecured">
                <security mode="None" />
            </binding>
        </webHttpBinding>
    </bindings>
    <services>
        <service name="Milkshake.Admin.Services.AdminService" behaviorConfiguration="CustomValidator">
            <endpoint address="" binding="wsHttpBinding" contract="Milkshake.Admin.Model.ServiceContracts.IAdminService" bindingConfiguration="secured" />
        </service>
        <service name="Milkshake.Admin.Services.DeploymentService">
            <endpoint address="" binding="wsHttpBinding" contract="Milkshake.Admin.Model.ServiceContracts.IDeploymentService"/>
        </service>
        <service name="Milkshake.Admin.Services.LogService" behaviorConfiguration="CustomValidator">
            <endpoint address="" binding="wsHttpBinding" contract="Milkshake.Core.Logging.ILogService" bindingConfiguration="secured" />
        </service>
        <service name="Milkshake.Admin.Services.MailService">
            <endpoint address="" binding="wsHttpBinding" contract="Milkshake.Admin.Model.ServiceContracts.IMailService"/>
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="CustomValidator">
                <serviceMetadata httpGetEnabled="true" />
                <serviceCredentials>
                    <serviceCertificate findValue="SelfSignedCertificate" x509FindType="FindBySubjectName" />
                    <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Milkshake.Admin.Services.MilkshakeCredentialValidator, Milkshake.Admin.Services" />
                    <clientCertificate>
                        <authentication certificateValidationMode="None" />
                    </clientCertificate>
                </serviceCredentials>
                <serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>

        <endpointBehaviors>
            <behavior name="json">
                <enableWebScript />
            </behavior>

            <behavior name="xml">
                <webHttp defaultOutgoingResponseFormat="Xml" defaultBodyStyle="Wrapped" />
            </behavior>
        </endpointBehaviors>
    </behaviors>
</system.serviceModel>

The client configuration looks like this: 客户端配置如下所示:

<system.serviceModel>
    <client>
        <endpoint address="http://server-url/LogService.svc" binding="wsHttpBinding" contract="Milkshake.Core.Logging.ILogService">
            <identity>
                <dns value="SelfSignedCertificate" />
            </identity>
        </endpoint>
    </client>
</system.serviceModel>

My custom validator is this: 我的自定义验证器是这样的:

using System;
using System.IdentityModel.Selectors;
using System.ServiceModel;

namespace Milkshake.Admin.Services
{
    /// <summary>
    /// WCF Service validator for Milkshake.
    /// </summary>
    public class MilkshakeCredentialValidator : UserNamePasswordValidator
    {
        /// <summary>
        /// When overridden in a derived class, validates the specified username and password.
        /// </summary>
        /// <param name="userName">The username to validate.</param>
        /// <param name="password">The password to validate.</param>
        public override void Validate(string userName, string password)
        {
            if (String.IsNullOrWhiteSpace(userName) || String.IsNullOrWhiteSpace(password))
            {
                throw new ArgumentNullException();
            }

            if (userName.Equals("martin") && password.Equals("normark"))
            {
                return;
            }

            FaultCode fc = new FaultCode("ValidationFailed");
            FaultReason fr = new FaultReason("Good reason");

            throw new FaultException(fr, fc);
        }
    }
}

My service client, looks like this: 我的服务客户端如下所示:

using System;
using System.ServiceModel;
using System.ServiceModel.Security;
using Milkshake.Core.Logging;

namespace Milkshake.Admin.ServiceClients.Logging
{
    /// <summary>
    /// WCF Service Client implementation of the <see cref="ILogService"/> contract.
    /// </summary>
    public class LogServiceClient : ILogService
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="LogServiceClient"/> class.
        /// </summary>
        public LogServiceClient()
        {
            var factory = new ChannelFactory<ILogService>(String.Empty);
            factory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
            factory.Credentials.UserName.UserName = "martin";
            factory.Credentials.UserName.Password = "normark";

            var binding = factory.Endpoint.Binding as WSHttpBinding;

            if (binding != null)
            {
                binding.Security.Mode = SecurityMode.Message;
                binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
            }

            this.AdminLogService = factory.CreateChannel();
        }

        /// <summary>
        /// Gets or sets the admin log service.
        /// </summary>
        /// <value>The admin log service.</value>
        private ILogService AdminLogService { get; set; }

        #region ILogService Members

        /// <summary>
        /// Logs the error simple.
        /// </summary>
        /// <param name="applicationInstanceId">The application instance id.</param>
        /// <param name="logDate">The log date.</param>
        /// <param name="exceptionMessage">The exception message.</param>
        /// <param name="description">The description.</param>
        /// <param name="severity">The severity.</param>
        /// <param name="userAgent">The user agent.</param>
        /// <param name="source">The source.</param>
        public void LogErrorSimple(int applicationInstanceId, DateTime logDate, string exceptionMessage, string description, Severity severity, string userAgent, string source)
        {
            this.AdminLogService.LogErrorSimple(applicationInstanceId, logDate, exceptionMessage, description, severity, userAgent, source);
        }

        /// <summary>
        /// Logs the error advanced.
        /// </summary>
        /// <param name="applicationInstanceId">The application instance id.</param>
        /// <param name="logDate">The log date.</param>
        /// <param name="exceptionType">Type of the exception.</param>
        /// <param name="exceptionCode">The exception code.</param>
        /// <param name="exceptionMessage">The exception message.</param>
        /// <param name="stackTrace">The stack trace.</param>
        /// <param name="caller">The caller.</param>
        /// <param name="location">The location.</param>
        /// <param name="source">The source (A service, app etc).</param>
        /// <param name="description">The description.</param>
        /// <param name="severity">The severity.</param>
        /// <param name="username">The username.</param>
        /// <param name="userAgent">The user agent.</param>
        public void LogErrorAdvanced(int applicationInstanceId, DateTime logDate, string exceptionType, string exceptionCode, string exceptionMessage, string stackTrace, string caller, string location, string source, string description, Severity severity, string username, string userAgent)
        {
            this.AdminLogService.LogErrorAdvanced(applicationInstanceId, logDate, exceptionType, exceptionCode, exceptionMessage, stackTrace, caller, location, source, description, severity, userAgent, userAgent);
        }

        /// <summary>
        /// Logs the behavior with data.
        /// </summary>
        /// <param name="applicationInstanceId">The application instance id.</param>
        /// <param name="action">The action.</param>
        /// <param name="logDate">The log date.</param>
        /// <param name="userAgent">The user agent.</param>
        /// <param name="behaviorData">The behavior data.</param>
        /// <param name="source">The source.</param>
        public void LogBehaviorWithData(int applicationInstanceId, string action, DateTime logDate, string userAgent, string behaviorData, string source)
        {
            this.AdminLogService.LogBehaviorWithData(applicationInstanceId, action, logDate, userAgent, behaviorData, source);
        }

        /// <summary>
        /// Logs the behavior.
        /// </summary>
        /// <param name="applicationInstanceId">The application instance id.</param>
        /// <param name="action">The action.</param>
        /// <param name="logDate">The log date.</param>
        /// <param name="userAgent">The user agent.</param>
        /// <param name="source">The source.</param>
        public void LogBehavior(int applicationInstanceId, string action, DateTime logDate, string userAgent, string source)
        {
            this.AdminLogService.LogBehavior(applicationInstanceId, action, logDate, userAgent, source);
        }

        #endregion
    }
}

I also use the UserNamePasswordValidator with certificates generated using makecert. 我还将UserNamePasswordValidator与使用makecert生成的证书一起使用。

Instead of using IIS, use WcfSvcHost so you can be sure it starts successfully. 可以使用WcfSvcHost而不是IIS,以确保它可以成功启动。 The reason I'm suggesting this is that possibly Chain building for the certificate is failing. 我建议这样做的原因是证书的链构建可能失败。 There is a setting you can use to disable chain building. 您可以使用一个设置来禁用链构建。 ( Update: I think you're doing that already with CertificateValidationMode="none") 更新:我认为您已经使用CertificateValidationMode =“ none”进行了此操作)

Another thing I'm noticing is that not all your service definitions specify behaviourConfiguration. 我要注意的另一件事是,并非您的所有服务定义都指定了behaviourConfiguration。 This is a little beech to find because it gets removed sometimes by VS when you update your service references. 这有点像山毛榉,因为在更新服务引用时,有时VS会将其删除。

The exception you mention, is that the message from the inner most exception? 您提到的异常是最内部异常的消息吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 WCF身份验证自定义用户名和密码验证程序,适用于多个用 - WCF authentication custom username and password validator for multiple users 使用存储库数据库的WCF自定义用户名和密码验证程序c# - WCF Custom Username and Password Validator using a Repository Database c# WCF 和自定义身份验证(用户名/密码) - WCF and custom Authentication (username/password) 安全的wcf(使用使用者名称密码验证器)无法从php用户端运作 - Secure wcf (using username password validator) not working from php client 具有SSL和用户名和密码身份验证的自主WCF服务 - Selfhosted WCF Service with SSL and Username and Password authentication 使用Windows用户名/密码的简单WCF身份验证 - Simple WCF Authentication with windows username/password WCF双工服务忽略自定义用户名身份验证 - WCF duplex service is ignoring custom username authentication 在WCF中使用Windows身份验证类型时,是否以纯文本格式发送用户名和密码? - Are username and password sent in plain text when using windows authentication type in WCF? WCF UserName身份验证:我可以在自定义ServiceAuthorizationManager中获取用户名吗? - WCF UserName Authentication: Can I get the Username in a custom ServiceAuthorizationManager? 使用wshttpbinding的WCF用户名和密码验证不起作用 - WCF UserName & Password validation using wshttpbinding notworking
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM