No 'Access-Control-Allow-Origin' header in

2020-02-13 05:09发布

问题:

i need to download image from backend Asp Core 2.2 and show it in Angular .

i create a component for show image in angular :

in Html Code :

<img [src]="src$ | async" class="img-fluid img-thumbnail">

in Ts File :

  @Input() ImagePath: string;
  ImageBlob: any;

  public src$: Observable<SafeUrl>;
  private imageSrc$: BehaviorSubject<string>;

  constructor(private downloadService: DownloadService, private domSanitizer: DomSanitizer) {
    this.imageSrc$ = new BehaviorSubject(null);
    this.src$ = this.imageSrc$.pipe(switchMap(src => this.getImage(this.ImagePath)));
  }

  ngOnChanges() {
    this.imageSrc$.next(this.ImagePath);
  }

  private createImage(blob: Blob) {
    console.log('CREATE_IMAGE');
    return this.domSanitizer.bypassSecurityTrustUrl(URL.createObjectURL(blob));
  }

  private getImage(url: string) {
    console.log('GET_IMAGE');
    return this.downloadService
      .DownloadImage(this.ImagePath)
      .pipe(map((blob: Blob) => this.createImage(blob)));
  }
}

and in Service :

DownloadImage(ImageUrl: string): Observable<Blob> {
    return this.httpClient.get(ImageUrl, { responseType: 'blob' });
 }

now when i need to show image it show me this error in console :

Access to XMLHttpRequest at 'https://localhost:44372/Uplaod/NewsPictureFolder/NewsMainPicture/903797628068313.jpg' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

GET http://localhost:4200/null 404 (Not Found)

and this is my interceptor :

   @Injectable()
export class RequestInterceptor implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        if (req.url.includes('/Upload/')) {
            console.log('upload')
            req = req.clone({ headers: req.headers.set('Access-Control-Allow-Origin', '*') })
            return next.handle(req);
        }
        if (!req.headers.has('Content-Type')) {
            console.log('type')
            req = req.clone({ headers: req.headers.set('Content-Type', 'application/json') });
        }
        req = req.clone({ headers: req.headers.set('Access-Control-Allow-Origin', '*') })
        req = req.clone({ headers: req.headers.set('Accept', 'application/json') });
        return next.handle(req);
    }
}

i do not know where is the problem ? in Front End or Backend ??

this is Startup in Asp core :

services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder.AllowAnyOrigin()
                  .AllowAnyMethod()
                  .AllowAnyHeader()
                  .WithOrigins("http://localhost:4200")
                  .AllowCredentials()
            .Build());

        });

where is the problem ? how can i solve this problem ????

回答1:

ASP.NET Core 2.2 doesn't allow the combination of AllowAnyOrigin and AllowCredentials. You need to change AllowAnyOrigin to SetIsOriginAllowed:

app.UseCors(builder => builder
                .AllowAnyHeader()
                .AllowAnyMethod()
                .SetIsOriginAllowed((host) => true)
                .AllowCredentials()
            );


回答2:

While the other answer is correct, if you however want to define specific allowed origins (and you should), you should remove .AllowAnyOrigin() or SetIsOriginAllowed((host) => true) from your CORS statement and it will work with .AllowCredentials().

        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder
                  .AllowAnyMethod()
                  .AllowAnyHeader()
                  .WithOrigins("http://localhost:4200")
                  .AllowCredentials()
            .Build());

        });

And if you want to allow multiple Origins, you can set an array of origins and use that as the param in .WithOrigins(). E.g:

private readonly string[] MyAllowedOrigins = new string[] {
    "http://localhost:4200",
    "http://localhost:3000"
};

...
.WithOrigins(MyAllowedOrigins)
...

Also, pay attention to the scheme used - check if it's http or https.

For the sake of completeness, never forget to add e.g. app.UseCors("CorsPolicy"); where you configure your pipeline, e.g. .Configure method in the Startup class.


All in all - while in some cases allowing any origin could be okay, you usually want and should define the allowed origins specifically.

Regarding SetIsOriginAllowed((host) => true) - this should be an expression to evaluate whether an origin should be allowed, making it return => true always, could be fine under a dev. environment, but shouldn't be used in production as far as I can tell.

You can find a good read on MS Docs. Checkout:

  • Enable Cross-Origin Requests
  • CorsPolicyBuilder
  • AllowAnyOrigin
  • WithOrigins
  • SetIsOriginAllowed