我有一个应用程序,其中Web UI(reactjs)和Web API(.net)部署在两个不同的服务器上。但是,当我将API身份验证设置为Windows时,它总是给我错误:Failed to load resource: the server responded with a status of 401 (Unauthorized)
当我进行以下设置时,我可以浏览已部署的应用程序链接:
UI Site: Windows Authentication
API Site: Anonymous Authentication.
但是,这无助于我获取登录的用户ID。返回已登录用户的iis /应用程序池名称。
因此,我将设置更改为以下内容:
UI Site: Windows Authentication
API Site: Windows Authentication and ASP.NET Impersonation.
现在,当我遇到第一个API时,我会在UI中收到授权错误。需要注意的是,如果我直接访问API链接,它将返回我的结果,并同时提供我的用户ID作为登录的用户ID。
我尝试了互联网上建议的各种解决方案,包括以下步骤之一至步骤4: How to pass Windows Authentication credential from client to Web API service,但尚未成功。
有人遇到这样的问题并找到了解决方法吗?
编辑: 在下面的回复中,我按照亚历山大·罗德里格斯的建议继续进行。我按照链接中所述启用了CORS。
第一个问题是:The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute
。
所以我继续并在以下位置添加了网站路径:
[EnableCors(origins: "http:myexample.com", headers: "*", methods: "*", SupportsCredentials = true)]
它完全没有帮助,然后我在web.config中添加了以下几行:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Methods" value="POST,GET" />
<add name="Access-Control-Allow-Origin" value="http://myexample.com" />
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Allow-Headers" value="cache-control,content-type,man,messagetype,soapaction" />
</customHeaders>
</httpProtocol>
下一个错误是:
The value of the 'Access-Control-Allow-Credentials' header in the response is 'true, true' which must be 'true'.
和
The value of the 'Access-Control-Allow-Origin' header in the response is 'http://myexample.com, http://myexample(index).com' which must be 'http://myexample.com'
因此,作为最后的选择,我在WebAPI和重新部署的应用程序的以下行中进行了评论。
[EnableCors(origins: "http:myexample.com", headers: "*", methods: "*", SupportsCredentials = true)]
行得通!这导致应用程序显示两个控制器的结果:一个是我设置了Authorize的控制器,另一个是没有Authorize的控制器。
该错误仅由我添加了[Authorize]的控制器抛出,因为大多数情况下另一个正在返回结果。
所以我的问题是,这是常规的身份验证和授权应该如何工作?或者我评论了授权的一个非常重要的部分?
更新:
因此,这仅使GET请求起作用而没有POST。
请求标头:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: cache-control,content-type,man,messagetype,soapaction
Access-Control-Allow-Methods: POST,GET
Access-Control-Allow-Origin: http://myexample.com
**Response Header**
Provisional headers are shown
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Origin: http://myexample.com
Referer: http://myexample.com/form/1001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36
答案 0 :(得分:1)
先决条件
要从Reactjs或任何Ajax方法访问任何Web API,Web API必须启用CORS
Web配置代码段
<system.web>
<authentication mode="Windows" ></authentication>
</system.web>
在控制器或任何用于安全的操作方法上使用 Authorize属性
示例
[EnableCors(origins: "*", headers: "*", methods: "*", SupportsCredentials = true)]
public partial class WebAPIController : ApiController
{
[HttpGet]
[Authorize]
[Route("api/AuthenticateUser")]
public HttpResponseMessage AuthenticateUser()
{
if (User != null)
{
return Request.CreateResponse(HttpStatusCode.OK, new
{
status = (int)HttpStatusCode.OK,
isAuthenticated = true,
isLibraryAdmin = User.IsInRole(@"domain\AdminGroup"),
username = User.Identity.Name.Substring(User.Identity.Name.LastIndexOf(@"\") + 1)
});
}
else
{
//This code never execute as we have used Authorize attribute on action method
return Request.CreateResponse(HttpStatusCode.OK, new
{
status = (int)HttpStatusCode.BadRequest,
isAuthenticated = false,
isLibraryAdmin = false,
username = ""
});
}
}
}
此[Authorize]
属性可确保仅在用户输入有效凭据时才执行操作,否则将显示401未经授权的访问。
如果您收到“此请求的授权已被拒绝”,请选中此post
因此,基于以上提供的解决方案,堆栈溢出问题需要在位于项目根目录“ .vs \ config”的“ applicationhost.config”文件中对Windows身份验证()进行更多配置,该文件夹已隐藏必须启用“显示所有隐藏的文件和文件夹”选项。
<windowsAuthentication enabled="true">
<providers>
<add value="Negotiate" />
<add value="NTLM" />
</providers>
</windowsAuthentication>
CORS从服务器端启用。现在,在请求API时,从前端传递标志withCredentials:true。
对于jQuery Ajax,您必须通过以下请求。
$.ajax({url:apiURL ,xhrFields: { withCredentials: true }, success:successHandler });
对于Reactjs,您必须按如下所示传递请求。
private options = new RequestOptions({ withCredentials: true });
this.http.get(this.baseUrl, this.options)
Ajax代码段
var apiURL="http://localhost:51647/api/AuthenticateUser";
$.ajax({
url:apiURL ,
xhrFields: { withCredentials: true },
success: function(result){
console.log(JSON.stringify(result));
}});
已编辑
让我们启用CORS
预请求(选项)
<system.web>
<authentication mode="Windows" />
<authorization>
<allow verbs="OPTIONS" users="*"/>
<deny users="?" />
</authorization>
</system.web>
global.asax.cs
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (Context.Request.HttpMethod == "OPTIONS")
{
if (Context.Request.Headers["Origin"] != null)
Context.Response.AddHeader("Access-Control-Allow-Origin", Context.Request.Headers["Origin"]);
Context.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, MaxDataServiceVersion");
Context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
Context.Response.AddHeader("Access-Control-Allow-Credentials", "true");
Response.End();
}
}
启用CORS
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// all requests are enabled in this example. SupportsCredentials must be here to allow authenticated requests
var corsAttr = new EnableCorsAttribute("*", "*", "*") { SupportsCredentials = true };
config.EnableCors(corsAttr);
}
}
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}