在Angular 7 Web应用程序中仅针对“ https:// localhost:44361 / connect / token”获取错误“被CORS策略阻止”

时间:2019-02-04 05:31:01

标签: asp.net-core asp.net-core-webapi openid-connect angular7

完全错误如下所示。

Access to XMLHttpRequest at 'https://localhost:44361/connect/token' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

我在.net核心Web api的启动类中启用了核心策略,如下所示。

  

我的ConfigureService方法

        public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        services.AddDbContext<LEAFDDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), builder =>
        {
            builder.EnableRetryOnFailure(5, TimeSpan.FromSeconds(10), null);
        }));

        services.AddIdentity<ApplicationUser, ApplicationRole>()
                .AddEntityFrameworkStores<LEAFDDbContext>()
                .AddDefaultTokenProviders();

        services.AddCors(options =>
        {
        options.AddPolicy("CorsPolicy",
            builder => builder.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials());
        });
        Installer.ConfigureServices(services);
        //services.AddCors();
        //services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        //services.AddSingleton<IAuthenticationSchemeProvider, CustomAuthenticationSchemeProvider>();


        //services.AddAuthentication(options =>
        //{
        //    //options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        //    //options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        //    //options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        //    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        //    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        //})
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddCookie(options =>
        {
            options.Events.OnRedirectToLogin = ctx =>
            {
                // if it is an ajax/api request, don't redirect
                // to login page.
                if (!(IsAjaxRequest(ctx.Request) || IsApiRequest(ctx.Request)))
                {
                    ctx.Response.Redirect(ctx.RedirectUri);
                    return Task.CompletedTask;
                }
                ctx.Response.StatusCode = StatusCodes.Status401Unauthorized;
                return ctx.Response.WriteAsync("Unauthorized");
            };
        })
        .AddOAuthValidation()
        //services.AddAuthentication()
        .AddOpenIdConnectServer(options =>
        {
            options.Provider = new AuthorizationProvider();

            // Enable the authorization and token endpoints.
            options.AuthorizationEndpointPath = "/connect/authorize";
            options.TokenEndpointPath = "/connect/token";
            options.AllowInsecureHttp = true;

            // Note: to override the default access token format and use JWT, assign AccessTokenHandler:
            //
            options.AccessTokenHandler = new JwtSecurityTokenHandler
            {
                InboundClaimTypeMap = new Dictionary<string, string>(),
                OutboundClaimTypeMap = new Dictionary<string, string>()
            };

            //
            // Note: when using JWT as the access token format, you have to register a signing key.
            //
            // You can register a new ephemeral key, that is discarded when the application shuts down.
            // Tokens signed using this key are automatically invalidated and thus this method
            // should only be used during development:
            //
            options.SigningCredentials.AddEphemeralKey();
            //
            // On production, using a X.509 certificate stored in the machine store is recommended.
            // You can generate a self-signed certificate using Pluralsight's self-cert utility:
            // https://s3.amazonaws.com/pluralsight-free/keith-brown/samples/SelfCert.zip
            //
            //options.SigningCredentials.AddCertificate("7D2A741FE34CC2C7369237A5F2078988E17A6A75");

        });

    }
  

配置方法

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }
        //app.UseOAuthValidation();
        app.UseAuthentication();
        app.UseMvc();

        app.UseMiddleware();

        app.UseCors("CorsPolicy");
        //app.UseCors(builder => builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().AllowCredentials());
        app.UseWelcomePage();


    }

对于除“ https://localhost:44361/connect/token”之外的所有其他呼叫,此操作都按预期进行:获取令牌时。

我正在将所有请求从Angular 7 Web应用发送到.net核心Web API。

作为一种变通办法,我已经安装了Google chrome的跨域资源共享扩展程序,并且需要更改代码级别才能永久解决此问题。

2 个答案:

答案 0 :(得分:0)

这是我想出的最终解决方案。

我不是直接从Angular 7应用程序中调用“ https://localhost:44361/connect/token”,而是在API控制器中创建了一个方法,该方法将调用上述调用并获取令牌。因此,只要需要,我只需在API控制器中调用新创建的方法即可。

新的api调用如下

        [HttpPost]
    [Route("/api/[controller]/Token")]
    [EnableCors("CorsPolicy")]
    public async Task<ContentResult> Token(LoginTokenRequestModel model)
    {
        string UserId = string.Empty;
        try
        {
            using (HttpClient httpClient = new HttpClient())
            {
                if (!String.IsNullOrEmpty(model.Email))
                {

                    var content = new FormUrlEncodedContent(new KeyValuePair<string, string>[]{
                         new KeyValuePair<string, string>("grant_type", model.grant_type),
                         new KeyValuePair<string, string>("client_secret", model.client_secret),
                         new KeyValuePair<string, string>("client_id", model.client_id),
                         new KeyValuePair<string, string>("username", model.Email),
                         new KeyValuePair<string, string>("password", model.Password),
                    });
                    string apiURL = "https://localhost:44361";

                    var response = await httpClient.PostAsync(apiURL + "/connect/token", content);
                    var resultContent = await response.Content.ReadAsStringAsync();

                    if (response.IsSuccessStatusCode)
                    {
                        var token = JsonConvert.DeserializeObject<object>(resultContent);
                        return new ContentResult
                        {
                            Content = token.ToString(),
                            ContentType = "text/plain",
                            StatusCode = 200
                        };
                    }

                    return new ContentResult
                    {
                        Content = JsonConvert.DeserializeObject<object>(resultContent).ToString(),
                        ContentType = "text/plain",
                        StatusCode = 200
                    };
                }
            }
        }

        catch (Exception ex)
        {
            return new ContentResult
            {
                Content = ex.Message,
                ContentType = "text/plain",
                StatusCode = 400
            };
        }
        return new ContentResult
        {
            Content = "",
            ContentType = "text/plain",
            StatusCode = 400
        };

    }

这解决了我的问题。

答案 1 :(得分:0)

使用app.UseCors() 之前 app.useMvc()。关于中间件调用,顺序很重要。就个人而言,我将其保存在确定if-else的环境中。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseCors("CorsDevPolicy");
        }
        else
        {
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseMiddleware(typeof(ErrorHandlingMiddleware));
        app.UseMvc();
    }