在 WCF 和 Windows 身份验证中处理 CORS

Posted

技术标签:

【中文标题】在 WCF 和 Windows 身份验证中处理 CORS【英文标题】:Handle CORS within WCF and Windows authentication 【发布时间】:2018-12-13 22:01:27 【问题描述】:

我已经实现了一个自托管的 WCF 休息服务和一个相应的 Angular CLI 客户端。我遇到了CORS 的麻烦,但是当HttpClientCredentialType.None 设置在WebHttpBinding 中时,我能够解决它们。 问题是,我需要使用HttpClientCredentialType.Windows,因为我必须知道使用系统的 Windows 用户的身份。 这是使用的绑定:

new WebHttpBinding

    MaxBufferSize = int.MaxValue,
    MaxBufferPoolSize = 524288,
    MaxReceivedMessageSize = int.MaxValue,                
    OpenTimeout = TimeSpan.FromMinutes(1),
    SendTimeout = TimeSpan.FromMinutes(1),
    ReceiveTimeout = TimeSpan.FromMinutes(10),
    CloseTimeout = TimeSpan.FromMinutes(1),
    ReaderQuotas =
    
        MaxStringContentLength = int.MaxValue,
        MaxArrayLength = int.MaxValue,
        MaxDepth = int.MaxValue,
        MaxNameTableCharCount = int.MaxValue
    ,
    Security =
    
        Mode = WebHttpSecurityMode.Transport,
        Transport =  ClientCredentialType = HttpClientCredentialType.Windows 
        //Transport =  ClientCredentialType = HttpClientCredentialType.None
    
;

但现在 CORS-Options 调用被 HttpStatus 401 Unauthorized 拒绝,因为其中没有身份验证标头。因此,整个调用都被拒绝(什么是正确的......理论上)。

当然,我已经添加了所有必要的标题。如前所述,它适用于None 身份验证。

WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "http://localhost:4200");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept, Id, Origin, Authorization");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Credentials", "true");

所以我看到了解决我的问题的三种可能性。

    以某种方式在我的Angular 客户端中调用 CORS-Options 以传递我的 Windows 凭据。 让 WCF 服务忽略 CORS-Options 调用中的身份验证。 将授权设置回无并以其他方式传递我的 Windows 凭据(不强制用户输入他的凭据)。

当我在Chrome Browser 中使用--disable-web-security 时,它甚至也适用于Windows 身份验证。但对我来说,这不是生产系统的解决方案。

也许有人对我的问题有任何想法甚至解决方案。

【问题讨论】:

你需要做#2。服务器不得要求对 CORS 预检 OPTIONS 请求进行身份验证。如果是这样,那么预检将始终在浏览器中失败——因为 CORS 规范禁止浏览器在预检 OPTIONS 请求中发送身份验证凭据。而#1 是不可能的——因为发送预检 OPTIONS 请求的不是 Angular 客户端代码;相反,浏览器本身会自动发送 OPTIONS 请求。而且它从不发送身份验证凭据作为该请求的一部分。 @sideshowbarker 谢谢,你是绝对正确的。但是如何告诉 wcf 服务忽略预检请求呢? 【参考方案1】:

这里的选项是使用Microsoft.AspNet.WebApi.Cors。

我使用 Web Api 遇到了这个问题,并发现这个解决方案(nuget 包)也适用于 WCF。

你需要在你的类上面使用这个装饰器:

[EnableCors(origins: "http://example.com", headers: "*", methods: "*")]

然后在你的方法上方添加装饰器:

[AcceptVerbs("POST")]

这将忽略飞行前请求,只会发送您的实际请求。

编辑

在看了你的代码之后,我明白了这个问题:你需要一个额外的参数:

var cors = new EnableCorsAttribute("http://IP:PORT", "*", "*")  SupportsCredentials = true ;
config.EnableCors(cors); 

asp.net forums 有一篇很棒的帖子也可以帮助您解决问题。

应要求

这是 wcf 中 HttpConfiguration 的 workaround。

【讨论】:

删除之前的尝试后,我将包和您的代码添加到我的 Service 类中,但仍然获得带有 Windows 身份验证的 401。如果它在您的项目中有效,也许您可​​以更明确地指定您的步骤? 如果 'config' 是 HttpConfiguration:这就是 WebApi 服务的配置。这与 WCF 无关。或者您可以告诉我如何使用 HttpConfiguration 配置我的 WCF,那么当然所有问题都解决了!但我现在看不到隧道尽头的光 ;-) 有一个使用令牌的解决方法,链接已附加:)【参考方案2】:

你不能只添加一个 global.asax 并添加一个 Access-Control-Allow-Origin Header

protected void Application_BeginRequest(object sender, EventArgs e)

    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://YourDomain");
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE");

        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
        HttpContext.Current.Response.End();
    

【讨论】:

标题不是问题。问题是 Windows 身份验证与预检请求相结合。使用 Windows 身份验证,请求甚至不会开始。 欧比你试过这个吗? If 语句处理选项应该处理预检

以上是关于在 WCF 和 Windows 身份验证中处理 CORS的主要内容,如果未能解决你的问题,请参考以下文章

带有身份验证的 WCF 流式处理

在带有 WCF 的 App.config 中使用 Windows 角色身份验证

使用 Windows 身份验证的 IIS 托管 WCF 服务和 SQL 查询

SharePoint 2010 自定义 WCF 服务 - Windows 和 FBA 身份验证

使用 RESTful WCF 和 Windows 窗体的用户/通过身份验证

WCF - Windows 身份验证 - 安全设置需要匿名