简体   繁体   English

CORS Dotnet 5 问题 Web Api

[英]CORS Issue with Dotnet 5 Web Api

I have a dotnet 5 web API with an Angular2+ front end, which I'm building from a previous 3.1 MVC version of the app.我有一个带有 Angular2+ 前端的 dotnet 5 web API,我是从以前的 3.1 MVC 版本的应用程序构建的。 I'm having an issue with CORS while looking to authenticate with Yahoo that I did not have with the MVC version.我在使用 MVC 版本没有的雅虎身份验证时遇到了 CORS 的问题。 The error I am getting is:我得到的错误是:

"Access to XMLHttpRequest at 'https://api.login.yahoo.com...' (redirected from 'https://localhost:5003/api/draft/yahooauth/') from origin 'https://localhost:5003' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource." “从源 'https://localhost: 5003' 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”header。”

My API Controller:我的 API Controller:

        [EnableCors("MyPolicy")]
        [HttpPost("yahooauth")]
        public void YahooAuth()
        {
            string leftUrl = string.Format("{0}://{1}", HttpContext.Request.Scheme, HttpContext.Request.Host);

            string returnUrl = $"{leftUrl}/api/draft/yahooexchange";

            string id = configuration["YahooClientId"];
            string secret = configuration["YahooClientSecret"];

            string url = $"https://api.login.yahoo.com/oauth2/request_auth?client_id={id}&redirect_uri={returnUrl}&response_type=code&language=en-us";

            Response.Redirect(url);            
        }

        [HttpGet("yahooexchange/{code}")]
        public IActionResult yahooexchange(string code)
        {
            // Code that is supposed to be triggered with returnUrl from Yahoo
        }

Startup.cs:启动.cs:

public class Startup
    {

        public Startup(IConfiguration configuration) => Configuration = configuration;

        public IConfiguration Configuration { get; }

        readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential 
                // cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                // requires using Microsoft.AspNetCore.Http;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddDbContext<IdentityDbCxt>(options => options.UseSqlServer(Configuration.GetConnectionString("IdentityDb")));
            services.AddDbContext<DraftContext>(options => options.UseSqlServer(Configuration.GetConnectionString("FSDraftDb")));

            services.AddIdentity<AppUser, IdentityRole>(opts =>
            {
                opts.User.RequireUniqueEmail = true;
            })
                .AddEntityFrameworkStores<IdentityDbCxt>()
                .AddDefaultTokenProviders();

            services.AddTransient<IEmailSender, EmailSender>();
            services.AddTransient<IAPICall, APICall>();

            services.AddTransient<IDraftService, DraftService>();

            services.AddCors(options =>
            {
                options.AddPolicy("MyPolicy",
                    builder =>
                    {
                        builder.WithOrigins("*")
                                            .AllowAnyHeader()
                                            .AllowAnyMethod();
                    });
            });


            services.AddMvc()
                .AddRazorRuntimeCompilation();
            services.AddMemoryCache();
            services.AddSession();
            services.AddSingleton<IHtmlSanitizer, HtmlSanitizer>();
            services.AddControllersWithViews(/*options =>
                options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute())*/);
            

            services.AddRazorPages();

            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1",
                    new OpenApiInfo { Title = "API", Version = "v1" });
            });

            services
                .AddControllers()
                .AddNewtonsoftJson();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostEnvironment env, IServiceProvider services)
        {
            //app.UseMiddleware<GCMiddleware>();
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }


            app.UseStatusCodePages();
            //app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseAuthentication();
            app.UseSession();
            app.UseRouting();
            app.UseCors();
            app.UseAuthorization();
            
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}");
                endpoints.MapControllerRoute(
                    name: "angular_fallback",
                    pattern: "{target:regex(draft|data|keeper|adminapi|admin`):nonfile}/{*catchall}",
                    defaults: new { controller = "Home", action = "Index" });
                endpoints.MapRazorPages();
            });

            app.UseSwagger();
            app.UseSwaggerUI(options =>
            {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "API");
            });

            app.UseSpa(spa =>
            {
                string strategy = Configuration.GetValue<string>("DevTools:ConnectionStrategy");

                if (strategy == "proxy")
                {
                    spa.UseProxyToSpaDevelopmentServer("http://127.0.0.1:4200");
                }
                else if (strategy == "managed")
                {
                    spa.Options.SourcePath = "../ClientApp";
                    spa.UseAngularCliServer("start");
                }
            });



        }
    }

