【问题标题】:Using ASP.NET Ajax to call WCF over SSL使用 ASP.NET Ajax 通过 SSL 调用 WCF
【发布时间】:2009-01-23 05:35:56
【问题描述】:

我正在使用 ASP.NET Ajax 从 ASP.NET 页面调用 WCF。我正在使用表单身份验证来保护网站。

在开发过程中一切都按预期工作,直到它被部署到生产服务器上,然后我开始收到 JavaScript 错误,因为找不到服务。生产服务器使用 SSL,所以我在 web.config 中添加了以下内容:

<webHttpBinding>
    <binding name="webBinding">
    <security mode="Transport" />
    </binding>
</webHttpBinding>

这阻止了 JavaScript 错误的发生,但现在 WCF 服务的行为不再像以前那样。

在将安全设置为传输之前,从 ASP.NET Ajax 调用 WCF 服务将在我的 Global.asax 中执行 Application_AuthenticateRequest。这将根据表单身份验证票在HttpContext.Current.User 上设置自定义IPrinciple。我的 WCF 服务的构造函数设置为 Thread.CurrentPrinciple = HttpContext.Current.User,因此我的服务可以访问在 Application_AuthenticateRequest 期间设置的 IPrinciple

将安全性更改为 Transport 后,它似乎没有通过 Application_AuthenticateRequest 运行,因为我的 Thread.CurrentPrinciple 不是我的自定义 IPrinciple

有谁知道我如何才能获得与使用 Transport 之前和使用 Transport 之后相同的行为?

我的网页使用以下内容来引用 WCF 服务:

<asp:ScriptManagerProxy ID="ScriptManagerProxy1" runat="
    <Services>
        <asp:ServiceReference Path="~/Services/MyService.svc" />
    </Services>
</asp:ScriptManagerProxy>

我的Application_AuthenticateRequest中使用的代码:

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    String cookieName = FormsAuthentication.FormsCookieName;
    HttpCookie authCookie = Context.Request.Cookies[cookieName];

    if (authCookie == null)
    {
        return;
    }

    FormsAuthenticationTicket authTicket = null;
    try
    {
        authTicket = FormsAuthentication.Decrypt(authCookie.Value);
    }
    catch
    {
        return;
    }

    if (authTicket == null)
    {
        return;
    }

    HttpContext.Current.User = new CustomPrinciple(authTicket.Name);
}

【问题讨论】:

    标签: wcf asp.net-ajax web-config forms-authentication


    【解决方案1】:

    只需将安全性从 None 更改为 Transport 不会影响通过 Authenticate_Request 运行的应用程序。您可能应该将调试器附加到服务实现并查看 HttpContext.Current.User 是什么。是您的自定义主体还是未设置?您可能还想在其中添加一些 Debug.Write 消息,看看操作的顺序是什么。 Authenticate_Request 事件是否在您预期之后发生?

    如果您在配置中使用&lt;serviceAuthorization principalPermissionMode="UseAspNetRoles" /&gt;,您可能会遇到this issue from MS Connect - 此设置似乎与安全传输不兼容,并且 WCF 会覆盖主体。如果您正在设置主体,您似乎需要使用principalPermissionMode="None"

    确保您仍然通过配置 (&lt;serviceHostingEnvironment aspNetCompatibilityEnabled="true" /&gt;) 或通过服务上的属性 ([AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]) 在服务上启用 ASP.NET Compatibility Mode。否则,服务将无法访问 HttpContext.Current。

    此外,不要在服务实现构造函数中获取 HttpContext.Current.User,而是尝试将其移动到附加到服务的行为中。实现处理AfterReceiveRequest 事件并将主体从Web 上下文传输到线程的IDispatchMessageInspector。它看起来像这样:

    public class HttpContextPrincipalInspector : IDispatchMessageInspector
    {
      public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
      {
        if (HttpContext.Current != null)
        {
          IPrincipal principal = HttpContext.Current.User;
          Thread.CurrentPrincipal = principal;
        }
        return null;
      }
    
      public void BeforeSendReply(ref Message reply, object correlationState) { }
    }
    

    当然,实现IEndpointBehavior 来附加调度程序...

    public class HttpContextPrincipalBehavior : IEndpointBehavior
    {
      public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
      {
        ChannelDispatcher channelDispatcher = endpointDispatcher.ChannelDispatcher;
        foreach (EndpointDispatcher endpointDispatch in channelDispatcher.Endpoints)
        {
          endpointDispatch.DispatchRuntime.MessageInspectors.Add(new HttpContextPrincipalInspector());
        }
      }
    
      // AddBindingParameters, ApplyClientBehavior, and Validate implementations
      // can be empty - they don't do anything.
    }
    

    ...和一个自定义 BehaviorExtensionElement,以便您可以在 WCF 配置中使用它:

    public class HttpContextPrincipalElement : BehaviorExtensionElement
    {
      public override Type BehaviorType
      {
        get { return typeof(HttpContextPrincipalBehavior); }
      }
    
      protected override object CreateBehavior()
      {
        return new HttpContextPrincipalBehavior();
      }
    }
    

    然后,您可以将任何服务配置为将其用作端点行为,这样服务实现就不会直接与 Web 上下文对话。使测试更容易一些,并且可以完全解决问题 - 任何时候收到服务的消息,它都会自动转移主体,而不是依赖于服务的构建。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-18
      • 2015-11-28
      • 1970-01-01
      • 1970-01-01
      • 2011-07-08
      • 2013-07-01
      • 2014-04-30
      • 2018-06-24
      相关资源
      最近更新 更多