Cross-Origin Request Blocked:(原因:CORS 请求未成功)
Cross-Origin Request Blocked: (Reason: CORS request did not succeed)
我正在开发一个全栈应用程序,后端使用 ASP.NET core 5.0 Web Api,前端使用 Angular 12。
向后端发送 http post 请求时,我收到与 CORS 策略相关的错误。
错误是:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5001/api/v1/user/login. (Reason: CORS request did not succeed).
我看了这个link:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSDidNotSucceed,但它没有给我足够的信息来提出解决方案
我认为我的问题可能与第一个要点有关:
Trying to access an https resource that has an invalid certificate will cause this error
因为我的前端使用的是http协议,我的后端使用的是https协议。
什么是有效证书?
我的网络浏览器中也没有安装广告拦截器,所以我想不出还有什么可以尝试的,因为我相信我在以下代码中启用了 CORS。
有什么问题吗?我可能缺少某种配置或其他东西?
代码示例
后端
startup.cs
// startup.cs
using MyApi.Installers;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace MyApi
{
public class Startup
{
public Startup(IConfiguration configuration) => Configuration = configuration;
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// CORS CONFIGURED HERE
services.AddCors(options =>
{
options.AddPolicy("CorsApi",
builder => builder.WithOrigins("http://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod());
});
// This is an extension method that installs swagger, jwt, services, etc...
// I can add those also if need be
services.InstallServicesInAssembly(Configuration);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
SwaggerOptions swaggerOptions = new SwaggerOptions();
Configuration.GetSection(nameof(SwaggerOptions)).Bind(swaggerOptions);
app.UseSwagger(options => options.RouteTemplate = swaggerOptions.JsonRoute);
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint(swaggerOptions.UiEndpoint, swaggerOptions.Description);
options.RoutePrefix = System.String.Empty;
});
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
// CORS ENABLED HERE
app.UseCors("CorsApi");
app.UseAuthorization();
app.UseEndpoints(endpoints => endpoints.MapControllers());
}
}
}
UserController.cs -> 登录功能
// UserController.cs -> Login function
[HttpPost(ApiRoutes.User.Login)]
public IActionResult Login([FromBody] UserLoginRequest request)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
// Validates users credentials
if (!_userService.IsValidUserCredentials(request.Email, request.Password))
{
return Unauthorized();
}
return Ok(});
}
前端
auth-service.ts
// auth.service.ts
export class AuthService {
private readonly baseUrl = 'https://localhost:5001/api/v1';
// Adds CORS header to the request?
private httpOptions = { headers: new HttpHeaders({ 'Content-Type':'application/json','Access-Control-Allow-Origins':'*'})};
constructor(
private http: HttpClient
) { }
login(email: string, password: string): Observable<any> {
let postData = new FormData();
postData.append('email', email);
postData.append('password', password);
return this.http.post<any>(`${this.baseUrl}/user/login`, postData, this.httpOptions);
}
}
login.component.ts
// login.component.ts
export class LoginComponent implements OnInit {
loginForm = this.fb.group({
email: ['', Validators.compose([Validators.email, Validators.required])],
password: ['', Validators.required]
});
constructor(
private authService: AuthService,
private router: Router,
private fb: FormBuilder,
) { }
ngOnInit(): void { }
get f() {
return this.loginForm.controls;
}
login(form: FormGroup): void {
// These output in console window
console.log(this.f.email.value);
console.log(this.f.password.value);
// Error here
this.authService.login(this.f.email.value, this.f.password.value).subscribe(
response => {
// This does not get output
console.log(response);
//this.router.navigate(['/home']);
},
error => console.log(error)
);
}
}
我尽量使代码尽可能简单。
编辑:忘了说我也启用了这个:
尝试将 UseCors 放在 UseRouting 和 UseAuthorization 之间
app.UseRouting();
app.UseCors("CorsApi");
app.UseAuthorization();
为 AddCors 尝试此语法
services.AddCors(o => o.AddPolicy("CorsApi", builder =>
{
builder.WithOrigins("http://localhost:4200")
.AllowAnyMethod()
.AllowAnyHeader();
}));
也许如果它仍然不起作用,也将其删除
'Access-Control-Allow-Origins':'*'
所以,我不一定能解释为什么这解决了我的问题,但确实...
在 chrome 我还去了:chrome://settings/security -> 管理证书 -> 删除本地主机证书。
然后在 Visual Studio 终端 运行 命令:dotnet dev-certs https --trust
经过以下作品
在Startup.cs中:
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
在 startup.cs -> ConfigureServices:
services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
);
});
在Startup.cs -> 配置:
app.UseRouting();
app.UseAuthorization();
app.UseAuthentication();
// ...
// UseCors must be between routing and endpoints
app.UseCors(MyAllowSpecificOrigins);
// ...
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
我正在开发一个全栈应用程序,后端使用 ASP.NET core 5.0 Web Api,前端使用 Angular 12。
向后端发送 http post 请求时,我收到与 CORS 策略相关的错误。
错误是:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5001/api/v1/user/login. (Reason: CORS request did not succeed).
我看了这个link: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSDidNotSucceed,但它没有给我足够的信息来提出解决方案
我认为我的问题可能与第一个要点有关:
Trying to access an https resource that has an invalid certificate will cause this error
因为我的前端使用的是http协议,我的后端使用的是https协议。
什么是有效证书?
我的网络浏览器中也没有安装广告拦截器,所以我想不出还有什么可以尝试的,因为我相信我在以下代码中启用了 CORS。
有什么问题吗?我可能缺少某种配置或其他东西?
代码示例
后端
startup.cs
// startup.cs
using MyApi.Installers;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace MyApi
{
public class Startup
{
public Startup(IConfiguration configuration) => Configuration = configuration;
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// CORS CONFIGURED HERE
services.AddCors(options =>
{
options.AddPolicy("CorsApi",
builder => builder.WithOrigins("http://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod());
});
// This is an extension method that installs swagger, jwt, services, etc...
// I can add those also if need be
services.InstallServicesInAssembly(Configuration);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
SwaggerOptions swaggerOptions = new SwaggerOptions();
Configuration.GetSection(nameof(SwaggerOptions)).Bind(swaggerOptions);
app.UseSwagger(options => options.RouteTemplate = swaggerOptions.JsonRoute);
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint(swaggerOptions.UiEndpoint, swaggerOptions.Description);
options.RoutePrefix = System.String.Empty;
});
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
// CORS ENABLED HERE
app.UseCors("CorsApi");
app.UseAuthorization();
app.UseEndpoints(endpoints => endpoints.MapControllers());
}
}
}
UserController.cs -> 登录功能
// UserController.cs -> Login function
[HttpPost(ApiRoutes.User.Login)]
public IActionResult Login([FromBody] UserLoginRequest request)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
// Validates users credentials
if (!_userService.IsValidUserCredentials(request.Email, request.Password))
{
return Unauthorized();
}
return Ok(});
}
前端
auth-service.ts
// auth.service.ts
export class AuthService {
private readonly baseUrl = 'https://localhost:5001/api/v1';
// Adds CORS header to the request?
private httpOptions = { headers: new HttpHeaders({ 'Content-Type':'application/json','Access-Control-Allow-Origins':'*'})};
constructor(
private http: HttpClient
) { }
login(email: string, password: string): Observable<any> {
let postData = new FormData();
postData.append('email', email);
postData.append('password', password);
return this.http.post<any>(`${this.baseUrl}/user/login`, postData, this.httpOptions);
}
}
login.component.ts
// login.component.ts
export class LoginComponent implements OnInit {
loginForm = this.fb.group({
email: ['', Validators.compose([Validators.email, Validators.required])],
password: ['', Validators.required]
});
constructor(
private authService: AuthService,
private router: Router,
private fb: FormBuilder,
) { }
ngOnInit(): void { }
get f() {
return this.loginForm.controls;
}
login(form: FormGroup): void {
// These output in console window
console.log(this.f.email.value);
console.log(this.f.password.value);
// Error here
this.authService.login(this.f.email.value, this.f.password.value).subscribe(
response => {
// This does not get output
console.log(response);
//this.router.navigate(['/home']);
},
error => console.log(error)
);
}
}
我尽量使代码尽可能简单。
编辑:忘了说我也启用了这个:
尝试将 UseCors 放在 UseRouting 和 UseAuthorization 之间
app.UseRouting();
app.UseCors("CorsApi");
app.UseAuthorization();
为 AddCors 尝试此语法
services.AddCors(o => o.AddPolicy("CorsApi", builder =>
{
builder.WithOrigins("http://localhost:4200")
.AllowAnyMethod()
.AllowAnyHeader();
}));
也许如果它仍然不起作用,也将其删除
'Access-Control-Allow-Origins':'*'
所以,我不一定能解释为什么这解决了我的问题,但确实...
在 chrome 我还去了:chrome://settings/security -> 管理证书 -> 删除本地主机证书。
然后在 Visual Studio 终端 运行 命令:dotnet dev-certs https --trust
经过以下作品
在Startup.cs中:
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
在 startup.cs -> ConfigureServices:
services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
);
});
在Startup.cs -> 配置:
app.UseRouting();
app.UseAuthorization();
app.UseAuthentication();
// ...
// UseCors must be between routing and endpoints
app.UseCors(MyAllowSpecificOrigins);
// ...
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});