使用ASP.NET Ajax通过SSL调用WCF

使用ASP.NET Ajax通过SSL调用WCF,wcf,asp.net-ajax,web-config,forms-authentication,Wcf,Asp.net Ajax,Web Config,Forms Authentication,我正在使用ASP.NET Ajax从ASP.NET页面调用WCF。我正在使用表单身份验证来保护网站 在开发过程中,一切都按照预期工作,直到它被部署到生产服务器上,然后我开始出现JavaScript错误,因为找不到该服务。生产服务器正在使用SSL,因此我在web.config中添加了以下内容: 我的应用程序中使用的代码\u AuthenticateRequest: protected void Application_AuthenticateRequest(object sender, Event

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

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

我的应用程序中使用的代码\u 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);
}

简单地将安全性从None更改为Transport不应该影响通过Authenticate\u请求运行的应用程序。您可能应该将调试器附加到服务实现,并查看HttpContext.Current.User是什么。它是您的自定义主体还是未设置?您可能还需要添加几个Debug.Write消息,并查看操作顺序。验证请求事件是否在您预期之后发生

如果在配置中使用
,则可能会遇到-此设置似乎与安全传输不兼容,WCF会覆盖主体。如果您正在设置主体,则似乎需要对其使用
principalPermissionMode=“None”

确保您仍然通过配置(
)或通过服务属性(
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Required)]在服务上启用了。否则,服务将无法访问HttpContext.Current

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

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
来连接dispatcher

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上下文对话。使测试变得更容易,并且可以完全解决问题-每当服务收到消息时,它都会自动将主体传输到服务器上,而不是依赖于服务的构造

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.
}
public class HttpContextPrincipalElement : BehaviorExtensionElement
{
  public override Type BehaviorType
  {
    get { return typeof(HttpContextPrincipalBehavior); }
  }

  protected override object CreateBehavior()
  {
    return new HttpContextPrincipalBehavior();
  }
}