這篇文章介紹如何允許跨域訪問
瀏覽器安全不允許不同域名的網頁之間發送請求。這種限制叫做同源策略(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,這里先暫時不做講解
...未完,待續