简体   繁体   中英

WCF on IIS 7.0 Service Security Configuration Issue using Basic Authentication

I have spend the last couple of days trying to solve an issue when hosting a WCF service in SQL 2008 Server and IIS 7.0.

This problem only occurs when I have anonymous authentication disabled and using Basic Authentication over SSL as shown in the web.config extract below

<security mode="Transport">
    <transport clientCredentialType="Basic" />
</security>

Basically when i try to access MeterReadingService.svc file I get an IIS error saying it cannot find the resource \\Account\\Login. It seems I am being redirected to a login page. Forms authentication is not enabled on IIS

Details of Error:

HTTP Error 404.0 - Not Found The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.

Detailed Error Information Module IIS Web Core Notification MapRequestHandler Handler StaticFile Error Code 0x80070002 Requested URL https://localhost:9011/FrontEndWS/Account/Login?ReturnUrl=%2fFrontEndWS%2fMeterReadingService.svc

Physical Path D:\\WebApplications\\MeterReaderPortal\\FrontEndWS\\Account\\Login Logon Method Basic Logon User Administrator

Can you indicate any pointers why this is happening or how can i log the cause of this error?

What authentication mode do you have configured under system.web in your web.config?

From the error message you've posted, I'll assume that it's Forms .

To use Basic authentication with Windows passwords, System.Web.Authentication needs to look like this:

<system.web>
  <authentication mode="Windows" />
</system.web>

..and binding.security like this:

<security mode="Transport">
  <transport clientCredentialType="Basic" />
</security>

I want the client (which is a asp.net site) calls a wcf. Both are hosted in IIS7 in my laptop. For WCF i have enabled Basic authenticatin in IIS7 and disbaled all other things. For the client i have enabled basic authentication and disabled all other options in authentication.

The problem is that with these configs below the client is not getting any data back from the wcf.

If i in the browser navigate to the service by providing the url to the service then i have to enter username/passsword in the form that pops up.

What i wan to do is to secure my wcf by username and password so that any one who wants to call my wcf have to provide username/pass and my wcf code check wether that exist (for instance in AD) and authenticates accordingly.

my Client(simple ASP.net web site calling a WCF) web.config:

<configuration>
<appSettings>
<add key="userName" value="Administrator"/>
<add key="password" value="pass"/>
<!--<add key="url" value="http://localhost:57895/ListData.svc"/>-->
<!--http://localhost/WCF/-->    
<add key="url" value="http://localhost:8082/ListData.svc"/>
</appSettings>
<system.web>
  <compilation debug="true" targetFramework="4.0" />
</system.web>
<system.webServer>
  <directoryBrowse enabled="true"/>
</system.webServer>
</configuration>

My WCF service web.config:

<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="Logging" value="true"/>
</appSettings>
<connectionStrings/>
<system.web>
<authentication mode="Windows"></authentication>
<compilation debug="true" />
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
</system.web>
<system.serviceModel>
<bindings>
  <basicHttpBinding>
    <binding name="httpBinding">
      <security mode="TransportCredentialOnly">
        <transport clientCredentialType="Basic" />
      </security>
    </binding>
  </basicHttpBinding>
  <!--<webHttpBinding>
    <binding name="webHttpTransportSecurity">
      <security mode="Transport">
        <transport clientCredentialType="Basic"/>
      </security>
    </binding>
  </webHttpBinding>-->
</bindings>
<services>
  <service behaviorConfiguration="SecureRESTSvcTestBehavior" name="Hdir.ListData">
    <!--<host>
      <baseAddresses>
        <add baseAddress="http://localhost:57895/ListData/"/>
      </baseAddresses>
    </host>-->
    <!--webHttpBinding allows exposing service methods in a RESTful manner-->
    <endpoint address="" binding="basicHttpBinding" bindingConfiguration="httpBinding"      behaviorConfiguration="webHttpBehavior" contract="Hdir.IListData"/>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <!--<behavior name=" ">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="false" />
    </behavior>-->
    <behavior name="SecureRESTSvcTestBehavior">
      <!-- To avoid disclosing metadata information, set the value below to 
           false and remove the metadata endpoint above before deployment -->
      <serviceMetadata httpGetEnabled="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="false"/>
      <serviceAuthorization serviceAuthorizationManagerType="Hdir.CustomAuthorizationManager, Hdir"/>
      <!--<serviceCredentials>
        <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Hdir.Hp.Data.CustomUserNameValidator, Hdir.Hp.Data" />
      </serviceCredentials>-->
    </behavior>
  </serviceBehaviors>
  <endpointBehaviors>
    <behavior name="webHttpBehavior">
      <!--<webHttp/>-->
    </behavior>
  </endpointBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<directoryBrowse enabled="true"/>
<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*"/>
    <add name="Access-Control-Allow-Headers" value="x-requested-with"/>
    <add name="Access-Control-Request-Method" value="GET"/>
  </customHeaders>
</httpProtocol>
</system.webServer>
</configuration>

I dont know what

<authentication mode="Windows" /> does. 

I have jsut added it there. I dont know if that is correct to do or not. AS i mentioned; What i wan to do is to secure my wcf by username and password so that any one (form anywhere uwing internet) who wants to call my wcf have to provide username/pass and my wcf code check wether that exist (for instance in AD) and authenticates accordingly. I dont know what type of binding to use wether using wshttpbinding, webhttpbinding or basichttpbinding. In the class CustomAuthorizationManager that you see in the config file, i have a override method called

protected override bool CheckAccessCore(OperationContext operationContext)
    {
        //Extract the Authorization header, and parse out the credentials converting the Base64 string:
        var authHeader = WebOperationContext.Current.IncomingRequest.Headers["Authorization"];
        if ((authHeader != null) && (authHeader != string.Empty))
        {                                                      

my problem with this is that is is being called twice, the first time is there are headers and the code can validate the header, but the sencond time the header is null. Anyonw who knows why is that?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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