【问题标题】:WCF security, username password without certificateWCF安全,用户名密码无证书
【发布时间】:2011-09-28 21:54:17
【问题描述】:

我是 WCF 的新手。我习惯了 *.asmx 但它会被弃用,所以我决定深入研究 WCF。我想为我的服务提供一个简单的用户名 + 密码身份验证,但在网络上到处都是关于 X509 证书的。我想在 IIS 中托管我的服务,因此我将在其中启用 SSL

我关注了一些关于 WCF 的 hello world 教程,但对所有新事物、datacontract、OperationContract、ServiceContract、所需接口、web.config 中的所有绑定、basicHttpBinding 等感到有些困惑。

我目前在File -> New project -> Visual C# -> WCF -> WCF Service Application

我有一个 hello world 应用程序,想知道保护它的最佳和最简单的方法是什么。我读过很多不同的东西,以至于我不知道什么是最适合我的情况。

托管在 IIS 中的服务将在互联网上可用(启用 ssl),并且我想将用户名和密码发送给几个受信任的人。

请为我提供最简单和合适的安全建议。

编辑 我正在尝试关注这篇博文: http://codebetter.com/petervanooijen/2010/03/22/a-simple-wcf-service-with-username-password-authentication-the-things-they-don-t-tell-you/ 但我无法发布元数据。我假设我的web.config 中有错误

<system.serviceModel>
    <services>
        <service behaviorConfiguration="WcfServiceSimStars.MyServiceTypeBehaviors" name="FarmService.CustomerDeskOperations">
            <endpoint address="" binding="wsHttpBinding" bindingConfiguration="RequestUserName" contract="WcfServiceSimStars.ISimService" />
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> 
        </service>
    </services>
    <bindings>
        <wsHttpBinding>
            <binding name="RequestUserName" >
                <security mode="Message">
                    <message clientCredentialType="UserName"/>
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://mytestserver/simservice.svc" binding="WSHttpBinding"
            bindingConfiguration="WSHttpBinding_ISimService" contract="WcfServiceSimStars.ISimService"
            name="WSHttpBinding_ISimService" />
    </client>
    <behaviors>
        <serviceBehaviors>
            <behavior name="WcfServiceSimStars.MyServiceTypeBehaviors">
                <serviceMetadata httpGetEnabled="true"/>
                <serviceCredentials>
                    <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WcfServiceSimStars.UserValidatorr, WcfServiceSimStars" />
                    <serviceCertificate findValue="Farm" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName" />
                </serviceCredentials>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

和我的解决方案浏览器:

编辑 2: 我尝试使用 Visual Studio 工具菜单中的 Microsoft Service Configuration Editor 打开我的 web.config 并收到此错误:

【问题讨论】:

  • 如果你使用 ssl,你的 mexHttpBinding 需要是 mexHttpsBinding
  • 我还没有在 IIS 中启用 SSL。想在没有 SSL 的情况下进行测试
  • 好的,您在尝试发布元数据时遇到什么错误?
  • 表示此服务的元数据发布已禁用
  • 您的绑定称为 RequestUserName,但在您的端点中您引用的是 wshttpbinding_ISimService。端点中的绑定配置应与您提供的绑定名称匹配。

标签: wcf iis-7.5 wcf-binding wcf-security


【解决方案1】:

如果您想使用 SSL,则需要使用 X509 证书。

如果您要将其托管在 IIS 上并在那里启用 SSL,则需要提供证书,出于调试目的,您可以在 IIS 中生成自签名证书。

在 IIS 中进行设置后,您需要编辑 WCF 绑定以启用 SSL。

您将需要与安全模式传输集的绑定

<basicHttpBinding>
    <binding name="SecureBinding" receiveTimeout="01:00:00">
      <security mode="Transport" />
    </binding>
</basicHttpBinding>

和一个安全的行为,以下指定将使用的 ssl 证书。

<behaviors>
  <serviceBehaviors>
    <behavior name="SecureBehavior">
      <serviceMetadata />
      <serviceCredentials>
        <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
      </serviceCredentials>
    </behavior>
    <behavior name="StandardBehavior">
    </behavior>
  </serviceBehaviors>
</behaviors>

然后您需要创建一个安全端点

<services>
  <service behaviorConfiguration="SecureBehavior" name="secureService">
    <endpoint address="" binding="basicHttpBinding" bindingConfiguration="SecureBinding" contract="<Your webservice class name including namespace>" />
    <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
  </service>

这应该使您能够在托管网站后在您的网站上使用 SSL。

要从您的客户端连接,您将使用以下内容(假设为 C#)

BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.Transport;
EndPointAddress endpointAddress = new EndpointAddress("Your Service address (including HTTPS)");
Client svc = new Client(binding,endpointAddress)

另一种方法是使用加密而不是 SSL。在客户端加密密码并将加密数据发送到服务,但我不确定这样做的最佳实践。

希望对你有帮助

编辑

如果你想向服务发送用户名和密码,你只需要在服务中创建一个新方法。

您将在接口文件 (IService1.cs) 中定义操作协定

[OperationContract]
bool Login(string password,string username);

然后您将在服务类 (Service1.svc) 中创建方法

public bool Login(string password,string username)
{
    //Your Code to check the username and password here
}

这可能是最简单的方法。另一种更复杂的方法是使用自定义成员资格提供程序来验证用户。

您需要创建一个继承自 MembershipProvider 的类并覆盖 ValidateUser 方法

public class SampleMembershipProvider : MembershipProvider
{ 
    public override bool ValidateUser(string username, string password)
    {
        //check the username and password here
    }


    //No need to override the other methods just leave them
    ....
}

现在您需要告诉 webconfig 使用表单身份验证并使用您的自定义成员资格提供程序

<authentication mode="Forms" />
<membership defaultProvider="CustomMembershipProvider">
  <providers>
    <clear />
    <add name="CustomMembershipProvider" type="SampleApplication.CustomMembershipProvider" />
  </providers>
</membership>

现在您已经设置了您的会员提供商,您可以将您的登录代码从上面更改为以下代码,此代码将对用户进行身份验证并设置授权 cookie。

public bool Login(string password,string username)
{
    if (Membership.ValidateUser(username, password))
    {
        FormsAuthentication.SetAuthCookie(username, false);
        return true;
    }
    return false;
}

现在,当您在服务上调用方法时,您可以检查用户是否已通过身份验证,如果是,您可以运行命令,否则不运行。

bool DoWork()
{
    if (HttpContext.Current.User.Identity.IsAuthenticated)
    {
         //do something
         return true;
    }
    else
    {
        return false;
    }
}

如果您需要我澄清任何事情,请告诉我

【讨论】:

  • 好的,我应该如何让服务接受用户名+密码?
  • 感谢@midimatt 的所有努力!将开始使用这个:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-03
  • 2012-01-22
  • 1970-01-01
  • 2010-10-21
  • 2013-06-25
  • 2011-05-28
相关资源
最近更新 更多