我一直想弄清楚在为需要Windows身份验证的MS Web API制作XHR时我缺少的是什么。
此请求适用于Chrome和IE 11本地以及远程控制台(不是服务器)上的Chrome。问题是远程盒子上的IE 11。
根据开发工具,IE发出3个请求。前两个请求通过授权:Negotiate标头并返回401s(CORS的预检?)。但是,第三个返回400.它似乎无法以我不理解的方式进行身份验证,特别是因为其他浏览器和本地测试都有效。
API是一个自托管的OWIN控制台应用程序。这是创业公司:
public void Configuration(IAppBuilder appBuilder)
{
appBuilder.UseCors(CorsOptions.AllowAll);
var listener = (HttpListener)appBuilder.Properties["System.Net.HttpListener"];
if (listener != null)
{
listener.AuthenticationSchemeSelectorDelegate = request =>
{
if (string.Compare(request.HttpMethod, "OPTIONS", StringComparison.OrdinalIgnoreCase) == 0)
{
return AuthenticationSchemes.Anonymous;
}
else
{
return AuthenticationSchemes.IntegratedWindowsAuthentication;
}
};
}
var config = new HttpConfiguration();
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });
appBuilder.UseWebApi(config);
}
这是客户端XHR调用:
var request = new XMLHttpRequest();
request.open('GET', 'http://xxxx:9000/api/test/something', true);
request.timeout = 10000;
request.withCredentials = true;
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
console.log('done');
} else {
console.error('error');
}
};
request.onerror = function() {
// There was a connection error of some sort
};
request.send();
API控制器:
[Authorize]
[RoutePrefix("api/test")]
public class TestController : ApiController
{
[HttpGet]
[ActionName("something")]
public IHttpActionResult Something()
{
return Ok();
}
}
2返回401的请求和返回400的请求:
First 401:
Request URL: http://xxxx:9000/xxxx
Request Method: GET
Status Code: 401 / Unauthorized
Request Headers
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US
Authorization: Negotiate [token]
Connection: Keep-Alive
Host: xxxx:9000
Referer: http://xxxx/xxxx.html
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3)
Response Headers
Content-Length: 0
Date: Fri, 22 Dec 2017 14:03:09 GMT
Server: Microsoft-HTTPAPI/2.0
WWW-Authenticate: Negotiate [token]
-------------
Second 401
Request URL: http://xxxx:9000/xxxx
Request Method: GET
Status Code: 401 / Unauthorized
Request Headers
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US
Authorization: Negotiate [token]
Connection: Keep-Alive
Host: xxxx:9000
Referer: http://xxxx/xxxx.html
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3)
Response Headers
Content-Length: 0
Date: Fri, 22 Dec 2017 14:03:09 GMT
Server: Microsoft-HTTPAPI/2.0
WWW-Authenticate: Negotiate [token]
-----------
400
Request URL: http://xxxx:9000/xxxx
Request Method: GET
Status Code: 400 / Bad Request
Request Headers
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US
Authorization: Negotiate [token]
Connection: Keep-Alive
Host: xxxx:9000
Referer: http://xxxx/xxxx.html
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3)
Response Headers
Content-Length: 0
Date: Fri, 22 Dec 2017 14:03:12 GMT
Server: Microsoft-HTTPAPI/2.0
答案 0 :(得分:1)
受信任的网站
我的猜测是远程计算机受域策略限制,并且您的站点不被视为该计算机上的可信站点。
添加(或要求添加,如果政策由IT设置)您的网站适当的安全区域(本地Intranet或受信任的站点),问题应该修复。
文档模式
在你了解它的同时,还要看看他们是否正在推动IE11的任何旧文档模式运行。
为WebAPI启用CORS
我发现您已经在OWIN的UseCors
上拨打了IAppBuilder
,但您还可以尝试在HttpConfiguration
个实例上启用CORS:
config.EnableCors(new EnableCorsAttribute("*", "*", "GET, POST, OPTIONS, PUT, DELETE"));
答案 1 :(得分:1)
我使用XHR传递了一个HttpOnly cookie /令牌:
在客户端上使用axios或类似的库,并使用包含withCredentials的配置:
import axios from 'axios';
const config = {
method: 'get',
url: 'http://xxxx:9000/api/test/something',
timeout: 5000,
withCredentials: true
};
//if (setCookie === true) {
//config.mode = 'no-cors'; // <= THIS IS IMPORTANT IF SETTING COOKIE!
//}
const response = await axios(config);
在服务器上设置cors选项:
const corsOptions = {
origin: 'http://xxxx:9000', // Set explicit origin!
methods: ['GET', 'POST', 'PUT', 'DELETE'], // Allow method(s)!
credentials: true //enable server to see credentials.
};
我希望它也适合你,它需要一些时间才能运作。如果失败,那么window.postMessage远射可能会起作用。最后,如果您使用的是Windows,也可能是本地问题:
您的网站所处的安全区域是什么(Internet选项&gt; 安全性)确保您在区域中启用以下设置: 其他&gt;跨域访问数据源。