【问题标题】:If CORS wildcard for authentication not allowed, how to facilitate cross-origin authentication?如果不允许使用 CORS 通配符进行身份验证,如何促进跨域身份验证?
【发布时间】:2020-02-28 19:56:56
【问题描述】:

我收到与 AJAX (HttpClient) 请求相关的 CORS 错误,该请求尝试接收 res.cookie 作为响应。

作为背景:

我的 CORS 政策

app.use(cors());
app.options('*',cors());
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);

app.use(csp({
  policies: {
      'default-src': [csp.NONE ],
      'img-src': [csp.SELF] }
}));

请求(来自 localhost:4200)

// Template
<form #f="ngForm" [formGroup]="userForm" (ngSubmit)="doSignUp(f)">
   . . . 
   . . . 
    <button>Submit</button>
</form>


//Sign-up Component
doSignUp(f: NgForm) {
  this.member.postSignupForm(f).subscribe((res)=>console.log(`RES: ${JSON.stringify(res)}`));
}


// Auth Service 
postSignupForm(f: NgForm): Observable<any> {
    return this.http.post(this.signup_url, f.value);
}

响应(来自 localhost:3000/users/sign-up route)

 . . . 
 . . . 
 user.save().then(()=> {
     res.cookie("SESSIONID", user.generateJWT(), {httpOnly:true, secure:true});


错误:

跨源请求被阻止:同源策略不允许读取位于 https://localhost:3000/users/sign-up 的远程资源。 (原因:CORS 请求未成功)。

我查看了 Wikipedia https://en.wikipedia.org/wiki/Cross-origin_resource_sharing 并发现了以下内容:

通配符同源策略在对象能力模型中也得到了广泛和适当的使用,其中页面具有不可猜测的 URL,并且任何知道秘密的人都可以访问。

“*”值的特殊之处在于它不允许请求提供凭据,这意味着它不允许在跨域请求中发送 HTTP 身份验证、客户端 SSL 证书或 cookie .

上一句让我很困惑。如果不能使用“8”提供凭据,如何配置 CORS 以允许跨源 HTTP 身份验证?

我也注意到了下面这个明显相关的问题CORS and HTTP authentication,这个问题已经拖了好几个月了,一直没有答案。

那么,如果 Wikipedia 是正确的,您如何允许跨域 AJAX 请求导致在响应中发回 cookie(例如包含用于身份验证的 JWT)?我一定是遗漏了一些东西或读错了,但是如果你不能在 Access-Control-Allow-Origin 中使用“*”,但你想要一个开放的 API,你如何对来自随机域的人进行身份验证?您显然无法提前知道将访问您的开放网站的所有域。

更新

根据下面两个答案的建议,我做了如下修改:

res.header('Access-Control-Allow-Origin', req.headers.origin || '*'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Origin, Accept');

我现在收到服务器端“重复密钥”错误:

MongoError: E11000 duplicate key error collection: UserDB.users index: authData.username.value_1 dup key: { : "michael"}

我仍然收到 CORS 错误,但我认为现在 CORS 错误可能是由于服务器出现异常而导致的。 (我发现当服务端出现异常时,往往反映在客户端CORS中)。还是因为 CORS 错误导致客户端没有正确接收响应导致服务器出现异常?

问题是,我相信我收到了重复密钥错误,因为由于某种原因我无法弄清楚,服务器试图两次保存同一个文档。文档在 Mongo 中正确更新,但随后服务器尝试再次保存相同的文档。在客户端,只有一个 post 请求。

这种双重保存行为是否与由于 CORS 导致客户端不接受来自服务器的响应这一事实有关? IE。是 CORS 导致了 dupl key 错误,还是 dup key 错误导致了 CORS 错误?什么会解释服务器试图两次保存同一个文档?

【问题讨论】:

  • 您的新问题与旧问题完全无关。您收到 CORS 错误是因为服务器发送的错误响应没有适当的 CORS 标头。

标签: angular mongodb express cors


【解决方案1】:

上一句让我很困惑!如果您不能使用“*”来提供凭据,您如何配置 CORS 以允许跨源 HTTP 身份验证?

服务器可以选择使用与请求中的 Origin 标头匹配的特定 Access-Control-Allow-Origin 响应标头进行响应。

例如,假设客户端请求:

GET /resource HTTP/1.1
Origin: origin-a.example.com

服务器可以响应:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: origin-a.example.com

在您的 Node.js 示例中,尝试如下操作:

res.header('Access-Control-Allow-Origin', req.headers.origin || '*');

【讨论】:

  • 非常感谢。这非常有帮助,我觉得这让我走上了正轨。但是,不幸的是,在进行了您建议的更改后 (res.header('Access-Control-Allow-Origin', req.headers.origin || '*') 我仍然收到 CORS 错误。我注意到(根据控制台)req.headers.originlocalhost:4200originhttp,而 hosthttps 是否存在问题?或者如果这不是问题,还有其他关于我该如何进一步调试呢?
  • 我对 OP 做了一些更新。请看上图,谢谢!
【解决方案2】:

通常 NodeJS 支持跨域请求,你需要明确指定方法和头。即需要指定AuthorizationOriginAccept等标头。

另外需要注意的是,浏览器在向服务器发送跨域请求时,主要是发送OPTIONS请求来检查目标资源的通信选项。这需要处理。

你可以使用这样的东西。

const app = express();
app.all('/', cors());
app.use(function(req, res, next) {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader(
    "Access-Control-Allow-Methods",
    "GET, PUT, POST, DELETE, OPTIONS"
  );
  res.setHeader(
    "Access-Control-Allow-Headers",
    "Content-Type, Authorization, Origin, Accept"
  );
  if ("OPTIONS" === req.method) {
    res.send(200);
  } else {
    next();
  }
});

希望这能澄清您的担忧。

【讨论】:

  • 非常感谢。这很有帮助。根据您的建议,我添加了res.setHeader( "Access-Control-Allow-Headers", "Content-Type, Authorization, Origin, Accept" );,这似乎在一定程度上有所帮助,但我仍然遇到错误(尽管现在略有不同)。我如上所述修改了我的OP。非常感谢,请检查更新,看看您是否能想到任何进一步的建议!
  • @Crowdpleasr 你看过你的数据库了吗?我认为密钥有重复项。这可能是该异常的原因。如您提供的错误所示,用户名似乎重复。
猜你喜欢
  • 2014-10-25
  • 2021-01-13
  • 2015-12-25
  • 2019-02-25
  • 2015-08-21
  • 2016-01-05
  • 2013-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多