WCF的基本身份验证

时间:2013-11-27 16:24:38

标签: c# .net wcf

我正在尝试使用wcf进行非常基本但安全的用户名/密码身份验证。

但是,当我查看ServiceSecurityContext.Current.PrimaryIdentity;的值时,它包含我的Windows机器的凭据并声称它已获得授权(即使我尚未进行任何授权),而不是我提供给的用户名和密码服务。

我的服务的web.config如下

<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5"/>
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" 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"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <wsHttpBinding>
        <binding name="WsHttpBindingConfig">
          <security mode="TransportWithMessageCredential">
            <transport clientCredentialType="None" />
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>

    </bindings>
    <protocolMapping>
        <add binding="wsHttpBinding" scheme="http" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>

</configuration>

,客户端应用程序的app.config如下

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IService1" />
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost/WcfSecuredService/Service1.svc"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"
                contract="ServiceReference1.IService1" name="WSHttpBinding_IService1">
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

我使用以下代码调用服务

ServiceReference1.Service1Client clnt = new ServiceReference1.Service1Client();
            clnt.ClientCredentials.UserName.UserName = "peter";
            clnt.ClientCredentials.UserName.Password = "grr";

            string result=clnt.GetSecuredData();

我做错了什么?

请注意,客户端应用和服务都在同一台计算机上运行。我不知道身份是运行服务的机器的身份还是从客户端传递给它的机器,因为它们都是相同的凭证......

我想另一个问题可能是“如何获取传递给服务的用户名和密码?”

3 个答案:

答案 0 :(得分:5)

我现在已经解决了这个问题

我需要创建一个自定义验证类,我在此处How to: Use a Custom User Name and Password Validator

我还需要对web.config进行一些更改

<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5"/>
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WcfService1Secure.Auth,WcfService1Secure" />
          </serviceCredentials>
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" 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"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <wsHttpBinding>
        <binding name="WsHttpBindingConfig">
          <security mode="TransportWithMessageCredential">
            <transport clientCredentialType="None" />
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>

    </bindings>
    <protocolMapping>
        <add binding="wsHttpBinding" scheme="https" bindingConfiguration="WsHttpBindingConfig" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>

</configuration>

和app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>

    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IService1" />
            </basicHttpBinding>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IService1">
                    <security mode="TransportWithMessageCredential">
                        <transport clientCredentialType="None" />
                        <message clientCredentialType="UserName" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="https://localhost/WcfService1Secure/Service1.svc"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"
                contract="ServiceReference1.IService1" name="WSHttpBinding_IService1" />
        </client>
    </system.serviceModel>
</configuration>

现在,用户已根据请求进行了验证,并且使用

可以使用用户名
  

ServiceSecurityContext.Current.PrimaryIdentity;

答案 1 :(得分:2)

您应该添加一个方法,可以接受服务器端的登录名和密码,并将它们存储在变量或数据库中 你的方法应该是这样的

ServiceReference1.Service1Client clnt = new ServiceReference1.Service1Client();
clnt.ClientCredentials.UserName.UserName = "peter";
clnt.ClientCredentials.UserName.Password = "grr";

clnt.SignUp(clnt);  

clnt.SignUp(login,password); 

您正在做的事情可以在独立应用程序上运行,但不能在网络摄像头中运行 您对方法服务的调用将具有类似

的内容
  

http://MyService/IMyContract/MyAction1

希望这个帮助

答案 2 :(得分:1)

如果您正在使用PerSession实例,那么您可以先在服务器上调用Authenticate,并在成功维护服务器上的标志后,后续调用将在执行前检查该标志。这意味着客户端需要首先调用Authenticate方法,然后才调用其他方法。

如果不使用PerSession实例,您可以为服务器创建自己的代理类,并且在创建代理实例时接受可以在每次调用的头文件中传递的LoginName / Password,并且在服务器端实现自定义ServiceAuthorizationManager,它可以从OperationContext检索凭证。 Current.IncomingMessageHeaders并验证它。