简体   繁体   English

WCF的基本身份验证

[英]Basic Authentication for WCF

I am trying to do a very basic but secure username/password authentication with wcf. 我正在尝试使用wcf进行非常基本但安全的用户名/密码身份验证。

However when I look at the value of the ServiceSecurityContext.Current.PrimaryIdentity; 但是,当我查看ServiceSecurityContext.Current.PrimaryIdentity;的值时ServiceSecurityContext.Current.PrimaryIdentity; it contains the credentials of my windows machine and claims it is authorised (even though I have not yet done any authorisation) instead of the username and password I provided to the service. 它包含我的Windows机器的凭据并声称它已被授权(即使我还没有完成任何授权),而不是我提供给服务的用户名和密码。

My web.config of the service is as follows 我的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>

and the app.config of the client app is as follows 并且客户端应用程序的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>

I call the service with the following code 我使用以下代码调用该服务

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

            string result=clnt.GetSecuredData();

What am I doing wrong? 我究竟做错了什么?

Please note that both the client app and the service are both running on the same machine. 请注意,客户端应用程序和服务都在同一台计算机上运行。 I do not know if the identity is that of the machine running the service or the one passed to it from the client as they are both the same credentials..... 我不知道身份是运行服务的机器的身份还是从客户端传递给它的机器,因为它们都是相同的凭证.....

I suppose the other question is possibly "How do I get the username and password that were passed to the service?" 我想另一个问题可能是“如何获取传递给服务的用户名和密码?”

I have worked this out now 我现在已经解决了这个问题

I needed to create a custom validation class which I found here How to: Use a Custom User Name and Password Validator 我需要创建一个自定义验证类,我在这里找到如何:使用自定义用户名和密码验证器

I also needed to make a few changes to the web.config 我还需要对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>

and the app.config 和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>

Now the user is validated on the request and the username is available using 现在,用户已根据请求进行了验证,并且可以使用用户名

ServiceSecurityContext.Current.PrimaryIdentity; ServiceSecurityContext.Current.PrimaryIdentity;

hi you should add a method that can accept login and password on your server side and store them in a variables or db 您好,您应该添加一个方法,可以接受服务器端的登录名和密码,并将它们存储在变量或数据库中
your method should look like this 你的方法应该是这样的

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

clnt.SignUp(clnt);  

or 要么

clnt.SignUp(login,password); 

what you are doing can work on a standalone application but not in a webcall your call to method service will have something like 你正在做什么可以在一个独立的应用程序上工作,但不是在一个网络摄像头,你对方法服务的调用会有类似的东西

http://MyService/IMyContract/MyAction1 HTTP://为MyService / IMyContract / MyAction1

Hope this help 希望这有帮助

If you are using PerSession instance then you can call first Authenticate on server and on successful maintain a flag on server, subsequent call will check for the flag before executing. 如果您正在使用PerSession实例,那么您可以在服务器上首先调用Authenticate,并在成功维护服务器上的标志后,后续调用将在执行前检查该标志。 that means client need to make first call to Authenticate method and then only call other methods. 这意味着客户端需要首先调用Authenticate方法然后只调用其他方法。

If not using PerSession instance you can create own proxy class for the server and while creating proxy instance accept LoginName/Password which it can pass in header on each call and on server side implement custom ServiceAuthorizationManager, it can retrieve credential from OperationContext.Current.IncomingMessageHeaders and validates it. 如果不使用PerSession实例,您可以为服务器创建自己的代理类,并且在创建代理实例时接受可以在每次调用的头文件中传递的LoginName / Password,在服务器端实现自定义ServiceAuthorizationManager,它可以从OperationContext.Current.IncomingMessageHeaders中检索凭证。并验证它。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM