尝试全局启用 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&lt;CorsAuthorizationFilter, CorsAuthorizationFilter&gt;();

还可以在MvcCorsMvcCoreBuilderExtensions 中检查它是如何完成的

【讨论】:

以上是关于尝试全局启用 CORS 时出现异常的主要内容,如果未能解决你的问题,请参考以下文章

将全局声明的缓冲区写入 FLASH 时出现 STM32 Hardfault 异常

将 HTML5 视频标签分配给 webGL 纹理时出现 CORS/跨域安全异常

启用缩小时处理任务时出现异常

反编译apk时出现异常

VS2010 F5调试时出现:“ 尝试运行项目时出错:未捕获通过反射调用的方法引发的异常”解决

更新文档时出现 XMLHttpRequest 错误,但应启用 CORS