這篇文章介紹如何允許跨域訪問 瀏覽器安全不允許不同功能變數名稱的網頁之間發送請求。這種限制叫做同源策略(the same-origin policy)。 同源策略可以防止一個惡意的站點讀取另一個站點的敏感數據。 有時候,你想允許網站發送跨域的請求到你的應用。 Cross Origin Resource Sh ...
這篇文章介紹如何允許跨域訪問
瀏覽器安全不允許不同功能變數名稱的網頁之間發送請求。這種限制叫做同源策略(the same-origin policy)。
同源策略可以防止一個惡意的站點讀取另一個站點的敏感數據。
有時候,你想允許網站發送跨域的請求到你的應用。
Cross Origin Resource Sharing ( CORS ) :
- 是一個W3C的標準;即允許放寬同源策略
- 不是一個安全的功能,CORS 放寬了安全性。允許跨域,會讓API更不安全
- 允許一個服務明確的允許一些跨域請求,而拒絕另外一些
- 比早些的技術(例如JSONP)更安全,更靈活
1.那麼同源指的是什麼呢
如果兩個URLs是同源的,那麼它們有相同的協議,主機(功能變數名稱),埠
下麵兩個是同源的URLs:
https://example.com/foo.html
https://example.com/bar.html
下麵的這些相比於前面的兩個URL,有不同的源:
https://example.net
– Different domain 不同的功能變數名稱https://www.example.com/foo.html
– Different subdomain 不同的子功能變數名稱http://example.com/foo.html
– Different scheme 不同的協議https://example.com:9000/foo.html
– Different port 不同的埠號
IE瀏覽器考慮同源問題的時候,不會考慮埠號
2.帶策略的CORS 和中間件
CORS中間件處理跨域請求。下麵的代碼允許指定的源能對整個應用進行跨域請求
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) {
//AddCors方法的調用會把CORS服務加到應用的服務容器中(service container); services.AddCors(options => { options.AddPolicy(MyAllowSpecificOrigins, builder => { builder.WithOrigins("http://example.com", //CorsPolicyBuilder方法可以鏈式調用方法, "http://www.contoso.com"); }); }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseCors(MyAllowSpecificOrigins); //這個代碼會把CORS策略通過CORS中間件應用到這個應用的所有終端(endpoints);即把跨域作用到整個應用
//註意:1.UseCors必須在UseMvc之前被調用;2. URL末尾不能加/ ;這個url指的是 builder.WithOrigins(url)中的url
app.UseHttpsRedirection();
app.UseMvc();
}
}
這段代碼做了下麵的操作
- 設置策略名為_myAllowSpecificOrigins,這個名字是隨意取的
- 調用UseCors 擴展方法來允許跨域
- 調用帶有lambda表達式的 AddCors 方法。lambda表達式取得一個 CorsPlicyBuild對象,進行一些設置
CorsPolicyBuilder方法可以鏈式調用方法:
builder.WithOrigins("http://example.com", "http://www.contoso.com") .AllowAnyHeader() .AllowAnyMethod();
測試跨域
3.使用[EnableCors]屬性設置允許跨域
[EnableCors]屬性提供了另一種方式設置跨域。即可以只設置選擇的終端,而不是所有的終端.
這裡不同於上面的那種方式,上面的方式是應用的所有終端都會被設置允許跨域;
而這裡只是設置了[EnableCors]屬性的終端;
使用[EnableCors]來指定預設的策略,而[EnableCors("{Policy String}")] 指定了特定的策略;
[EnableCors]屬性應用於:
- Razor Page PageModel
- Controller
- Controller action method
你可以使用[EnableCors]屬性應用不同的策略到 controller/page-model/action 中;
當[EnableCors]屬性應用到 controller/page-model/action ,並且CORS在中間件被允許了(指【Enable("{Policy String}")】的方式),這兩種策略就都被使用了;
不推薦結合使用策略;使用[EnableCors]屬性或者中間件,而不是在相同的應用中使用兩個
下麵的代碼給每個方法使用了一種策略
[Route("api/[controller]")] [ApiController] public class WidgetController : ControllerBase { // GET api/values [EnableCors("AnotherPolicy")] [HttpGet] public ActionResult<IEnumerable<string>> Get() { return new string[] { "green widget", "red widget" }; } // GET api/values/5 [EnableCors] // Default policy. [HttpGet("{id}")] public ActionResult<string> Get(int id) { switch (id) { case 1: return "green widget"; case 2: return "red widget"; default: return NotFound(); } } }
下麵的代碼創建了一個跨越預設策略和一個名字叫“AnotherPolicy”的策略:
public class StartupMultiPolicy { public StartupMultiPolicy(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddCors(options => { options.AddDefaultPolicy( builder => { builder.WithOrigins("http://example.com", "http://www.contoso.com"); }); options.AddPolicy("AnotherPolicy", builder => { builder.WithOrigins("http://www.contoso.com") .AllowAnyHeader() .AllowAnyMethod(); }); }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseHttpsRedirection(); app.UseMvc(); } }
另,其實還有[DisableCors]屬性可以禁止CORS,這裡先暫時不做講解
...未完,待續