尝试全局启用 CORS 时出现异常
Posted
技术标签:
【中文标题】尝试全局启用 CORS 时出现异常【英文标题】:Exception when trying to enable CORS globally 【发布时间】:2017-01-08 23:10:04 【问题描述】:我正在尝试像这样在全球范围内启用 CORS:
services.Configure<MvcOptions>(options =>
options.Filters.Add(new CorsAuthorizationFilterFactory("AllowSpecificOrigin"));
);
当我尝试加载我的应用程序时,我遇到了这个异常:
InvalidOperationException:未注册“Microsoft.AspNetCore.Mvc.Cors.CorsAuthorizationFilter”类型的服务。
这些是 Startup.cs 和 project.json:
using System;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Mvc.Server.Models;
using Mvc.Server.Services;
using NWebsec.AspNetCore.Middleware;
using System.IO;
using Newtonsoft.Json.Serialization;
using Swashbuckle.Swagger.Model;
using System.Globalization;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.PlatformAbstractions;
using Microsoft.Extensions.Options;
using Mvc.Server.Configuration;
using IdentityServer4.Contrib.AspNetIdentity;
using Mvc.Server.Extensions;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Cors.Internal;
namespace Mvc.Server
public class Startup
public void ConfigureServices(IServiceCollection services)
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("config.json")
.AddEnvironmentVariables()
.Build();
services.AddLocalization(options => options.ResourcesPath = "Resources");
services
.AddMvcCore()
.AddJsonFormatters()
.AddViewLocalization(Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization()
.AddAuthorization();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseNpgsql(configuration["Data:DefaultConnection:ConnectionString"]));
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
// Configure supported cultures and localization options
services.Configure<RequestLocalizationOptions>(options =>
var supportedCultures = new[]
new CultureInfo("en"),
new CultureInfo("bg")
;
// State what the default culture for your application is. This will be used if no specific culture
// can be determined for a given request.
options.DefaultRequestCulture = new RequestCulture(culture: "en", uiCulture: "en");
// You must explicitly state which cultures your application supports.
// These are the cultures the app supports for formatting numbers, dates, etc.
options.SupportedCultures = supportedCultures;
// These are the cultures the app supports for UI strings, i.e. we have localized resources for.
options.SupportedUICultures = supportedCultures;
// You can change which providers are configured to determine the culture for requests, or even add a custom
// provider with your own logic. The providers will be asked in order to provide a culture for each request,
// and the first to provide a non-null result that is in the configured supported cultures list will be used.
// By default, the following built-in providers are configured:
// - QueryStringRequestCultureProvider, sets culture via "culture" and "ui-culture" query string values, useful for testing
// - CookieRequestCultureProvider, sets culture via "ASPNET_CULTURE" cookie
// - AcceptLanguageHeaderRequestCultureProvider, sets culture via the "Accept-Language" request header
//options.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(async context =>
//
// // My custom request culture logic
// return new ProviderCultureResult("en");
//));
);
services.AddCors(options =>
options.AddPolicy("AllowSpecificOrigin",
builder => builder.WithOrigins("http://localhost:18509").AllowAnyHeader().AllowAnyMethod().AllowCredentials());
);
services.Configure<MvcOptions>(options =>
options.Filters.Add(new CorsAuthorizationFilterFactory("AllowSpecificOrigin"));
);
// Register the Identity services.
services.AddIdentity<ApplicationUser, IdentityRole<Guid>>()
.AddEntityFrameworkStores<ApplicationDbContext, Guid>()
.AddDefaultTokenProviders();
services.AddIdentityServer(options =>
//options.SigningCertificate = cert;
// Not implemented yet in IdentityServer4
options.Endpoints.EnableEndSessionEndpoint = false;
)
.AddInMemoryClients(Clients.Get())
.AddInMemoryScopes(Scopes.Get())
.ConfigureAspNetIdentity<ApplicationUser>()
.AddCustomGrantValidator<CustomGrantValidator>()
.SetTemporarySigningCredential();
public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHostingEnvironment env, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory)
app.UseCors("AllowSpecificOrigin");
var locOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(locOptions.Value);
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
else
app.UseExceptionHandler("/Home/Error");
app.UseStaticFiles();
// Add a middleware used to validate access
// tokens and protect the API endpoints.
app.UseOAuthValidation();
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions()
ClientId = "registration",
RequireHttpsMetadata = false,
Authority = "http://localhost:54540/",
);
// Alternatively, you can also use the introspection middleware.
// Using it is recommended if your resource server is in a
// different application/separated from the authorization server.
//
// app.UseOAuthIntrospection(options =>
// options.AutomaticAuthenticate = true;
// options.AutomaticChallenge = true;
// options.Authority = "http://localhost:54540/";
// options.Audience = "resource_server";
// options.ClientId = "resource_server";
// options.ClientSecret = "875sqd4s5d748z78z7ds1ff8zz8814ff88ed8ea4z4zzd";
// );
//app.UseCsp(options => options.DefaultSources(directive => directive.Self())
// .ImageSources(directive => directive.Self()
// .CustomSources("*"))
// .ScriptSources(directive => directive.Self()
// .UnsafeInline())
// .StyleSources(directive => directive.Self()
// .UnsafeInline()));
app.UseXContentTypeOptions();
app.UseXfo(options => options.Deny());
app.UseXXssProtection(options => options.EnabledWithBlockMode());
app.UseIdentity();
app.UseIdentityServer();
var googleOptions = new GoogleOptions
//ClientId = "560027070069-37ldt4kfuohhu3m495hk2j4pjp92d382.apps.googleusercontent.com",
ClientId = "713128117807-iu95ps09o6aegvjhmngql4rbiklg2bt2.apps.googleusercontent.com",
//ClientSecret = "n2Q-GEw9RQjzcRbU3qhfTj8f",
ClientSecret = "6ZRzzsTH9tK69WaenScZwwS9",
Scope = "email",
"openid",
"profile",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/plus.me",
"https://www.googleapis.com/auth/plus.login",
"https://www.googleapis.com/auth/contacts.readonly",
"https://www.googleapis.com/auth/contacts",
"https://www.googleapis.com/auth/plus.login",
"https://www.googleapis.com/auth/user.addresses.read",
"https://www.googleapis.com/auth/user.birthday.read",
"https://www.googleapis.com/auth/user.emails.read",
"https://www.googleapis.com/auth/user.phonenumbers.read",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/plus.login",
,
SaveTokens = true,
AccessType = "offline"
;
//googleOptions.Scope.Add("email");
//googleOptions.Scope.Add("https://www.googleapis.com/auth/contacts");
//googleOptions.Scope.Add("https://www.googleapis.com/auth/contacts.readonly");
//googleOptions.Scope.Add("https://www.googleapis.com/auth/user.addresses.read");
//googleOptions.Scope.Add("https://www.googleapis.com/auth/user.birthday.read");
//googleOptions.Scope.Add("https://www.googleapis.com/auth/user.emails.read");
//googleOptions.Scope.Add("https://www.googleapis.com/auth/user.phonenumbers.read");
app.UseGoogleAuthentication(googleOptions);
app.UseTwitterAuthentication(new TwitterOptions
ConsumerKey = "6XaCTaLbMqfj6ww3zvZ5g",
ConsumerSecret = "Il2eFzGIrYhz6BWjYhVXBPQSfZuS4xoHpSSyD9PI"
);
var fb = new Microsoft.AspNetCore.Builder.FacebookOptions()
AppId = "188223508260529",
AppSecret = "fa7a0168e96e2c85bcab8d247b1b5b66",
;
fb.Scope.Add("email");
fb.Scope.Add("friends_about_me");
fb.Scope.Add("friends_photos");
app.UseFacebookAuthentication(fb);
app.UseStatusCodePagesWithReExecute("/error");
app.UseMvcWithDefaultRoute();
app.UseMvc();
// Enable middleware to serve generated Swagger as a JSON endpoint
//app.UseSwagger();
// Enable middleware to serve swagger-ui assets (html, JS, CSS etc.)
//app.UseSwaggerUi();
项目.json
"dependencies":
"AspNet.Security.OAuth.Introspection": "1.0.0-alpha2-final",
"AspNet.Security.OAuth.Validation": "1.0.0-alpha2-final",
"Base": "1.0.0-*",
"DataAccessLayer": "1.0.0-*",
"Google.Apis": "1.15.0",
"Google.Apis.Auth": "1.15.0",
"Google.Apis.Core": "1.15.0",
"Google.Apis.Drive.v2": "1.15.0.578",
"Google.Apis.Gmail.v1": "1.15.0.580",
"Google.Apis.People.v1": "1.15.0.405",
"IdentityServer4.Contrib.AspNetIdentity": "1.0.0-*",
"Microsoft.AspNetCore.Authentication.Facebook": "1.0.0",
"Microsoft.AspNetCore.Authentication.Google": "1.0.0",
"Microsoft.AspNetCore.Authentication.Twitter": "1.0.0",
"Microsoft.AspNetCore.Cors": "1.0.0",
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
"Microsoft.AspNetCore.Localization": "1.0.0-*",
"Microsoft.AspNetCore.Mvc": "1.0.0",
"Microsoft.AspNetCore.Mvc.Localization": "1.0.0-*",
"Microsoft.AspNetCore.Owin": "1.0.0-rc1-final",
"Microsoft.AspNetCore.Razor.Tools":
"type": "build",
"version": "1.0.0-preview2-final"
,
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
"Microsoft.EntityFrameworkCore.Design": "1.0.0-preview2-final",
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.0",
"Microsoft.Extensions.Configuration.CommandLine": "1.0.0",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
"Microsoft.Extensions.Configuration.Json": "1.0.0",
"Microsoft.Extensions.Logging": "1.0.0",
"Microsoft.Extensions.Logging.Console": "1.0.0",
"Microsoft.Extensions.Logging.Debug": "1.0.0",
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
"Microsoft.NETCore.App":
"version": "1.0.0",
"type": "platform"
,
"Microsoft.NETCore.Portable.Compatibility": "1.0.1",
"Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0",
"Npgsql": "3.1.5",
"Npgsql.EntityFrameworkCore.PostgreSQL": "1.0.1",
"Npgsql.EntityFrameworkCore.PostgreSQL.Design": "1.0.1",
"NWebsec.AspNetCore.Middleware": "1.0.0-gamma1-15",
"Swashbuckle": "6.0.0-beta902",
"IdentityServer4": "1.0.0-beta4-update2",
"Microsoft.IdentityModel.Tokens": "5.0.0",
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0",
"Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": "1.0.0",
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "1.0.0"
,
"tools":
"BundlerMinifier.Core": "2.0.238",
"Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final",
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final"
,
"frameworks":
"netcoreapp1.0":
"imports": [
"dotnet5.6",
"portable-net45+win8"
]
,
"buildOptions":
"emitEntryPoint": true,
"preserveCompilationContext": true,
"xmlDoc": false
,
"runtimeOptions":
"configProperties":
"System.GC.Server": true
,
"publishOptions":
"include": [
"wwwroot",
"Views",
"Areas/**/Views",
"appsettings.json",
"web.config"
]
,
"scripts":
"prepublish": [ "bower install", "dotnet bundle" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
你能帮我解决这个问题吗?
【问题讨论】:
【参考方案1】:那是因为您使用的是services.AddMvcCore()
而不是services.AddMvc()
。
只需在 ConfigureServices 方法中的 services.AddCors
之后添加 services.TryAddTransient<CorsAuthorizationFilter, CorsAuthorizationFilter>();
。
还可以在MvcCorsMvcCoreBuilderExtensions 中检查它是如何完成的
【讨论】:
以上是关于尝试全局启用 CORS 时出现异常的主要内容,如果未能解决你的问题,请参考以下文章
将全局声明的缓冲区写入 FLASH 时出现 STM32 Hardfault 异常
将 HTML5 视频标签分配给 webGL 纹理时出现 CORS/跨域安全异常