I've looked at a few sources, including one quite hopeful post here, but this did not solve my problem: Problems with CORS Response to preflight in dotnet core 3.1我查看了一些来源,包括一个非常有希望的帖子,但这并没有解决我的问题: CORS 的问题对 dotnet core 3.1 中的预检的响应

In case it's helpful, I'm looking to do step 2: https://developer.yahoo.com/oauth2/guide/flows_authcode/如果有帮助,我希望执行第 2 步: https://developer.yahoo.com/oauth2/guide/flows_authcode/

Edit: This is the documentation I used regarding CORS: https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-5.0#attr编辑:这是我使用的关于 CORS 的文档: https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-5.0#attr

Try to use this syntax and move AddCors to the top of ConfigureServices.尝试使用此语法并将 AddCors 移动到 ConfigureServices 的顶部。 Assign name to UseRouting.为 UseRouting 分配名称。

services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
            {
                builder.AllowAnyOrigin()
                       .AllowAnyMethod()
                       .AllowAnyHeader();
            }));

.......
            ....
            app.UseRouting();
            app.UseCors("MyPolicy");
             app.UseAuthentication();
            app.UseAuthorization();
             .....

So I ended up figuring out a workaround and just created a new MVC controller, as my previous MVC app worked fine.所以我最终找到了一个解决方法,并创建了一个新的 MVC controller,因为我以前的 MVC 应用程序运行良好。

In addition, I realized that I had not updated my Yahoo Developer App for the new return URI.此外,我意识到我没有为新的返回 URI 更新我的 Yahoo Developer App。 This did not fix my CORS problem, but it was preventing this from properly working.这并没有解决我的 CORS 问题,但它阻止了它正常工作。

Code from Angular to go to the new controller.从 Angular 到 go 到新的 controller 的代码。

window.location.href = "https://localhost:5003/yahoo/index";

My MVC Controller:我的 MVC Controller:

public class YahooController : Controller
    {
        private IAPICall apiCall;

        public YahooController(IAPICall aCall)
        {
            apiCall = aCall;
        }

        // getting session data on player values
        private DraftService GetDS()
        {
            DraftService draftService = HttpContext.Session.GetJson<DraftService>("DraftService") ?? new DraftService();
            return draftService;
        }

        // saving session data on player values
        private void SaveDS(DraftService ds)
        {
            HttpContext.Session.SetJson("DraftService", ds);
        }

        [HttpGet]
        public void Index()
        {
            string returnUrl = Url.Action("yahooexchange",
                  "yahoo", new
                  {

                  },
                   protocol: HttpContext.Request.Scheme);
            
            string url = apiCall.YahooAuthUrl(returnUrl);

            Response.Redirect(url);
        }

        public void yahooexchange(string code)
        {
            string content = apiCall.YahooGetToken(code);

            var jContent = JsonConvert.DeserializeObject<JObject>(content);


            string accessToken = jContent.GetValue("access_token").ToString();
            string refreshToken = jContent.GetValue("refresh_token").ToString();

            string leftUrl = string.Format("{0}://{1}", HttpContext.Request.Scheme, HttpContext.Request.Host);

            DraftService ds = GetDS();


            ds.YahooAccessToken = accessToken;
            ds.YahooRefreshToken = refreshToken;

            SaveDS(ds);

            string url = leftUrl + "/draft/" + ds.DraftId;

            Response.Redirect(url);

        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM