C#进阶-ASP.NET的WebService跨域CORS题目办理方案

打印 上一主题 下一主题

主题 511|帖子 511|积分 1533

在现代的Web应用程序开发中,跨域资源共享(Cross-Origin Resource Sharing, CORS)题目是开发者常常遇到的一个挑衅。特别是当前端和后端服务摆设在不同的域名或端口时,CORS题目就会显得尤为突出。在这篇博客中,我们将深入探讨如何在 .NET WebService 中办理CORS题目,资助开发者顺利实现跨域请求。

一、CORS题目描述

在Web应用中,欣赏器安全机制通常会克制来自不同域的请求,这被称为“同源策略”。同源策略允许同一来源(协议、主机和端口类似)的资源相互访问,但会克制不同来源的资源访问。这种机制虽然提高了安全性,但在现实开发中,前端和后端通常会摆设在不同的服务器上,这就引发了CORS题目。
举个例子,当你试图从 http://frontend.com 发送一个请求到 http://api.backend.com 时,欣赏器会拦截这个请求并抛出一个CORS错误:
  1. Access to XMLHttpRequest at 'http://api.backend.com/resource' from origin 'http://frontend.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
复制代码
对于 .NET WebService ,如果前端应用尝试从另一个域名访问服务,而服务端没有适当的CORS策略,那么欣赏器会克制这些请求并表现该跨域错误。

二、CORS题目代码示例

为了更好地明白CORS题目及其办理方案,让我们先创建一个简单的前后端交互的.NET WebService示例。
1. 后端WebService接口代码

首先,创建一个新的 .NET Framework 项目。你可以利用 Visual Studio 或者命令行工具(如 dotnet CLI )来创建项目。在项目中,我们定义一个 .asmx 文件,并在 .asmx.cs 文件里创建一个接口。


接口代码如下:
  1. using Newtonsoft.Json;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Data;
  5. using System.Web;
  6. using System.Web.Services;
  7. namespace TestProject
  8. {
  9.     [WebService(Namespace = "http://tempuri.org/")]
  10.     [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
  11.     [System.ComponentModel.ToolboxItem(false)]
  12.     [System.Web.Script.Services.ScriptService]
  13.     public class Test : WebService
  14.     {
  15.         [WebMethod]
  16.         public void GetJsonData()
  17.         {
  18.             string json = "{"MapPoints":[{"Coordinates":["118.87220827635","34.885061248714"],"Speed":"45.7","Time":"2024-05-13T13:02:09"}]}";
  19.             HttpContext.Current.Response.ContentType = "application/json";
  20.             HttpContext.Current.Response.Write(json);
  21.         }
  22.     }
  23. }
复制代码
这个控制器有一个GET方法,当请求 http://localhost:80/Test.asmx/GetJsonData 时,它会返回一个串JSON数据。
这里我们可以用 Postman 测试代码,精确返回结果,则验证后端接口代码没有题目。


2. 前端接口请求代码

这里我利用的前端访问接口的JavaScript代码是基于 axios 实现的。
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>CORS Test</title>
  7. </head>
  8. <body>
  9.     <h1>CORS Test</h1>
  10.     <button id="fetchDataButton">Fetch Data</button>
  11.     <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  12.     <script>
  13.         document.getElementById('fetchDataButton').addEventListener('click', function () {
  14.             getCarLocation();
  15.         });
  16.         function getCarLocation() {
  17.             axios.get('http://localhost:80/Test.asmx/GetJsonData')
  18.                 .then(function (response) {
  19.                     console.log('Success:', response.data);
  20.                 })
  21.                 .catch(function (error) {
  22.                     console.error('Error:', error);
  23.                 });
  24.         }
  25.     </script>
  26. </body>
  27. </html>
复制代码
页面效果图如下:

当点击 Fetch Data 按钮时,页面会访问 http://localhost:80/Test.asmx/GetJsonData 接口,并输出返回值到F12控制台日记里。
此时,如果我们不配置CORS,那么请求会被拦截,并报错:
  1. Access to XMLHttpRequest at 'http://localhost:80/Test.asmx/GetJsonData' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
复制代码

三、CORS配置具体步骤

为了让我们的 WebService 支持跨域请求,我们须要在项目中配置CORS。在 .NET Framework 中,我们可以通过如下步骤来配置CORS。
1. 配置Global.asax全局请求头参数

创建或打开项目的 Global.asax 文件,找到或添加 Application_BeginRequest() 方法,添加响应头参数,其中 <"Access-Control-Allow-Origin", "*"> 这个响应头是最紧张的。
  1. namespace TestProject
  2. {
  3.     public class Global : System.Web.HttpApplication
  4.     {
  5.         protected void Application_BeginRequest()
  6.         {
  7.             HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
  8.             HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
  9.             HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization, X-Requested-With");
  10.             if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
  11.             {
  12.                 HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "86400");
  13.                 HttpContext.Current.Response.StatusCode = 204;
  14.                 HttpContext.Current.Response.End();
  15.             }
  16.         }
  17.     }
  18. }
