【问题标题】:Angular Request Can't Access API Control due to CORS由于 CORS,Angular 请求无法访问 API 控制
【发布时间】:2020-01-07 07:35:04
【问题描述】:

我有一个简单地上传个人资料图片的端点。尽管我启用了 CORS,但前端团队一直告诉我,由于以下错误,他们无法到达该端点:

zone.js:2990 从源 'http://localhost:4200' 访问 XMLHttpRequest 在 'http://localhost:4200' 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:它没有 HTTP ok 状态.

他们正在 Angular 上开发。另一方面,移动团队(在 Xamarin 上开发)在达到该端点时没有任何问题。下面是我对 API 控制器的细分。

[EnableCors(origins: "*", headers: "*", methods: "*")]
public class BaseController : ApiController
{
    //common methods used on every controller written here
}

而且,这里是包含图片上传方法的端点:

public class ImageController : BaseController
{
    [IdentityBasicAuthentication]
    [Authorize]
    public HttpResponseMessage PostAccountPicture()
    {
        //some code here
    }
}

首先,这些 [Authorize][IdentityBasicAuthentication] 标头被放置在 ImageController 的顶部,但我读到这种情况最终可能会混合请求管道,所以我将它们移到了操作的顶部(没有解决不了问题)。

我的 web.config 上也有这些 customHeader 行:

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Credentials" value="true"/>
    <add name="Access-Control-Allow-Headers" value="Content-Type" />
    <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, OPTIONS" />
  </customHeaders>
</httpProtocol>

而且,我的处理程序描述如下:

<handlers>
  <remove name="WebDAV" />
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <!--<remove name="OPTIONSVerbHandler" />-->
  <remove name="TRACEVerbHandler" />
  <add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" requireAccess="None" responseBufferLimit="4194304" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

一开始我没有name="OPTIONSVerbHandler"。将其添加到 web.config 后,移动请求开始出现 500 Internal Server Error。

下面是我根据其他建议编辑的 Global.asax(Application_BeginRequest 开头没有包含):

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        GlobalConfiguration.Configure(WebApiConfig.Register);
        GlobalConfiguration.Configuration.Formatters.Add(new FormMultipartEncodedMediaTypeFormatter());
    }

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
        {
            HttpContext.Current.Response.Flush();
        }
    }
}

最后,我的WebApiConfig 课程如下:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

我还要求我的前端伙伴与我分享她的 ajax 请求。是这样的:

  $("form").submit(function(evt){evt.preventDefault(); var formData = new FormData($(this)[0]); $.ajax({
url: 'https://<our subdomain name is here>/api/Image/PostAccountPicture',
type: 'POST',
data: formData,
async: false,
cache: false,
contentType: false,
enctype: 'multipart/form-data',
processData: false,
headers: {'Authorization':'Basic ' + localStorage.getItem('currentUser')} ,
success: function (response) {
  alert(response);
}});return false;});

我在之前的项目中也启用了 CORS,在控制器类上设置 [EnableCors("*","*","*")] 并在 WebApiConfig.cs 上设置 config.EnableCors() 就足够了,而无需像 web.config 文件中那样进行上述所有其他调整.

现在,我不知道是什么让前端到达我的终点。

提前谢谢你!

【问题讨论】:

  • 能分享一下角码吗
  • @EhsanKiani 感谢您的关注。我离 Angular 太远了,如果你能准确地告诉我你从 Angular 方面需要什么,我很高兴。我已经在我的问题中分享了他们的 ajax 请求
  • 我也遇到了同样的问题,通过从我的角度请求中删除标头解决了
  • @EhsanKiani 但她需要通过标题区域向我发送用户令牌?

标签: c# angular cors asp.net-web-api2


【解决方案1】:

在使用 Angular 进行开发并在浏览器和后端之间使用本地服务器时,我遇到了同样的问题(以便在代码更改时即时更新 gui)。我们通过添加Allow CORS Plugin 解决了这个问题 Chrome(我想其他浏览器)不喜欢处理页面的服务器与发送 api 调用的服务器不同。

这在生产中当然没有问题,因为浏览器正在到达预期的服务器,而不是中间服务器中的一种人。

【讨论】:

  • 遗憾的是这对我们没有帮助。我检查了我队友的chorme,它已经有了这个插件。我只是打开它并再次触发请求,但CORS错误仍然存​​在
【解决方案2】:

您可以尝试在角度端发送跨域/跨域:true 就像下面的方式
标题:{ '授权':'基本' + localStorage.getItem('currentUser'), '访问控制允许来源':'*', 'Access-Control-Allow-Headers':'Origin,X-Requested-With,Content-Type,Accept' }

【讨论】:

  • 现在错误变成了The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.
  • 我根据您的上次更新编辑了我的朋友的 ajax,但我们收到与我上述评论相同的错误
  • 您是否使用来自客户端的 Http 请求使用 ssl /tls 协议访问其余 api。?
  • 是的,rest API 的 URL 以 https 开头,而 localhost 不是
  • 那么这不是安全层通信。尝试使用具有相同标题的localhost
【解决方案3】:

免责声明:仅用于开发目的。

仅在开发期间,我的 Angular 应用程序中有一个用例,我必须从外部 URL 获取模拟数据。我尝试设置标题和代理,但最终发现这个插件就像一个魅力。

试试 CORS Everywhere Firefox 的插件/扩展。

如果使用 chrome 或 edge(chromium),请查看 chrome webstore。

注意:使用风险自负。确保您了解您授予这些插件/扩展的权限类型。

仅供参考如果链接在某个时间点失效,请尝试用谷歌搜索,呵呵。 ;)

【讨论】:

    猜你喜欢
    • 2021-11-09
    • 2018-09-18
    • 2020-10-17
    • 2016-11-26
    • 2018-05-30
    • 2019-05-28
    • 2016-08-13
    • 2018-02-21
    • 1970-01-01
    相关资源
    最近更新 更多