如何修复 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);
}

example