复制代码
要非常注意的是,每个请求头参数只能添加一次,如果重复添加,依然会访问报错,可以排查一下 web.config 文件或者专门的路由模块有没有已经添加,或者再每次添加之前判定当前请求头是否已经存在,如果存在删除在添加。

2. 创建自定义HTTP模块并注册

在 .NET Framework 中,通过自定义 HTTP 模块修改 HTTP 响应头,可以协助处理跨域题目。
我们右键办理方案,新建项目,创建 ​​CustomHttpModules​​ 模块。


模块内创建 HeaderFilterHttpModule.cs 文件。

代码如下 :
  1. using System;
  2. using System.Web;
  3. namespace CustomHttpModules
  4. {
  5.     public class HeaderFilterHttpModule : IHttpModule
  6.     {
  7.         public void Init(HttpApplication context)
  8.         {
  9.             context.PreSendRequestHeaders += OnPreSendRequestHeaders;
  10.         }
  11.         public void Dispose()
  12.         { }
  13.         void OnPreSendRequestHeaders(object sender, EventArgs e)
  14.         {
  15.             try
  16.             {
  17.                 HttpApplication app = sender as HttpApplication;
  18.                 if (app != null && app.Context != null && app.Context.Response != null)
  19.                 {
  20.                     var headers = app.Context.Response.Headers;
  21.                     if (headers != null)
  22.                     {
  23.                         headers.Remove("Server");
  24.                         headers.Remove("X-AspNet-Version");
  25.                         headers.Remove("X-AspNetMvc-Version");
  26.                         headers.Remove("X-Frame-Options");
  27.                         headers.Remove("X-Powered-By");
  28.                         // 添加CORS相关的头信息
  29.                         headers.Add("Access-Control-Allow-Origin", "*");
  30.                         headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
  31.                         headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept");
  32.                     }
  33.                 }
  34.             }
  35.             catch (Exception ex)
  36.             {
  37.                 // 记录异常
  38.             }
  39.         }
  40.     }
  41. }
复制代码
创建完成后,我们到主项目注册这个自定义的 HTTP 模块。
先给主项目添加引用:
右键主项目,添加新模块到引用。

然后,打开 web.config 文件,找到 <configuration> 下的 <system.webServer> 标签,引入我们刚刚创建好的 HeaderFilterHttpModule 模块。
  1. <configuration>
  2.   <system.webServer>
  3.     <modules>
  4.       <add name="HeaderFilterHttpModule" type="CustomHttpModules.HeaderFilterHttpModule" />
  5.     </modules>
  6.   </system.webServer>
  7. </configuration>
复制代码

3. 测试增加CORS配置后的代码

添加上述有关CORS的配置后,我们重新启动 .NET Framework 项目,通过测试页面点击 Fetch Data 按钮,给 http://localhost:80/Test.asmx/GetJsonData 接口发送请求。
可以看到我们得到了精确的返回值。
  1. {
  2.     "MapPoints": [
  3.         {
  4.             "Coordinates": [
  5.                 "118.87220827635",
  6.                 "34.885061248714"
  7.             ],
  8.             "Speed": "45.7",
  9.             "Time": "2024-05-13T13:02:09"
  10.         }
  11.     ]
  12. }
复制代码
.NET WebService 跨域CORS题目完美办理。

四、CORS题目办理总结

通过配置 global.asax 全局文件,创建和注册自定义 HTTP 模块,我们乐成地办理了 .NET WebService 中的 CORS 题目。这种方法的关键在于拦截和修改 HTTP 响应头,添加须要的 CORS 头信息。总结如下:

  • 修改Global.asax文件:修改 Application_BeginRequest 方法,修改全局请求头参数。
  • 创建自定义 HTTP 模块:实现 IHttpModule 接口,并在 PreSendRequestHeaders 变乱中添加或移除 HTTP 头信息。
  • 注册 HTTP 模块:在 Web.config 文件中注册自定义的 HTTP 模块。
  • 测试能否跨域:通过前端发送跨域请求来验证 CORS 配置是否精确。
通过这些步骤,开发者可以有用地办理跨域资源共享题目,确保前后端服务的顺畅通讯。在现实开发中,根据具体项目的需求,CORS 配置可能会有所不同,但核心思想和步骤是类似的。希望这篇博客能为你办理 CORS 题目提供有代价的资助。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张国伟

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表