从 Angular 客户端调用 API 时出现身份服务器 CORS 错误

Posted

技术标签:

【中文标题】从 Angular 客户端调用 API 时出现身份服务器 CORS 错误【英文标题】:Identity server CORS error while calling API from Angular client 【发布时间】:2021-06-01 18:55:34 【问题描述】:

您好,我创建了一个 Angular 应用程序,它连接到 Identity Server 4 以进行身份​​验证。我使用 AllowedCorsOrigins 注册了 Angular 客户端,并且 Scopes 正在访问 API。我还有其他客户端“.net core MVC”,它们也具有相同的范围(访问 API)。我对 MVC 客户端没有任何问题,但是有角度我收到了 CORS 错误。

身份服务器客户端

new Client
        
            ClientId = "clientangularSLO",
            ClientName = "Angular Client",
            AllowedGrantTypes = GrantTypes.Code,
            RequireClientSecret = false,
            AllowedScopes = new List<string>
            
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                "api1",
                "roles"
            ,

            
            RedirectUris = new List<string> "http://localhost:4200", "http://localhost:4300",
            PostLogoutRedirectUris = new List<string> "http://localhost:4200", "http://localhost:4300",
            AllowedCorsOrigins = new List<string>  "http://localhost:4200", "http://localhost:4300" ,

            AccessTokenLifetime = 120,  //2mins 
            RequireConsent= true,
            RequirePkce = true,
            AllowAccessTokensViaBrowser = true,
            AllowOfflineAccess = true,
            
        

API 范围

public static IEnumerable<ApiScope> ApiScopes =>
        new List<ApiScope>
        
            new ApiScope("api1", "Test API",new List<string>()  "role" )            
        ;

Angular 客户端 我正在使用 angular-auth-oidc-client 11.5.1

    export function configureAuth(oidcConfigService: OidcConfigService) 
  return () =>
    oidcConfigService.withConfig(
      stsServer: 'https://localhost:5001',
      redirectUrl: window.location.origin,
      clientId: 'clientangularSLO',
      scope: 'openid profile api1',
      responseType: 'code',
      triggerAuthorizationResultEvent: true,
      postLogoutRedirectUri: `$window.location.origin/unauthorized`,
      
      logLevel: LogLevel.Debug,
      historyCleanupOff: true,
                 
    );

我尝试在 API 中添加 Cors,我不确定这是不是正确的 wasy

API --> StartUp.cs

public void ConfigureServices(IServiceCollection services)
        
            //services.AddCors(c =>
            //
            //    c.AddPolicy("AllowOrigin", options => 
            //        options.WithOrigins("http://localhost:4200", "http://localhost:4300")
            //        .AllowAnyMethod()
            //        .AllowAnyHeader()                 
            //    );
            //);

           
            services.AddSingleton<ICorsPolicyService>((container) => 
                var logger = container.GetRequiredService<ILogger<DefaultCorsPolicyService>>();
                return new DefaultCorsPolicyService(logger)
                
                    //AllowedOrigins =  "http://localhost:4200", "http://localhost:4300" 
                    AllowAll = true
                ;
            );
            
            services.AddAuthorization(opt =>
            
                opt.AddPolicy("Apiscope", policy =>
                
                    policy.RequireAuthenticatedUser();
                    policy.RequireClaim("Scope", "api1");
                    
                );

            );



 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        
            if (env.IsDevelopment())
            
                app.UseDeveloperExceptionPage();
            

            app.UseCors(options => options.AllowAnyOrigin());
            //app.UseCors(options => options.WithOrigins("http://localhost:4200", "http://localhost:4300"));

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthentication();

            app.UseAuthorization();
        
            app.UseEndpoints(endpoints =>
            
                endpoints.MapControllers()
                    .RequireAuthorization("ApiScope"); //checking the policy "Apiscope"
            );
        

HttpInterceptor 添加令牌

 private getToken()
    return this.oidcSecurityService.getToken();
  

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> 
    
    if(this.tokenValue)
      request = request.clone( 
        setHeaders: 
          Authorization : `Bearer $this.getToken()`
        
      )
    

    return next.handle(request);
  

我正在使用 Angular11 和身份服务器 v4.0.0 。请告诉我,解决这个问题的正确方法。

【问题讨论】:

【参考方案1】:

感谢大家的cmets。

通过在 API 配置中添加 AllowAnyHeader()AllowAnyMethod() 解决此问题

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    
        if (env.IsDevelopment())
        
            app.UseDeveloperExceptionPage();
        

        app.UseCors(options =>
            options.AllowAnyOrigin()
            .AllowAnyHeader()
            .AllowAnyMethod()
            );

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthentication();

        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        
            endpoints.MapControllers()
                .RequireAuthorization("ApiScope"); //checking the policy "Apiscope"
        );
    

【讨论】:

【参考方案2】:

我不能 100% 确定我完全理解上下文,但我怀疑为 Angular 应用程序提供服务的 .NET Core 后端服务没有使用端口 4200 上 Angular 开发服务器的代理配置。

因此,在ConfigureServices(IServiceCollection services) 中基于.NET 的Angular 后端服务的Startup.cs 中需要以下配置:

services.AddSpaStaticFiles(configuration =>

    configuration.RootPath = "ClientApp/dist";
);

Configure(IApplicationBuilder app, IWebHostEnvironment env)

app.UseSpa(spa =>

    // To learn more about options for serving an Angular SPA from ASP.NET Core,
    // see https://go.microsoft.com/fwlink/?linkid=864501
     spa.Options.SourcePath = "ClientApp";

    if (env.IsDevelopment())
    
        spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");
    
 );

在此处查看详细信息: https://docs.microsoft.com/en-us/aspnet/core/client-side/spa/angular?view=aspnetcore-5.0&tabs=visual-studio

我建议使用dotnet new angular -o my-new-app 生成一个项目并检查那里的配置。 如果我们想独立运行带有ng serve 的Angular 开发服务器,这种方法通常用于避免跨域调用。

如果这种方法已经奏效,下一步就是正确配置身份服务器。

【讨论】:

【参考方案3】:

尝试将此 'Access-Control-Allow-Origin': '*' 添加到您的请求中

【讨论】:

以上是关于从 Angular 客户端调用 API 时出现身份服务器 CORS 错误的主要内容,如果未能解决你的问题,请参考以下文章

Angular 调用 Eureka API 时出现 CORS 来源错误

从 Angular Js(Java Web)调用 API 时出现 CORS 错误

尝试从 api.ipify.org 获取 IP 地址时出现 Angular HTTP 错误

从泽西客户端调用 post API 时出现 415 错误

尝试从客户端登录到后端烧瓶 api 时出现 401 UNAUTHORIZED 状态

尝试从 Github API + Spring Boot 获取到 Angular 时出现 CORS 错误