React应用调用ABP.IO Swagger接口出现CORS错误(OpenIddict)
解决ABP.IO后端对接React前端的CORS跨域问题
1. 配置后端appsettings.json的CORS规则
在后端HttpApiHost项目的appsettings.json中添加CORS配置,将AllowedOrigins替换为你的React应用实际运行地址(比如http://localhost:3000):
"App": { "CorsOrigins": "http://localhost:3000" }
2. 在模块类中启用CORS服务与中间件
打开后端模块类(如YourProjectNameHttpApiHostModule),在ConfigureServices方法中添加CORS服务配置:
public override void ConfigureServices(ServiceConfigurationContext context) { var configuration = context.Services.GetConfiguration(); // 其他配置... // 配置CORS策略 context.Services.AddCors(options => { options.AddPolicy("AllowReactOrigin", policy => { policy.WithOrigins(configuration["App:CorsOrigins"].Split(",", StringSplitOptions.RemoveEmptyEntries)) .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); }
接着在Configure方法中添加CORS中间件,注意中间件顺序必须放在UseRouting之后,UseAuthentication、UseAuthorization之前:
public override void Configure(ApplicationConfigurationContext context) { var app = context.GetApplicationBuilder(); // 其他中间件配置... app.UseRouting(); // 启用CORS策略 app.UseCors("AllowReactOrigin"); app.UseAuthentication(); app.UseAuthorization(); // 其他中间件... }
3. 配置OpenIddict客户端的跨域允许
你已经配置了OpenIddict数据种子,需要补充客户端的AllowedCorsOrigins配置。在OpenIdDictDataSeedContributor的SeedAsync方法中,找到客户端创建的代码,添加允许的React地址:
var clientId = "YourProjectName_App"; await CreateClientAsync( name: clientId, scopes: commonScopes.Union(new[] { "YourProjectName" }), grantTypes: new[] { "authorization_code", "refresh_token" }, secret: "1q2w3e*", redirectUris: new[] { "http://localhost:3000/authentication/login-callback" }, postLogoutRedirectUris: new[] { "http://localhost:3000/authentication/logout-callback" }, allowedCorsOrigins: new[] { "http://localhost:3000" } );
如果你的CreateClientAsync方法没有allowedCorsOrigins参数,需要修改方法逻辑,在创建OpenIddictApplicationDescriptor时添加:
private async Task CreateClientAsync( string name, IEnumerable<string> scopes, IEnumerable<string> grantTypes, string secret = null, IEnumerable<string> redirectUris = null, IEnumerable<string> postLogoutRedirectUris = null, IEnumerable<string> allowedCorsOrigins = null) { var application = await _openIddictApplicationManager.FindByClientIdAsync(name); if (application != null) return; var descriptor = new OpenIddictApplicationDescriptor { ClientId = name, DisplayName = name, RedirectUris = redirectUris?.Select(uri => new Uri(uri)).ToList(), PostLogoutRedirectUris = postLogoutRedirectUris?.Select(uri => new Uri(uri)).ToList(), Permissions = { OpenIddictConstants.Permissions.Endpoints.Authorization, OpenIddictConstants.Permissions.Endpoints.Logout, OpenIddictConstants.Permissions.Endpoints.Token, OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, OpenIddictConstants.Permissions.GrantTypes.RefreshToken }, Requirements = { OpenIddictConstants.Requirements.Features.ProofKeyForCodeExchange } }; // 添加允许的跨域Origin if (allowedCorsOrigins != null) { foreach (var origin in allowedCorsOrigins) { descriptor.AllowedCorsOrigins.Add(new Uri(origin)); } } // 配置客户端密钥(如果需要) if (!string.IsNullOrEmpty(secret)) { descriptor.ClientSecret = secret; } await _openIddictApplicationManager.CreateAsync(descriptor); }
4. 验证与注意事项
- 确保配置中的React地址和实际运行地址完全一致(包括HTTP/HTTPS、端口号,不能有末尾斜杠的差异)
- 修改配置后务必重启后端服务,确保配置生效
- 你的React用HTTP、后端用HTTPS属于混合内容场景,浏览器可能触发额外限制,建议React也改用HTTPS启动(执行
HTTPS=true npm start),避免后续其他问题
内容的提问来源于stack exchange,提问作者Sebbas
相关产品推荐
相关产品推荐

