CORS 403 错误 Angular 和 Express

Posted

技术标签:

【中文标题】CORS 403 错误 Angular 和 Express【英文标题】:CORS 403 error Angular and Express 【发布时间】:2014-04-05 19:19:03 【问题描述】:

我的 Express 配置的一部分看起来像这样并在不同的域上运行

app.use(function(req, res, next) 
    res.setHeader("Access-Control-Allow-Origin", 'http://localhost:3000');
    res.setHeader("Access-Control-Allow-Credentials","true");
    res.setHeader("Access-Control-Expose-Headers", "Set-Cookie");
    res.setHeader("Access-Control-Allow-Headers", "Content-Type, x-xsrf-token, X-Requested-With, Accept, Expires, Last-Modified, Cache-Control");
    res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, DELETE");
    next();
);
app.configure('development', 'production', function() 
    app.use(express.csrf());
    app.use(function(req, res, next) 
        res.cookie('XSRF-TOKEN', req.csrfToken());
        next();
    );
);

当使用 CORS 时,在与 GET 不同的任何内容之前都有 OPTIONS 请求。服务器被手动配置为每次以 200 响应它,因此它继续进行 POST 或其他任何操作。 请求来自 Angular。有人说我需要添加其中一些行才能正确配置 Angular。

$httpProvider.defaults.xsrfCookieName = 'XSRF-TOKEN';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.withCredentials = true;

我得到的错误是 403 Forbidden,目前唯一的解决方案是在服务器中注释掉整个 app.configure(..)。显然,我对 CSRF 有一些问题,我不明白我应该怎么做。

已编辑

【问题讨论】:

你如何设置你的cookies? 【参考方案1】:

This section of the doc 这么说

对于没有凭据的请求,服务器可以指定“*”作为通配符,从而允许任何来源访问资源。

通配符用于不需要身份验证的完全公共 API。如果您想使用凭据(通过 cookie),您必须在 Access-Control-Allow-Origin 中设置允许的 url 的确切列表

确保在后端使用res.setHeader("Access-Control-Allow-Credentials","true");,例如:

 app.use(function(req, res, next) 
    res.setHeader("Access-Control-Allow-Origin", 'YOUR URL HERE');
    res.setHeader("Access-Control-Allow-Credentials","true");
    res.setHeader("Access-Control-Expose-Headers", "Set-Cookie");
    res.setHeader("Access-Control-Allow-Headers", "Content-Type, x-xsrf-token, X-Requested-With, Accept, Expires, Last-Modified, Cache-Control");
    res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
);

此外,$httpProvider.defaults.withCredentials = true; 应在角度侧使用以允许发送凭据。

angular.module('CoolModule')
  .config(['$httpProvider', function($httpProvider)
    // For Access-Control-Allow-Origin and Set-Cookie header
    $httpProvider.defaults.withCredentials = true;
  ]); 

$http(withCredentials: true, ...).get(...)

希望这会有所帮助。

编辑: 不是解决方案,但作为允许 OPTIONS 请求的解决方法,可以添加这段代码:

...
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
if ('OPTIONS' == req.method)  
  res.send(200);  else  next(); 

...

【讨论】:

伊戈尔,这部分工作。我添加了 next();在所有访问控制配置之后,我又得到了 403,但它现在发送 cookie。如果没有 next() OPTIONS 请求将永远挂起......那么我需要停止 OPTIONS 请求或向其中添加 cookie 吗?或者我又错了 403 表示“禁止”请求被丢弃。如果您使用 Chrome,您可以阅读原因。至少对我来说,Chrome 表示由于 CORS 标头配置而被禁止。请尝试将此作为一种解决方法,让我们看看它是否有帮助 --- 添加“if ('OPTIONS' == req.method) res.send(200); else next(); ” res.setHeader 语句 这是一个错误,因为它在 Allow-Origin 配置之前收到了 OPTIONS 请求。我将路由器修复为在每个 OPTIONS 请求上响应 200,但这会再次导致 403。但是,我注释掉了 csrf 配置,现在一切正常。显然,这不是解决方案,因为现在服务器对 csrf 攻击是开放的。 您是否在Access-Control 标头之后添加了if ('OPTIONS' == req.method) res.send(200); else next(); ?如果是,它应该为每个 OPTIONS 请求返回 200 OK 而不会出错。 您是否为 xsrf 添加了必要的标头?【参考方案2】:

您需要启用 CORS 支持您的 angular.js 应用:

yourApp.config(['$httpProvider', function($httpProvider) 
        $httpProvider.defaults.useXDomain = true;
        delete $httpProvider.defaults.headers.common['X-Requested-With'];
    
]);

【讨论】:

我试了几次,没有任何区别。实际上,我发现 POST 请求没有正确发送 cookie。 this thread 那么,如果您可以在问题中包含此类信息,那就太好了,这样可以节省我查找和输入答案的时间。 CORS 问题通常在服务器端解决,而不是在客户端解决,所以这个答案不太可能有帮助。【参考方案3】:

这应该可以解决您的问题。

var allowCrossDomain = function(req, res, next) 
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type');

    next();


app.use(allowCrossDomain);

【讨论】:

以上是关于CORS 403 错误 Angular 和 Express的主要内容,如果未能解决你的问题,请参考以下文章

Keycloak-angular:访问/帐户失败,出现 403 错误和 CORS 消息

CORS 错误和带有 JWT 令牌的 403 响应

CORS 预检选项请求的 403 错误。怎么修?

Angular从客户端避免CORS问题

启用 CORS 和解决 403 Forbidden 错误的问题

AJAX、CORS、Chrome 和 HTTP 错误代码 (401,403,404,500) 的推荐解决方案