跨源请求被阻止:同源策略不允许读取远程资源(原因:CORS 标头丢失)

问题描述 投票:0回答:1

**

我正在尝试使用 Angular 向我的 .Net 8 Web API 发出 POST 请求,并且发生此错误。

**

这是我的 API 控制器 .Net 8 Web Api

[ApiController]
[Route("api/[controller]")]
public class AccountController : BaseController
{
 [HttpPost]
[Route("login")]
public async Task<IActionResult> Login([FromBody] LoginInput loginInput)
{
    logger.LogInformation($"Login attempt for {loginInput.Email}");

    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    try
    {
        //Validate Email and Password
        if (!await authService.ValidateUserWithPassword(loginInput))
        {
            return Unauthorized("Incorrect Username or password");
        }

        var account = await accountService.FindAccountByEmailAsync(loginInput.Email);
        //var roles = await accountService.GetRolesAsync(user);

        //
        var token = await authService.GenerateJwtToken(account);

        var results = new { jwtToken = "Bearer " + token, id = account.Id };
        //var results = new { jwtToken = "Bearer " + token, roles = roles, id = account.Id };

        return Accepted(results);
    }
    catch (Exception ex)
    {
        logger.LogError(ex, $"something went wrong {nameof(Login)}: ");

        return StatusCode(500, $"Internal server Error");
    }
}
}

程序.cs

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using student_management_sys.Configs;
using student_management_sys.Entity;
using student_management_sys.Services;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

// Configure log4net logging
builder.Logging.ClearProviders();
builder.Logging.AddLog4Net("log4net.config");

// Enable CORS
var clientsCORSPolicy = "MyAllowSpecificOrigins";

builder.Services.AddCors(options =>
{
    options.AddPolicy(clientsCORSPolicy, policy =>
    {
        policy.WithOrigins("http://localhost:4200");
        policy.AllowAnyHeader();
        policy.AllowAnyMethod();
        policy.AllowCredentials();
    });
});

builder.Services.AddControllers();

builder.Services.AddDbContext<StudManSysDBContext>(options =>
                options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddIdentity<Account, IdentityRole>()
                .AddEntityFrameworkStores<StudManSysDBContext>()
                .AddDefaultTokenProviders();

builder.Services.Configure<DataProtectionTokenProviderOptions>(options =>
{
        options.TokenLifespan = TimeSpan.FromHours(2);
});

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
    {
        var jwtOptions = builder.Configuration.GetSection("JwtOptions");

        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = false,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = jwtOptions.GetSection("Issuer").Value, 
            ValidAudience = jwtOptions.GetSection("Audiance").Value,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtOptions.GetSection("Key").Value)) 
        };
    }
);


// Configure authorization
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AdminPolicy", policy => policy.RequireRole("Admin"));
    options.AddPolicy("StudentPolicy", policy => policy.RequireRole("Student"));
    options.AddPolicy("ParentPolicy", policy => policy.RequireRole("Parent"));
});


builder.Services.AddScoped<IAuthService, AuthService>();
builder.Services.AddScoped<IStudentService, StudentService>();

//Inject AutoMap
builder.Services.AddAutoMapper(typeof(MapperConfig));

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(option =>
    {
        option.SwaggerDoc("v1", new OpenApiInfo
        {
            Title = "C# Student Management Sys API",
            Version = "v1",
            Description = "API System for Managing students"
        });

        //Define BearerAuth...
        option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
        {
            Name = "Authorization",
            Type = SecuritySchemeType.ApiKey,
            BearerFormat = "JWT",
            In = ParameterLocation.Header,
            Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n " +
            "Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer eyJhbGciOiJI\""
        }
        );

        option.AddSecurityRequirement(new OpenApiSecurityRequirement {
        {
            new OpenApiSecurityScheme {
                Reference = new OpenApiReference {
                Type = ReferenceType.SecurityScheme,
                Id = "Bearer"
                }
            },
            new string[] {}
        }});

    });


var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseRouting();

app.UseCors(clientsCORSPolicy);

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

角度 v18 帐户.服务.ts

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { environment } from '../../environment/environment';
import { AuthService } from './auth.service';

@Injectable({
  providedIn: 'root'
})
export class AccountService {

  API_PATH = environment.apiUrl + 'Account/';

  requestHeader = new HttpHeaders({ 'No-Auth': 'True' });

  constructor(
    private httpclient: HttpClient,
  ) { }
 
public login(loginData: any) {
    console.log('LOGIN-SERVICE:', loginData)
    return this.httpclient.post(this.API_PATH + 'login', loginData, {
      headers: this.requestHeader,
    });
  }
}

环境.ts

export const environment = {
    production: false,
    apiUrl: "https://localhost:41913/api/",
  }; 

登录.组件.ts

import { Component } from '@angular/core';
import { FormsModule, NgForm } from '@angular/forms';
import { AccountService } from '../../services/account.service';
import { Router } from '@angular/router';
import { RouterLink} from '@angular/router';


@Component({
  selector: 'app-login',
  standalone: true,
  imports: [RouterLink, FormsModule],
  providers: [
  ],
  templateUrl: './login.component.html',
  styleUrl: './login.component.css'
})

export class LoginComponent {

  invalidLogin: boolean = false;

  constructor(
    private accountService: AccountService, 
  ){
  }

  login(loginForms: NgForm) {

    this.accountService.login(loginForms.value).subscribe(
      (response: any) => {
        console.log('RESPONSE : ', response)        
      },
      (error) => {   
      
        if(error.status === 0)
        {
          console.log('STATUS : ', error.status)
          console.log('ERROR: ', error)
          
          alert('Server is not available, Please try again later');
        }
        else{
          var displayErrorAlert = document.getElementById('login-error-alert');   

          if(displayErrorAlert){ 
            displayErrorAlert.style.display = "block";           
          }

          setTimeout(() => {
            if(displayErrorAlert) { 
              displayErrorAlert.style.display = "none"; 
            }
          }, 5000);

          this.invalidLogin = true; 

          console.log('STATUS: ', error.status)
          console.log('ERROR: ', error)
        }
      }
    );
  }

}

登录.component.html

<section>
    <div class="frame">
        <h3>Student Management System</h3>
        <h5>Login</h5>
        <form #loginForm="ngForm" (ngSubmit)="login(loginForm)" class="login">
            <div>
                <i class="bi bi-person-fill" style="color: #222b45;"></i>
                <input ngModel name="Email" id="Email" type="text" class="form-control" placeholder="Email">
            </div>
              
            <div>
                <i class="bi bi-lock-fill" style="color: #222b45;"></i>
                <input ngModel name="password" id="password" type="password" class="form-control" placeholder="password">
            </div>

            <input type="submit" value="Login" class="btn btn-primary">

        </form>

        <div>
            <a routerLink="/register" style="font-size: 15px;color: #222b45;" >Do you have an account? Login here</a>
        </div>
    </div>
</section>

installed nuget package for cors

full description of browser log message

additional browser message

Postman requested successfully

这是我迄今为止所做的事情的清单:

  1. 在 Firefox 中禁用增强的跟踪保护
  2. 使用不同的 API 测试了我的 Angular 应用程序:
  3. 请求已通过
  4. 使用不同的前端测试了我的 Web API 应用程序:
  5. REQUEST 失败,响应相同
angular cors asp.net-apicontroller
1个回答
0
投票
在后端包含 cors 标头并安装 cors 标头

© www.soinside.com 2019 - 2024. All rights reserved.