如何修复 reactjs web 应用程序到 .net webapi 授权错误
How to fix reactjs web app to .net webapi authorization error
我有一个应用程序,其中 Web UI (reactjs) 和 Web APIs (.net) 部署在两个不同的服务器上。但是,当我将 API 身份验证设置为 Windows 时,它一直给我错误:Failed to load resource: the server responded with a status of 401 (Unauthorized)
当我有以下设置时,我可以浏览已部署的应用程序 link:
UI 站点:Windows 身份验证<br>
API 站点:匿名身份验证。
但这并不能帮助我获得 logged-in user-id。 returns iis/app-pool 登录用户的名称。
所以,我将设置更改为以下内容:
UI 站点:Windows 身份验证<br>
API 站点:Windows 身份验证和 ASP.NET 模拟。
现在我在 UI 第一次点击 API 时收到授权错误。需要注意的是,如果我直接访问 API link,它会返回我的结果并提供我记录的用户 ID user-id。
我尝试了互联网上建议的各种解决方案,包括以下步骤的第 1 步到第 4 步:
How to pass Windows Authentication credential from client to Web API service 但还没有成功。
有没有人遇到过这样的问题并找到了解决办法?
编辑:
我按照 Alexandre Rodrigues 在下面的回复中建议的步骤继续进行。我按照 link 中的描述启用了 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] 的控制器抛出,因为另一个控制器大部分时间都在返回结果。
所以我的问题是,这是常规身份验证和授权的工作方式,还是我评论了授权的一个非常重要的部分?
更新:
所以这只使 GET 请求起作用,而不是 POST。
请求Header:
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
先决条件
要从 Reactjs 或任何 Ajax 方法访问任何 Web API Web API 必须启用 CORS
Web 配置代码片段
<system.web>
<authentication mode="Windows" ></authentication>
</system.web>
在控制器或任何安全操作方法上使用授权属性
例子
[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
因此,根据上面提供的解决方案,堆栈溢出问题需要在“applicationhost.config”文件(位于项目根目录“.vs\config”,这个文件夹是隐藏的,你必须启用显示所有隐藏的文件和文件夹选项。
<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);
}
我有一个应用程序,其中 Web UI (reactjs) 和 Web APIs (.net) 部署在两个不同的服务器上。但是,当我将 API 身份验证设置为 Windows 时,它一直给我错误:Failed to load resource: the server responded with a status of 401 (Unauthorized)
当我有以下设置时,我可以浏览已部署的应用程序 link:
UI 站点:Windows 身份验证<br>
API 站点:匿名身份验证。
但这并不能帮助我获得 logged-in user-id。 returns iis/app-pool 登录用户的名称。
所以,我将设置更改为以下内容:
UI 站点:Windows 身份验证<br>
API 站点:Windows 身份验证和 ASP.NET 模拟。
现在我在 UI 第一次点击 API 时收到授权错误。需要注意的是,如果我直接访问 API link,它会返回我的结果并提供我记录的用户 ID user-id。
我尝试了互联网上建议的各种解决方案,包括以下步骤的第 1 步到第 4 步: How to pass Windows Authentication credential from client to Web API service 但还没有成功。
有没有人遇到过这样的问题并找到了解决办法?
编辑: 我按照 Alexandre Rodrigues 在下面的回复中建议的步骤继续进行。我按照 link 中的描述启用了 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] 的控制器抛出,因为另一个控制器大部分时间都在返回结果。
所以我的问题是,这是常规身份验证和授权的工作方式,还是我评论了授权的一个非常重要的部分?
更新:
所以这只使 GET 请求起作用,而不是 POST。
请求Header:
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
先决条件
要从 Reactjs 或任何 Ajax 方法访问任何 Web API Web API 必须启用 CORS
Web 配置代码片段
<system.web>
<authentication mode="Windows" ></authentication>
</system.web>
在控制器或任何安全操作方法上使用授权属性
例子
[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
因此,根据上面提供的解决方案,堆栈溢出问题需要在“applicationhost.config”文件(位于项目根目录“.vs\config”,这个文件夹是隐藏的,你必须启用显示所有隐藏的文件和文件夹选项。
<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);
}