如何将reactjs Web应用修复为.net webapi授权错误

时间:2019-05-23 21:09:01

标签: asp.net-mvc reactjs iis authorization windows-authentication

我有一个应用程序,其中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

1 个答案:

答案 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);
}

example