ASP.NET中Web API解决跨域问题

2022-04-17 11:01:49

一、什么是跨域问题

跨域:指的是浏览器不能执行其他网站的脚本。是由浏览器的同源策略造成的,是浏览器施加的安全限制。(服务端可以正常接收浏览器发生的请求,也可以正常返回,但是由于浏览器的安全策略,浏览器不能处理服务端的返回)。

那么什么是同源策略呢?

同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

正是由于这个原因,如果是在不同的项目之间进行调用(这里说的调用指的是浏览器调用后端,如果是后端直接调用就不会存在跨域问题)就会被浏览器阻止。WebApi中常见的场景:Web Api作为单独的数据服务层,提供接口供前端界面调用,MVC项目作为显示层,这种情况下如果在MVC的前端界面里面通过ajax调用WebApi的接口,就会存在跨域问题。

二、如何解决跨域问题

网上有很多跨域问题的解决方案,这里就不在一一列举了,下面主要讲解一下在WebApi中如何使用CORS解决跨域问题。CORS全称Cross-Origin Resource Sharing,中文全称是跨域资源共享。CORS解决跨域问题的原理是在http的请求报文和响应报文里面加入响应的标识告诉浏览器能够访问哪些域名的请求。

三、使用代码解决跨域问题

下面结合一个具体的实例来讲解在WebApi里面如何使用CORS解决跨域问题。

1、场景描述

新建两个单独的项目:一个WebApi项目(带有MVC功能,用来提供数据和页面显示),一个MVC项目(只是负责页面显示),项目结构如下图所示:

ASP.NET中Web API解决跨域问题

其中,WebApi项目的端口号是:33982,MVC项目的端口号是:34352(这两个端口号是在本机的地址,在其他电脑上端口号可能不同)。显而易见:两个项目的端口号不同,不属于同源,如果在MVC里面通过前端调用WebApi提供的数据接口,就会出现跨域的问题。

2、项目结构

2.1 WebApi项目结构

新建WebApiController文件夹,用来存放WebApi控制器,并新建一个WebApi控制器,命名为Student。StudentController控制器的代码如下:

using  name: "DefaultApi",                routeTemplate: "api/{controller}/{action}/{id}",                defaults: new { id = RouteParameter.Optional }            );        }    }}

这里使用“*”号表示对所有的域名都可以跨域。再次从MVC里面访问WebApi,查看测试结果:

ASP.NET中Web API解决跨域问题

从上面的截图中可以看出,这时就可以允许跨域访问了,在Response Headers里面添加了:Access-Control-Allow-Origin:*。

六、CORS参数详解

在上面我们在WebApi的配置文件中使用了:

config.EnableCors(new EnableCorsAttribute("*","*","*"));

 这一句代码解决了跨域问题。但是这种“*”号是不安全的。查看MSDN,发现EnableCorsAttribute类有如下的构造函数:

public EnableCorsAttribute(    string origins,    string headers,    string methods)

详细的参数解释请查看MSDN。

知道了EnableCorsAttribute类的构造函数以后,我们可以使用下面的方法进行改进。

方法一:在Web.Config文件的appSettings节点里面配置参数:

ASP.NET中Web API解决跨域问题

然后修改WebApiConfig.cs文件的Register方法:

using System;using System.Collections.Generic;using System.Linq;using System.Web.Http;using System.Web.Http.Cors;using System.Configuration;namespace WebApi{    public static class WebApiConfig    {        public static void Register(HttpConfiguration config)        {            #region 跨域配置            string allowedOrigin = ConfigurationManager.AppSettings["allowedOrigin"];            string allowedHeaders = ConfigurationManager.AppSettings["allowedHeaders"];            string allowedMethods = ConfigurationManager.AppSettings["allowedMethods"];            config.EnableCors(new EnableCorsAttribute(allowedOrigin, allowedHeaders, allowedMethods));             #endregion            // Web API 路由            config.MapHttpAttributeRoutes();            config.Routes.MapHttpRoute(                name: "DefaultApi",                routeTemplate: "api/{controller}/{action}/{id}",                defaults: new { id = RouteParameter.Optional }            );        }    }}

方法二:如果只想对某些api或者api里面的某些方法做跨域,可以直接在API控制器类上面使用特性标注或者在方法上面使用特性标注。

允许Student控制器可以跨域:

using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Net.Http;using System.Web.Http;using WebApi.Entity;using System.Web.Http.Cors;namespace WebApi.WebApiController{    [EnableCors(origins:"http://localhost:34352",headers:"*",methods:"GET,POST,PUT,DELETE")]    public class StudentController : ApiController    {        public static List<Student> studentList = InitStudentList();        private static List<Student> InitStudentList()        {            return new List<Student>()            {             new Student {StudentID =1,StudentName="唐僧",Age=24,Sex="男",Major="师范"},                new Student {StudentID =2,StudentName="孙悟空",Age=579,Sex="男",Major="管理"},               new Student {StudentID =3,StudentName="沙悟净",Age=879,Sex="男",Major="水利工程"},               new Student {StudentID =4,StudentName="白骨精",Age=456,Sex="女",Major="表演"},               new Student {StudentID =5,StudentName="玉兔精",Age=456,Sex="女",Major="舞蹈"}            };        }        [HttpGet]        public IHttpActionResult GetAllStudent()        {            return Json<List<Student>>(studentList);        }    }}

只允许Student控制器里面的GetAllStudent方法可以跨域:

using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Net.Http;using System.Web.Http;using WebApi.Entity;using System.Web.Http.Cors;namespace WebApi.WebApiController{    public class StudentController : ApiController    {        public static List<Student> studentList = InitStudentList();        private static List<Student> InitStudentList()        {            return new List<Student>()            {             new Student {StudentID =1,StudentName="唐僧",Age=24,Sex="男",Major="师范"},                new Student {StudentID =2,StudentName="孙悟空",Age=579,Sex="男",Major="管理"},               new Student {StudentID =3,StudentName="沙悟净",Age=879,Sex="男",Major="水利工程"},               new Student {StudentID =4,StudentName="白骨精",Age=456,Sex="女",Major="表演"},               new Student {StudentID =5,StudentName="玉兔精",Age=456,Sex="女",Major="舞蹈"}            };        }        /// <summary>        /// 允许跨域        /// </summary>        /// <returns></returns>        [EnableCors(origins: "http://localhost:34352", headers: "*", methods: "GET,POST,PUT,DELETE")]        [HttpGet]        public IHttpActionResult GetAllStudent()        {            return Json<List<Student>>(studentList);        }        /// <summary>        /// 不允许跨域        /// </summary>        [HttpPost]        public void Post()        { }    }}

到此这篇关于ASP.NET中Web API解决跨域问题的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。