.NetCore 使用 Nginx 作为反向代理 - OAuth 异常 - 标头中的非 ASCII 或控制字符无效:0x000D

.NetCore 使用 Nginx 作为反向代理 - OAuth 异常 - 标头中的非 ASCII 或控制字符无效:0x000D

我有一个使用 Nginx 作为反向代理运行的 .net 核心应用程序,当我尝试使用 Facebook 登录时出现此错误:

标头中的非 ASCII 或控制字符无效:0x000D

在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpHeaders.ThrowInvalidHeaderCharacter(Char ch) 在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpHeaders.ValidateHeaderValueCharacters(StringValues& headerValues) 在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseHeaders.SetValueFast(String key, StringValues& value) 在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpHeaders.Microsoft.AspNetCore.Http.IHeaderDictionary.set_Item(String key, StringValues value) 在 Microsoft.AspNetCore.Http.Internal.DefaultHttpResponse.Redirect(String location, Boolean permanent) 在 Microsoft.AspNetCore.Http.HttpResponse.Redirect(String location) 在gringomvc.Startup.RemoteAuthFail(RemoteFailureContext context) 位于 C:\Users\Offir\Documents\Source\Repos\gringomvc\gringomvc\Startup.cs:line 35 位于 Microsoft.AspNetCore.Authentication.RemoteAuthenticationEvents.RemoteFailure(RemoteFailureContext context) 位于 Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync() 位于 Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) 位于 Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context) 位于 Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context) 位于 Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext 上下文)

在我使用 IIS express 的开发环境中,我没有收到此错误,只使用了 Nginx。

启动.cs:

public class Startup
    {
        private IConfiguration _config;

        public Startup(IConfiguration config)
        {
            _config = config;
        }

        private Task RemoteAuthFail(RemoteFailureContext context)
        {
            context.Response.Redirect("/Error/ErrorLogin?message=" + context.Failure.Message);
            context.HandleResponse();
            return Task.CompletedTask;
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {

            //https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-2.2
            //https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-3.0
            //https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/#how-to-use-it-in-nginx
            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
            });

            services.AddDbContext<testContext>(options => options.UseSqlServer(_config.GetConnectionString("DefaultConnection")));

            services.AddAuthentication(options =>
            {
                options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = "Temporary";
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            })
              .AddFacebook(options =>
              {
                  options.AppId = "2235597157716847";
                  options.AppSecret = "03daab4e1c16cecc728bd83e9da1e3af";
                  options.Events.OnRemoteFailure = RemoteAuthFail;
              })
              .AddCookie(options =>
              {
                  options.LoginPath = "/auth/signin";
              })
              .AddCookie("Temporary");



            services.AddMemoryCache();

            services.AddMvc()
                .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
                .AddDataAnnotationsLocalization()
                .AddRazorOptions(opt =>
                {
                    opt.ViewLocationFormats.Add("/Views/{1}/Partials/{0}.cshtml");
                    opt.ViewLocationFormats.Add("/Views/Shared/Partials/{0}.cshtml");
                });

            services.AddBreadcrumbs(GetType().Assembly);
            services.AddScoped<ICacheRepository, CacheRepository>();
            services.AddScoped<ILocationService, LocationService>();
            services.AddScoped<IBusinessService, BusinessService>();
            services.AddScoped<IUserService, UserService>();
            services.AddScoped<ITipService, TipService>();
            services.AddScoped<ITextService, TextService>();
            services.AddScoped<ISeoService, SeoService>();
            services.AddScoped<IImageService, ImageService>();
            services.AddScoped<ICategoryService, CategoryService>();
            services.AddScoped<ICommentService, CommentService>();
            services.AddScoped<IContactUsService, ContactUsService>();
            services.AddScoped<ISearchService, SearchService>();
            services.AddScoped<IInfoService, InfoService>();
            services.AddScoped<ILoggerService, LoggerService>();

            #region localization
            services.AddLocalization(options => options.ResourcesPath = "Resources");

            services.Configure<RequestLocalizationOptions>(options =>
                {
                    var supportedCultures = new List<CultureInfo>
                            {
                                new CultureInfo("he")
                                //new CultureInfo("en"),
                                //new CultureInfo("es")
                            };

                    options.DefaultRequestCulture = new RequestCulture("he");
                    options.SupportedCultures = supportedCultures;
                    options.SupportedUICultures = supportedCultures;
                });

            #endregion

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            //Getting the forward headers from Nginx like we define above
            app.UseForwardedHeaders();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                // Handle unhandled errors
                app.UseExceptionHandler("/Error");
                app.UseStatusCodePagesWithReExecute("/Error/{0}");

                //keep it - not related to the error handling.
                app.UseHsts();
            }


            #region Localization2
            var supportedCultures = new[]
            {
                new CultureInfo("he")
                //new CultureInfo("en"),
                //new CultureInfo("es")
            };

            app.UseRequestLocalization(new RequestLocalizationOptions
            {
                DefaultRequestCulture = new RequestCulture("he"),
                // Formatting numbers, dates, etc.
                SupportedCultures = supportedCultures,
                // UI strings that we have localized.
                SupportedUICultures = supportedCultures
            });

            #endregion

            //redirect site to https
            app.UseHttpsRedirection();


            //use wwwroot for fetching static files
            app.UseStaticFiles();


            // To configure external authentication, 
            // see: http://go.microsoft.com/fwlink/?LinkID=532715
            app.UseAuthentication();

            //Request Localization
            app.UseRequestLocalization();


            app.UseMvcWithDefaultRoute();

        }
    }

