在 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 的 App.config 中使用 Windows 角色身份验证
使用 Windows 身份验证的 IIS 托管 WCF 服务和 SQL 查询
SharePoint 2010 自定义 WCF 服务 - Windows 和 FBA 身份验证