.NET Core 3 Web Api Cors fetch 一直 307 Temporary Redirect
.NET Core 3 Web Api Cors fetch 一直 307 Temporary Redirect
继上一篇 .net core 3 web api jwt 一直 401 为添加JWT-BearerToken认证
所述的坑后,
本次为添加CORS跨域
,又踩坑了。
自从 .NET Core 2.2 之后,CORS跨域配置代码发生了很大变化。
在 .NET Core 3.1 中,本作者碰到各种HTTP错误,诸如 500、307、401
等错误代码...
在必应Bing和不断Debug调整配置代码位置后,得知:
AllowAnyOrigin
方法,在新的 CORS 中间件已经被阻止使用允许任意 Origin,所以该方法无效。AllowCredentials
方法,自从 .NET Core 2.2 之后,不允许和AllowAnyOrigin
同时调用。WithOrigins
方法,在 .NET Core 3.1 中有bug,具体原因未知,暂时只能用SetIsOriginAllowed(t=> true)
代替,等效.AllowAnyOrigin
方法。- 创建项目默认的模板中,
app.UseHttpsRedirection()
在前面,所以我将app.UseCors()
放在它后面,这是导致HTTP 307 Temporary Redirect
福报的根本原因之一。 - 度娘告诉我,
app.UseCors()
方法要在app.UseAuthentication()
之后,是误人子弟的,其实放在它前面也可以,并且app.UseCors()
要在app.UseRouting()
之后,app.UseEndpoints()
和app.UseHttpsRedirection()
之前 - 使用fetch跨域请求时,要注意controller的action是否有设置除了
HttpOptions
之外的其它Http Method方法,如果有要加上HttpOptions
标记特性,因为fetch跨域请求会先执行OPTIONS
预请求。 - 使用fetch请求需要JWT认证的接口时,除了在HTTP Headers设置
Authorization
之外,还需要设置'credentials': 'include'
。 - 写
app.UseXxxxxx
方法,引入中间件时,要注意管道(Middleware
)注册顺序。
参考:
- CORS配置:https://docs.microsoft.com/zh-cn/aspnet/core/security/cors?view=aspnetcore-3.1
- JWT认证:https://docs.microsoft.com/zh-cn/aspnet/core/security/authentication/?view=aspnetcore-3.1
- Cors Issue: https://github.com/dotnet/aspnetcore/issues/16672
- Forum: https://forums.asp.net/t/2160821.aspx?CORS+in+ASP+NET+Core+3+x
源代码
以下是在 .NET Core 3.1下经过严谨测试,可以JWT认证
、CORS跨域
、IIS托管
、自寄主运行
的源代码,仅供参考。
WebApi.csproj
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp3.1</TargetFramework> <RootNamespace>WebApi</RootNamespace> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.2" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.2" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.2" /> <PackageReference Include="Microsoft.Extensions.Logging.EventSource" Version="3.1.2" /> <PackageReference Include="Microsoft.Extensions.Logging.TraceSource" Version="3.1.2" /> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.2" /> <PackageReference Include="Microsoft.TeamFoundationServer.Client" Version="16.153.0" /> <PackageReference Include="Microsoft.VisualStudio.Services.Client" Version="16.153.0" /> <PackageReference Include="Microsoft.VisualStudio.Services.InteractiveClient" Version="16.153.0" /> <PackageReference Include="NLog.Web.AspNetCore" Version="4.9.0" /> </ItemGroup></Project>
Program.cs
using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.Hosting;using Microsoft.Extensions.Logging;using NLog.Extensions.Logging;using System.Diagnostics;using System.IO;namespace WebApi{ public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) { return Host.CreateDefaultBuilder(args) .ConfigureLogging((context, logging) => { logging.ClearProviders()#if DEBUG .AddConsole() .AddDebug() .AddEventLog() .AddTraceSource(new SourceSwitch(nameof(Program), "Warning"), new ConsoleTraceListener())#endif .AddNLog(); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseContentRoot(Directory.GetCurrentDirectory()) .UseKestrel() .UseIISIntegration() .UseIIS() .UseStartup<Startup>(); }); } }}
Startup.cs
using MCS.Vsts.Options;using MCS.Vsts.Services;using Microsoft.AspNetCore.Authentication.JwtBearer;using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.AspNetCore.HttpOverrides;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;using Microsoft.IdentityModel.Tokens;using System.Text;namespace WebApi{ public class Startup { public IConfiguration Configuration { get; } public Startup(IConfiguration configuration) { Configuration = configuration; } public void ConfigureServices(IServiceCollection services) { services.AddControllers(); //认证 services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { var secretBytes = Encoding.UTF8.GetBytes(Configuration["ServerConfig:Secret"]); options.TokenValidationParameters = new TokenValidationParameters() { IssuerSigningKey = new SymmetricSecurityKey(secretBytes), ValidateIssuer = false, ValidateAudience = false, ValidateActor = false, RequireSignedTokens = true, RequireExpirationTime = true, ValidateLifetime = true }; }); //跨域 services.AddCors(options => { options.AddDefaultPolicy(builder => { builder //允许任何来源的主机访问 //TODO: 新的 CORS 中间件已经阻止允许任意 Origin,即设置 AllowAnyOrigin 也不会生效 //AllowAnyOrigin() //设置允许访问的域 //TODO: 目前.NET Core 3.1 有 bug, 暂时通过 SetIsOriginAllowed 解决 //.WithOrigins(Configuration["CorsConfig:Origin"]) .SetIsOriginAllowed(t=> true) .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials(); }); }); //TODO: do something... } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { //Enabled HSTS app.UseHsts(); } //TODO: 要放在UseCors之后 //app.UseHttpsRedirection(); app.UseRouting(); app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto }); //TODO: UseCors要在UseRouting之后,UseEndpoints 和 UseHttpsRedirection 之前 app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); app.UseHttpsRedirection(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } }}
appsettings.json
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "https_port": 44370, "urls": "http://*:50867", "ServerConfig": { "Secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, "CorsConfig": { "BaseUri": "http://myserver" }}
赞 (0)