Nginx 配置文件:

server {
    listen        80;
    server_name   example.co.il *.example.co.il;
    location / {
        proxy_pass         http://localhost:5000/;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}

Nginx 访问日志:

162.158.154.200 - - [28/Sep/2019:13:30:53 +0000] "GET /signin-facebook?code=AQAKt8zNTbedUb8LKnsuBZpG-eCA_77sfnic6jt_TPE36C7e46MUhFs0i_ZU29PA2qbOClyXdaz6NfA0JW5NcpF6cnLJ4Nd6b7JjGa51-YOiLvKGavUbsAjEQpIOCdQ7cXcx8dOUlyDP5oU-knAi28U-mBfbiurFUv-laYOJY1UMqRIxRrVJKaZ4LwRIHm41d8w0yky0-bOEJPhBvK0mYmBBO86drYsXnOnY-stosIfCxS82D_q0ffJoijelXJoxNOMnJP8BAq-JhtQScfnroWZXf_ilZLCBmTkvl2va-D9x9SSNM8V7cfgQgdSWO31UnA0&state=CfDJ8OVuvnVG6_9Nphg79v1prru4BxrL9c3MKwcP1buvw6zjIE7TbEk3j76UQE4WHJ2YcodUwMoe0oZwguXeJE_Xjg0WSnq00A2RoBUya2ZEGkiug92j8GhTZwrnMkWdRT6aD0tuKJbOa0_DYFcY07ol5pfxmMYswsyZumW1Z_cCHpi4ZW5yzZm4x7NZll_fCS2DJktUa9rIn-c2nhp4pn3CLuY1TnzzedHQEqQkGY3zpEgsbXXCWFVQB_Hb722FacJfgg HTTP/1.1" 500 186229 "https://example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36" "185.108.83.170"
162.158.154.200 - - [28/Sep/2019:13:30:58 +0000] "GET / HTTP/1.1" 200 34605 "https://example.com/signin-facebook?code=AQAKt8zNTbedUb8LKnsuBZpG-eCA_77sfnic6jt_TPE36C7e46MUhFs0i_ZU29PA2qbOClyXdaz6NfA0JW5NcpF6cnLJ4Nd6b7JjGa51-YOiLvKGavUbsAjEQpIOCdQ7cXcx8dOUlyDP5oU-knAi28U-mBfbiurFUv-laYOJY1UMqRIxRrVJKaZ4LaRIHm41d8w0yky0-bOEJPhBvK0mYmBBO86drYsXnOnY-stosIfCxS82D_q0ffJoijelXJoxNOMnJP8BAq-JhtQScfnroWZXf_ilZLCBmTkvl2va-D9x9SSNM8V7cfgQgdSWO31UmA0&state=CfDJ8OVuvnVG6_9Nphg79v1prru4BxrL9c3MKwcP1buvw6zjIE7TbEk3j76UQE4WHJ2YcodUwMoe0oZzguXeJE_Xjg0WSnq00A2RoBUya2ZEGkiug92j8GhTZwrnMkWdRT6aD0tuKJbOa0_DYFcY07ol4pfxmMYswsyZumW1Z_cCHpi4ZW5yzZm4x7NZll_fCS2DJktUa9rIn-c2nhp4pn3CLuY1TnzzedHQEqQkGY3zpEgsbXXCWFVQB_Hb722FacJfgg" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36" "185.108.83.170"

Nginx 错误日志:

2019/09/28 13:30:53 [warn] 8571#8571: *3912 an upstream response is buffered to a temporary file /var/cache/nginx/proxy_temp/2/22/0000000222 while reading upstream, client: 162.158.154.200, server: example.com, request: "GET /signin-facebook?code=AQAKt8zNTbedUb8LKnsuBZpG-eCA_77sfnic6jt_TPE36C7e46MUhFs0i_ZU29PA2qbOClyXdaz6NfA0JW5NcpF6cnLJ4Nd6b7JjGa51-YOiLvKGavUbsAjEQpIOCdQ7cXcx8dOUlyDP5oU-knAi28U-mBfbiurFUv-laYOJY1UMqRIxRrVJKaZ4LwRIHm41d8w0yky0-bOEJPhBvK0mYmBBO86drYsXnOnY-stosIfCxS82D_q0ffJoijelXJoxNOMnJP8BAq-JhtQScfnroWZXf_ilZLCBmTkvl2va-D9x9SSNM8V7cfgQgdSWO31UmA0&state=CfDJ8OVuvnVG6_9Nphg79v1prru4BxrL9c3MKwcP1buvw6zjIE7TbEk3j76UQE4WHJ2YcodUwMoe0oZwguXeJE_Xjg0WSnq00A2RoBUya2ZEGkiug92j8GhTZwrnMkWdRT6aD0tuKJbOa0_DYFcY07ol4pfxmMYswsyZumW1Z_cCHpi4ZW5yzZm4x7NZll_fCS2DJktUa9rIn-c2nhp4pn3CLuY1TnzzedHQEqQkGY3zpEgsbXXCWFVQB_Hb722FacJfgg HTTP/1.1", upstream: "http://127.0.0.1:5000/signin-facebook?code=AQAKt8zNTbedUb8LKnsuBZpG-eCA_77sfnic6jt_TPE36C7e46MUhFs0i_ZU29PA2qbOClyXdaz6NfA0JW5NcpF6cnLJ4Nd6b7JjGa51-YOiLvKGavUbsAjEQpIOCdQ7cXcx8dOUlyDP5oU-knAi28U-mBfbiurFUv-laYOJY1UMqRIxRrVJKaZ4LwRIHm41d8w0yky0-bOEJPhBvK0mYmBBO86drYsXnOnY-stosIfCxS82D_q0ffJoijelXJoxNOMnJP8BAq-JhtQScfnroWZXf_ilZLCBmTkvl2va-D9x9SSNM8V7cfgQgdSWO31UmA0&state=CfDJ8OVuvnVG6_9Nphg79v1prru4BxrL9c3MKwcP1buvw6zjIE7TbEk3j76UQE4WHJ2YcodUwMoe0oZwguXeJE_Xjg0WSnq00A2RoBUya2ZEGkiug92j8GhTZwrnMkWdRT6aD0tuKJbOa0_DYFcY07ol4pfxmMYswsyZumW1Z_cCHpi4ZW5yzZm4x7NZll_fCS2DJktUa9rIn-c2nhp4pn3CLuY1TnzzedHQEqQkGY3zpEgsbXXCWFVQB_Hb722FacJfgg", host: "example.com", referrer: "https://example.com/"

相关内容