如何在带OAuth令牌认证的.NET Web API中配置CORS允许多个域名访问
.NET Framework带OAuth认证的Web API多域名CORS配置方案
首先先清理所有冗余CORS配置,避免响应头重复:
- 删除web.config
<system.webServer>节点下所有手动配置的Access-Control-Allow-Origin相关响应头 - 删除自定义Delegating Handler中编写的CORS响应头添加逻辑
- 确认全局没有其他硬编码返回CORS响应头的代码
步骤1:安装官方CORS包
通过NuGet安装Microsoft.AspNet.WebApi.Cors,版本需和你项目中已安装的Microsoft.AspNet.WebApi.Core版本保持一致,避免兼容问题。
步骤2:配置允许的域名白名单
在web.config的<appSettings>节点中添加允许访问的域名配置:
<appSettings> <!-- 多个域名用英文逗号分隔,不要加末尾斜杠 --> <add key="AllowedCorsOrigins" value="https://app1.yourdomain.com,https://app2.yourdomain.com,https://outlook.office.com" /> </appSettings>
注:Exchange加载项的请求域名需要按要求填入对应域名,比如Office 365的加载项需要添加https://outlook.office.com、https://outlook.office365.com等域名。
步骤3:自定义CORS策略提供类
创建自定义CORS属性,实现动态匹配白名单域名的逻辑:
using System; using System.Configuration; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using System.Web.Cors; using System.Web.Http.Cors; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] public class AllowSpecifiedOriginsAttribute : Attribute, ICorsPolicyProvider { private readonly CorsPolicy _corsPolicy; public AllowSpecifiedOriginsAttribute() { _corsPolicy = new CorsPolicy { AllowAnyMethod = true, AllowAnyHeader = true, // 带OAuth令牌的请求必须开启凭证支持,不能使用通配符* SupportsCredentials = true }; // 从配置加载允许的域名 var originList = ConfigurationManager.AppSettings["AllowedCorsOrigins"].Split(','); foreach (var origin in originList) { _corsPolicy.Origins.Add(origin.Trim()); } } public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return Task.FromResult(_corsPolicy); } }
步骤4:注册CORS中间件
在WebApiConfig.cs的Register方法中开启CORS支持,不需要传入全局EnableCorsAttribute:
using System.Web.Http; public static class WebApiConfig { public static void Register(HttpConfiguration config) { // 仅添加这一句开启CORS支持即可 config.EnableCors(); // 原有路由配置保持不变 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } }
步骤5:处理预检请求被OAuth拦截的问题
预检OPTIONS请求不会携带Authorization头,默认会被OAuth认证拦截返回401错误,需要在认证中间件中跳过OPTIONS请求的认证校验,在Startup.Auth.cs的ConfigureAuth方法中添加如下逻辑:
using Microsoft.Owin; using Owin; public void ConfigureAuth(IAppBuilder app) { // 优先处理OPTIONS预检请求,跳过认证 app.Use(async (context, next) => { if (context.Request.Method == "OPTIONS") { context.Response.StatusCode = 200; await context.Response.WriteAsync(string.Empty); return; } await next.Invoke(); }); // 原有OAuth认证配置保持不变 // ...... }
步骤6:应用CORS规则
- 如果需要全局所有接口都应用该规则,可在所有API控制器的基类上添加
[AllowSpecifiedOrigins]特性 - 如果只需要给特定接口开放,可在对应的Controller或Action上添加
[AllowSpecifiedOrigins]特性
注意事项
- 禁止同时使用web.config配置CORS头和Web API的CORS中间件,否则会出现重复响应头错误
- 开启
SupportsCredentials后CORS规范不允许返回通配符*,本方案会自动匹配请求的Origin并只返回对应的允许域名,不会出现多值错误 - 配置允许的域名时不要加末尾斜杠,否则会出现域名匹配失败的问题
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

