ASP.NET Core Web API + Angular 对预检请求的响应未通过访问控制检查:预检请求不允许重定向
Posted
技术标签:
【中文标题】ASP.NET Core Web API + Angular 对预检请求的响应未通过访问控制检查:预检请求不允许重定向【英文标题】:ASP.NET Core Web API + Angular Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request 【发布时间】:2020-10-15 19:26:22 【问题描述】:我在 ASP.NET Core Web API 上有一个后端,在 Angular 9 上有一个前端。我正在实施 google 身份验证。在邮递员中它工作正常,但在我的角度应用程序中,当我尝试通过谷歌授权时出现错误:
Access to XMLHttpRequest at 'https://accounts.google.com/o/oauth2/v2/...
(redirected from 'https://localhost:44340/api/auth/googlelogin')
from origin 'http://localhost:4200' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
Redirect is not allowed for a preflight request.
后端的CORS配置:
services.AddCors(options =>
options.AddPolicy("MyPolicy",
builder =>
builder
.WithOrigins(Configuration["ApplicationSettings:Client_URL"].ToString())
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
);
);
app.UseCors("MyPolicy");
我的服务中的方法
public ChallengeResult LoginViaGoogle()
var provider = "Google";
var redirectUrl = "/api/auth/ExternalLoginCallBack";
var properties = Database.SignInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return new ChallengeResult(provider, properties);
我的控制器中的方法
[HttpGet("GoogleLogin")]
public IActionResult GoogleLogin()
ChallengeResult result;
try
result = _authService.LoginViaGoogle();
catch(Exception ex)
throw ex;
return result;
我在 Angular 中的方法:
googleLogin()
const httpOptions =
headers: new HttpHeaders(
"Access-Control-Allow-Origin": "*"
)
;
return this.http.get("https://localhost:44340/api/auth/googlelogin", httpOptions);
我在这个网站上尝试了很多解决方案,但都没有帮助。
我认为问题可能是我在 google oauth 中错误地注册了 URL。
【问题讨论】:
你的 appconfig 文件中 Client_URL 的值是多少? @bthnhttp://localhost:4200
,除了谷歌身份验证,一切正常。
我认为 google 无法向您的本地主机发送请求。您应该购买或使用免费域并托管您的应用程序并将该域提供给 google。
我不确定,但也许你也可以尝试使用 ngrok 让 google auth 与 localhost 一起工作。
@bthn 但如果我在浏览器或邮递员中访问我的 api uri https://localhost:44340/api/auth/googlelogin
我可以授权并获取令牌,所以我认为问题与本地主机无关。
【参考方案1】:
问题是您在此获取请求上返回了重定向,即not allowed when using CORS。
如果您遇到此类问题,我绝对会建议您查看 MDN 文档,它们非常有用且几乎完整。
要解决此问题,您可以返回带有正确身份验证 URL 的有效负载,然后使用您的前端代码进行跟踪。
我不特别了解角度,但我想它看起来像:
googleLogin()
// This header options was not doing anything, the request cannot tell the server how to do CORS.
const authUrl = this.http.get("https://localhost:44340/api/auth/googlelogin");
return this.http.get(authUrl);
【讨论】:
如果我不使用标题选项,我会收到另一个错误:... has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
而在角度上不可能写return this.http.get(authUrl);
,我只能return authUrl;
。
显然 Angular 会自动调用 CORS,因此标题绝对应该什么都不做。您在构建器上的 WithOrigins
函数可能会覆盖您的 AllowsAnyOrigin
,这可能会导致问题。也许先尝试使用正常的有效载荷,然后从那里开始。重定向可能会抛出红鲱鱼。
首先正常有效载荷是什么意思?
您可以在没有正文的情况下进行 POST,因为这是一个更改状态(登录)的端点,您将希望使用 POST,因为 GET 旨在获取信息而不是更改状态.如果您将 Angular 更改为 .post 并将方法更改为 [HttpPost()]
它现在将是一个 post 方法...至于重定向,返回带有 url 的有效负载仍然可能是您的最佳选择,那么您可以使用 angular 来关注它并且不会存在 CORS 重定向问题。【参考方案2】:
当您对后端进行 ajax 调用并将重定向返回给 Google 时,您的初始请求将遵循该重定向。这意味着您正在尝试对 Google 进行 ajax 调用,这是不允许的。
为了解决这个问题,您需要通过一些表单提交或执行window.location='yourdomain.page/path'
对您的后端进行实际的、完整的“回发”。这就是为什么当您将 url 放到浏览器中并按 Enter 时有效的原因。
我的建议是让端点只返回您可以使用 ajax 访问的 google oauth url,然后进行重定向,即
const url = await httpClient.get<GoogleAuth>('/oauth/google').toPromise(); //replace with your google auth returning endpoint
window.location = url;
【讨论】:
什么是<GoogleAuth>
? Angular 没有这种东西
这只是一个示例类,将其替换为您的端点返回并可以反序列化的任何内容。以上是关于ASP.NET Core Web API + Angular 对预检请求的响应未通过访问控制检查:预检请求不允许重定向的主要内容,如果未能解决你的问题,请参考以下文章
使用 ASP.NET Core MVC 创建 Web API