angularjs 在www.example.com Web API中处理CORS飞行前Asp.net

f45qwnt8  于 2022-10-31  发布在  Angular
关注(0)|答案(4)|浏览(205)

我的架构中有三个应用程序。
它们位于同一台服务器上,但端口号不同。

A - Token Application (port 4444) - Asp.net WebApi
B - API Application   (port 3333) - Asp.net WebApi
C - UI Application    (port 2222) - AngularJS App.

申请流程如下
1-UI项目从令牌应用程序获取令牌(它需要Windows身份验证)。例如:awxrsdsaWeffs12da
2-UI应用程序将此令牌放入名为“accessToken”的自定义标头
例如:访问令牌:awxrsdsaWeffs12da
3-UI应用程序向API应用程序Ex发送请求:http:myaddress:3333/api/TheRestServiceHere
UI应用程序收到401错误。它发送OPTIONS方法。(我猜是预检问题)
在我的web api项目中,我启用了如下的Cors。

public static void Register(HttpConfiguration config)
{
            ....

            //CORS
            var cors = new EnableCorsAttribute("*", "*", "*");
            config.EnableCors(cors);

            ....
}

设定

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {

            //CORS
            var cors = new EnableCorsAttribute("*", "*", "*");
            config.EnableCors();

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            var json = config.Formatters.JsonFormatter;
            json.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.None;
            json.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            json.SerializerSettings.Formatting = Formatting.None;
            json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

            config.Formatters.Remove(config.Formatters.XmlFormatter);
        }
    }

所以我正在寻找一个解决方案,调用API应用程序(B)控制器,并获得200:)
此致

shstlldc

shstlldc1#

我通过创建一个模块来响应使用OPTIONS动词的请求,从而在我正在处理的应用程序中修复了这个问题。您可能应该对其进行一些修改,以包含应用程序所请求的动词和内容类型。在我的例子中,我决定将所有内容都以JSON格式发布(这需要进行预检)。该模块如下所示:

public class OptionsModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest += (sender, args) =>
        {
            var app = (HttpApplication) sender;

            if (app.Request.HttpMethod == "OPTIONS")
            {
                app.Response.StatusCode = 200;
                app.Response.AddHeader("Access-Control-Allow-Headers", "content-type");
                app.Response.AddHeader("Access-Control-Allow-Origin", APISettings.ApplicationOrigin);
                app.Response.AddHeader("Access-Control-Allow-Credentials", "true");
                app.Response.AddHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS");
                app.Response.AddHeader("Content-Type", "application/json");
                app.Response.End();
            }
        };
    }

    public void Dispose()
    {
    }
}

然后,您需要在web.config中注册它:

<system.webServer>
    <modules>
      <add name="HandleOptions" type="namespace.OptionsModule" />
    </modules>
</system.webServer>

另一件你可能需要做的事情是明确地指定允许的来源。Chrome不喜欢在那里使用通配符。

wf82jlnq

wf82jlnq2#

我的一个朋友通过使用OPTIONSVerbHandler解决了这个问题。
当UI应用程序要使用GET方法时,浏览器首先将OPTION方法发送到服务器(预检)。然后,如果预检请求正常,它将发送GET请求。

出于CORS测试目的,我们使用以下代码发送GET方法。

<html>
<head>
    <script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script>
    $( document ).ready(function() {
        var adress = "http://10.10.27.36:3434/backend/api/role";

        $.ajaxSetup({
            headers: { 
            'Content-Type': 'application/json',
            'accessToken': 'some value',
            'Origin' : ''
            }
        });

        $.ajax({
        type: "GET",
        url: adress,
        dataType: "json"
        });

    });

    </script></head><body></body></html>

要处理在GET之前由浏览器发送的OPTION方法,您应该具有以下设置。

1-Web配置

<system.webServer>
    <handlers>
        <add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" resourceType="Unspecified" requireAccess="None" />
    </handlers>
</system.webServer>

2-正在使用以下设置添加OPTIONSVerbHandler

点击请求限制

3-我们的标头设置有accessToken,如您所见,这是自定义的

zpgglvta

zpgglvta3#

这个问题发生在Cordova v11,Android平台上。我使用了Jereme提供的解决方案(评分最高的答案),但有一个例外:在OptionsModule中,我必须省略语句

app.Response.AddHeader("Access-Control-Allow-Origin", APISettings.ApplicationOrigin);

相反,在web.config文件中,我添加<system.webServer>了以下部分:

<httpProtocol>
    <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />  
        <!-- Note:  "localhost" for Cordova is not valid, only * worked. -->
    </customHeaders>
</httpProtocol>

关于Cordova的一个词,以防有人不熟悉。Cordova为Android平台打包了一个原生应用程序,其中包含一个“javascript页面”,使用应用程序中的Web视图来显示页面。使用Chrome调试器查看javascript页面时,页面来源显示为localhost。但是,对于Access-Control-Allow-Origin头,localhost不是可接受的值;因此,我不得不在Web.config文件中使用“*”。2当我在OptionsModule中有响应头时,预检响应是正常的(状态200),但不是对启动预检请求的XMLHttpRequest(api)的响应。3只在Web.config文件中放置自定义头就可以使两个响应都是正常的(状态200)。

j9per5c4

j9per5c44#

适用于Azure环境

您需要允许来自门户网站的来源。

相关问题