使用webHttpBinding

时间:2015-12-27 11:38:14

标签: wcf authentication iis

我将在WCF中实现基本身份验证。我在所有这些内容中都很新,我的程序基于这一系列文章http://leastprivilege.com/2008/01/11/http-basic-authentication-against-non-windows-accounts-in-iisasp-net-part-0-intro/我使用webHttpBinding并启用了HTTPS。

所以主要思想是以这种方式实现IHttpModule:

  1. 当用户请求某个资源时,模块会检查是否存在Authorization标头。
  2. 如果存在授权,模块将提取标题的值,解码并检查登录并传递
  3. 在另一种情况下,模块发送一个带有401代码和标题的响应" WWW-Authenticate"。
  4. 这是我对模块的实现:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Management;
    using System.Text;
    
    namespace MyProj_A
    {
        public class MyHTTPModule : IHttpModule
        {
    
            void IHttpModule.Dispose()
            {
            }
    
            void IHttpModule.Init(HttpApplication context)
            {
                context.BeginRequest += Context_BeginRequest;
                context.AuthenticateRequest += OnEnter;
                context.EndRequest += OnLeave;
            }
    
    
            private void Context_BeginRequest(object sender, EventArgs e)
            {
                HttpContext context = HttpContext.Current;
                context.Response.Write("BeginRequest");
            }
    
            void OnEnter(object sender, EventArgs e)
            {
                HttpContext context = HttpContext.Current;
                if (IsHeaderPresent())
                {
                    if (!AuthenticateUser())
                    {
                        DenyAccess();
                    }
                }
                else
                {
                    // if anonymous requests are not allowed - end the request
                    DenyAccess();
                }
            }
    
            bool IsHeaderPresent()
            {
                return HttpContext.Current.Request.Headers["Authorization"] != null;
            }
    
            bool AuthenticateUser()
            {
                string username = "", password = "";
                string authHeader = HttpContext.Current.Request.Headers["Authorization"];
                if (authHeader != null && authHeader.StartsWith("Basic"))
                {
                    // extract credentials from header
                    string[] credentials = ExtractCredentials(authHeader);
                    username = credentials[0];
                    password = credentials[1];
                    if (username.CompareTo("tikskit") == 0 && password.CompareTo("") == 0)
                    {
                        return true;
                    } else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
    
    
            private static void DenyAccess()
            {
                HttpContext context = HttpContext.Current;
    
                context.Response.StatusCode = 401;
                context.Response.End();
            }
    
            void OnLeave(object sender, EventArgs e)
            {
                // check if module is enabled
                if (HttpContext.Current.Response.StatusCode == 401)
                {
                    SendAuthenticationHeader();
                }
            }
    
            private void SendAuthenticationHeader()
            {
                HttpContext context = HttpContext.Current;
    
                context.Response.StatusCode = 401;
                context.Response.AddHeader(
                    "WWW-Authenticate",
                    "Basic realm=\"yo-ho-ho\""
                    );
    
            }
        }
    
    }
    

    我在远程计算机上的IIS 7.5下发布它,并使用Visual Studio中的远程调试器连接到它。我在Context_BeginRequest,OnEnter和OnLeave上设置了断点。

    然后我使用URL从浏览器访问我的WCF,这是发生的事情:

    1. 输入URL后按下Enter Context_BeginRequest被解雇
    2. 在VS中我可以看到授权标题不存在
    3. OnEnter被触发,最终将401代码分配给响应
    4. 也执行OnLeave并将WWW-Authenticate设置为响应头
    5. 在浏览器中显示标准登录对话框
    6. 我输入了用户名和密码,然后按确定
    7. 现在再次触发Context_BeginRequest,我可以看到授权标题存在,并且包含一个类似" Basic"的值,这是正确的
    8. 此时并未执行OnEnter
    9. OnLeave被解雇,但由于某种原因,HttpContext.Current.Response.StatusCode的值为401
    10. 这是我的Web.config

      <?xml version="1.0"?>
      <configuration>
      
        <appSettings>
          <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
        </appSettings>
        <system.web>
          <compilation debug="true" targetFramework="4.5.2" />
          <httpRuntime targetFramework="4.5.2"/>
          <customErrors mode="Off" />
        </system.web>
      
      
        <system.serviceModel>
          <behaviors>
      
            <endpointBehaviors>
              <behavior name="webBehavior">
                <webHttp automaticFormatSelectionEnabled="false"/>
              </behavior>
            </endpointBehaviors>
      
             <serviceBehaviors>
              <behavior name="Default" >
                <serviceMetadata httpGetEnabled="false" />
                <serviceMetadata httpsGetEnabled="false"/>
                <serviceAuthenticationManager authenticationSchemes="Basic"/>
                <serviceCredentials>
                </serviceCredentials>
      
              </behavior>
            </serviceBehaviors>
      
          </behaviors>
      
          <bindings>      
            <webHttpBinding>
              <binding name="MyBinding">
                <security mode="TransportCredentialOnly">
                  <transport clientCredentialType="Basic"/>
                </security>
              </binding>
            </webHttpBinding>
          </bindings>
      
          <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
      
          <services>
            <service name="MyProj_A.Service1">
              <endpoint address="" binding="webHttpBinding" contract="MyProj_A.IService1"
                        behaviorConfiguration="webBehavior"/>
              <host>
                <baseAddresses>
                  <add baseAddress="http://localhost/" />
                </baseAddresses>
              </host>
            </service>
          </services>
          <diagnostics>
            <endToEndTracing activityTracing="false" messageFlowTracing="true" propagateActivity="true"></endToEndTracing>
          </diagnostics>
        </system.serviceModel>
      
        <system.webServer>
          <modules runAllManagedModulesForAllRequests="true">
            <add name="MyHTTPModule"
              type="MyProj_A.MyHTTPModule,MyProj-A"/>
          </modules>
      
          <directoryBrowse enabled="false"/>
        </system.webServer>
      
      </configuration>
      

      所以我的问题是 1.为什么OnEnter第二次没有被激发,8,如何在第9项中分配401? 2.如何解决此问题,我的意思是我是否需要将所有身份验证处理从AuthenticateRequest(OnLeave)移至BeginRequest(Context_BeginRequest)?或者也许这样的处理有更好的地方?

      谢谢!

1 个答案:

答案 0 :(得分:0)

案件已关闭

我忘记在端点配置中引用绑定配置:

<endpoint address="" binding="webHttpBinding"
  contract="MyProj_A.IService1" 
  behaviorConfiguration="webBehavior" 
  **bindingConfiguration="MyBinding"**/>