網(wǎng)站首頁 編程語言 正文
一、什么是跨域問題
跨域:指的是瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。是由瀏覽器的同源策略造成的,是瀏覽器施加的安全限制。(服務(wù)端可以正常接收瀏覽器發(fā)生的請求,也可以正常返回,但是由于瀏覽器的安全策略,瀏覽器不能處理服務(wù)端的返回)。
那么什么是同源策略呢?
同源策略/SOP(Same origin policy)是一種約定,由Netscape公司1995年引入瀏覽器,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSS、CSFR等攻擊。所謂同源是指"協(xié)議+域名+端口"三者相同,即便兩個不同的域名指向同一個ip地址,也非同源。
正是由于這個原因,如果是在不同的項目之間進行調(diào)用(這里說的調(diào)用指的是瀏覽器調(diào)用后端,如果是后端直接調(diào)用就不會存在跨域問題)就會被瀏覽器阻止。WebApi中常見的場景:Web Api作為單獨的數(shù)據(jù)服務(wù)層,提供接口供前端界面調(diào)用,MVC項目作為顯示層,這種情況下如果在MVC的前端界面里面通過ajax調(diào)用WebApi的接口,就會存在跨域問題。
二、如何解決跨域問題
網(wǎng)上有很多跨域問題的解決方案,這里就不在一一列舉了,下面主要講解一下在WebApi中如何使用CORS解決跨域問題。CORS全稱Cross-Origin Resource Sharing,中文全稱是跨域資源共享。CORS解決跨域問題的原理是在http的請求報文和響應(yīng)報文里面加入響應(yīng)的標識告訴瀏覽器能夠訪問哪些域名的請求。
三、使用代碼解決跨域問題
下面結(jié)合一個具體的實例來講解在WebApi里面如何使用CORS解決跨域問題。
1、場景描述
新建兩個單獨的項目:一個WebApi項目(帶有MVC功能,用來提供數(shù)據(jù)和頁面顯示),一個MVC項目(只是負責頁面顯示),項目結(jié)構(gòu)如下圖所示:
其中,WebApi項目的端口號是:33982,MVC項目的端口號是:34352(這兩個端口號是在本機的地址,在其他電腦上端口號可能不同)。顯而易見:兩個項目的端口號不同,不屬于同源,如果在MVC里面通過前端調(diào)用WebApi提供的數(shù)據(jù)接口,就會出現(xiàn)跨域的問題。
2、項目結(jié)構(gòu)
2.1 WebApi項目結(jié)構(gòu)
新建WebApiController文件夾,用來存放WebApi控制器,并新建一個WebApi控制器,命名為Student。StudentController控制器的代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using WebApi.Entity; namespace WebApi.WebApiController { public class StudentController : ApiController { public static ListstudentList = InitStudentList(); private static List InitStudentList() { return new List () { 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 >(studentList); } } }
修改WebApi配置文件類,路由規(guī)則里面增加action,代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web.Http; namespace WebApi { public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API 配置和服務(wù) // Web API 路由 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); } } }
新建一個MVC控制器,命名為Student,并添加Index視圖,Index視圖代碼如下:
@{ Layout = null; }測試跨域問題 Get Student List
2.2 MVC項目結(jié)構(gòu)
MVC項目結(jié)構(gòu)比較簡單,新建一個名為Student的控制器,并添加視圖,視圖如下:
@{ Layout = null; }測試跨域問題 Get Student List
四、測試
1、在不做任何處理情況下的測試
先看看同源下的訪問情況,直接啟動WebApi項目,截圖如下:
點擊按鈕,測試結(jié)果如下:
因為是在同一個域中,所以訪問沒有問題,前端可以正常獲取到WebApi返回的數(shù)據(jù)。下面在來看看在MVC項目中的測試情況。測試截圖如下:
從圖中可以看出訪問失敗了,按F12查看訪問情況:
從上面的截圖中可以看出,發(fā)生了跨域訪問,瀏覽器出于安全性的考慮,不能接收返回的數(shù)據(jù)。
五、使用CORS解決跨域問題
1、安裝CORS
在WebApi項目上右鍵->管理NuGet程序包,然后搜索“microsoft.aspnet.webapi.cors”,選擇第一個進行安裝
具體的安裝過程在這里不再詳細解釋。
2、配置跨域
在WebApiConfig.cs類中配置跨域,修改后的代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web.Http; using System.Web.Http.Cors; namespace WebApi { public static class WebApiConfig { public static void Register(HttpConfiguration config) { // 跨域配置 config.EnableCors(new EnableCorsAttribute("*","*","*")); // Web API 路由 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); } } }
這里使用“*”號表示對所有的域名都可以跨域。再次從MVC里面訪問WebApi,查看測試結(jié)果:
從上面的截圖中可以看出,這時就可以允許跨域訪問了,在Response Headers里面添加了:Access-Control-Allow-Origin:*。
六、CORS參數(shù)詳解
在上面我們在WebApi的配置文件中使用了:
config.EnableCors(new EnableCorsAttribute("*","*","*"));
?這一句代碼解決了跨域問題。但是這種“*”號是不安全的。查看MSDN,發(fā)現(xiàn)EnableCorsAttribute類有如下的構(gòu)造函數(shù):
public EnableCorsAttribute( string origins, string headers, string methods )
詳細的參數(shù)解釋請查看MSDN。
知道了EnableCorsAttribute類的構(gòu)造函數(shù)以后,我們可以使用下面的方法進行改進。
方法一:在Web.Config文件的appSettings節(jié)點里面配置參數(shù):
然后修改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 ListstudentList = InitStudentList(); private static List InitStudentList() { return new List () { 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 >(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 ListstudentList = InitStudentList(); private static List InitStudentList() { return new List () { 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="舞蹈"} }; } /// /// 允許跨域 /// ///[EnableCors(origins: "http://localhost:34352", headers: "*", methods: "GET,POST,PUT,DELETE")] [HttpGet] public IHttpActionResult GetAllStudent() { return Json >(studentList); } ///
/// 不允許跨域 /// [HttpPost] public void Post() { } } }
原文鏈接:https://www.cnblogs.com/dotnet261010/p/8831450.html
相關(guān)推薦
- 2023-03-20 C#實現(xiàn)簡單的文件加密與解密方式_C#教程
- 2023-03-02 Go語言讀取文本文件的三種方式總結(jié)_Golang
- 2023-02-23 淺談Go語言的高效編碼細節(jié)_Golang
- 2022-10-16 解析React?ref?命令代替父子組件的數(shù)據(jù)傳遞問題_React
- 2022-03-15 react 編譯警告 chunk common [mini-css-extract-plugin]
- 2023-01-26 Android?源碼淺析RecyclerView?Adapter_Android
- 2022-10-28 Go語言包和包管理詳解_Golang
- 2022-06-11 docker安裝elastic?search和kibana的實現(xiàn)_docker
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支