为跨源请求设置cookie

Pim*_*den 35 authentication cookies localhost http-headers cors

如何共享cookie跨源?更具体地说,如何将Set-Cookie标题与标题结合使用Access-Control-Allow-Origin

这是我的情况的解释:

我正在尝试localhost:4000为托管在其上的Web应用程序中运行的API设置cookie localhost:3000.

我似乎在浏览器中收到了正确的响应标题,但不幸的是它们没有任何效果.这些是响应标头:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://localhost:3000
Vary: Origin, Accept-Encoding
Set-Cookie: token=0d522ba17e130d6d19eb9c25b7ac58387b798639f81ffe75bd449afbc3cc715d6b038e426adeac3316f0511dc7fae3f7; Max-Age=86400; Domain=localhost:4000; Path=/; Expires=Tue, 19 Sep 2017 21:11:36 GMT; HttpOnly
Content-Type: application/json; charset=utf-8
Content-Length: 180
ETag: W/"b4-VNrmF4xNeHGeLrGehNZTQNwAaUQ"
Date: Mon, 18 Sep 2017 21:11:36 GMT
Connection: keep-alive

此外,Response Cookies当我使用Chrome开发者工具的"网络"标签检查流量时,我可以看到cookie .但是,我看不到在"应用程序"选项卡下设置的cookie Storage/Cookies.我没有看到任何CORS错误,所以我假设我错过了其他的东西.

有什么建议?

更新I:

我正在使用React-Redux应用程序中的请求模块/signin向服务器上的端点发出请求.对于服务器我使用快递.

快递服务器:

res.cookie('token', 'xxx-xxx-xxx', { maxAge: 86400000, httpOnly: true, domain: 'localhost:3000' })

在浏览器中请求:

request.post({ uri: '/signin', json: { userName: 'userOne', password: '123456'}}, (err, response, body) => {
    // doing stuff
})

更新II:

我现在设置请求和响应标头现在像疯了一样,确保它们在请求和响应中都存在.下面是截图.注意头Access-Control-Allow-Credentials,Access-Control-Allow-Headers,Access-Control-Allow-MethodsAccess-Control-Allow-Origin.看看我在Axios的github上发现的问题,我的印象是现在已经设置了所有必需的标题.然而,仍然没有运气......

在此输入图像描述

Pim*_*den 64

你需要做什么

要允许成功通过CORS请求接收和发送cookie,请执行以下操作.

后端(服务器): 将HTTP标头Access-Control-Allow-Credentials值设置为true.此外,请确保Access-Control-Allow-Origin已设置HTTP标头.

前端(客户端):*标志设置为XMLHttpRequest.withCredentials,这可以通过不同的方式实现,具体取决于所使用的请求 - 响应库:

要么

避免将CORS与cookie结合使用.您可以使用代理实现此目的.

如果你出于某种原因不要避免它.解决方案如上.

事实证明,如果域包含端口,Chrome将不会设置cookie.设置它withCredentials: true(没有端口)不是问题.非常感谢Erwin的提示!

  • 这是一个很好的答案,并且为CORS,标头,后端和前端进行了所有设置,并避免了本地主机使用真实的子域在本地覆盖/ etc / hosts,但我仍然看到邮递员在响应标头中显示了SET-COOKIE,但是chrome debug没有在响应标题中显示此信息,并且cookie实际上未在chrome中设置。还有其他想法要检查吗? (4认同)
  • 这个答案对我有很大帮助!花了很长时间才找到它。但是我认为答案应该提到将`Access-Control-Allow-Origin`设置为一个明确的域,而不仅仅是“ *”是必需的。那将是一个完美的答案 (3认同)
  • 我认为你有这个问题只是因为“本地主机”在这里检查这个:/sf/answers/83170181/ 这也可能有助于你的情况(/sf/ask/3567680301/ to-correct-set-the-cookies-for-a-subdomain-in-jsp/50988268#50988268) (2认同)

Len*_*Lip 29

2020 年发布的 Chrome 浏览器注意事项。

未来版本的 Chrome 将仅在跨站点请求中使用SameSite=None和设置 cookie 时才传送 cookie Secure

因此,如果您的后端服务器未设置 SameSite=None,Chrome 将默认使用 SameSite=Lax,并且不会将此 cookie 与 { withCredentials: true } 请求一起使用。

更多信息https://www.chromium.org/updates/same-site

Firefox 和 Edge 开发人员也希望在未来发布此功能。

规范在这里找到:https : //tools.ietf.org/html/draft-west-cookie-incrementalism-01#page-8

  • 提供 Samesite=none 和安全标志需要 HTTPS。如何在无法选择 HTTPS 的本地系统中实现此目的?我们能以某种方式绕过吗? (10认同)

Ste*_*gas 11

为了让客户端能够从跨域请求中读取 cookie,您需要具备:

  1. 来自服务器的所有响应都需要在其标头中包含以下内容:

    Access-Control-Allow-Credentials: true

  2. 客户端需要发送所有带有withCredentials: true选项的请求

在我使用 Angular 7 和 Spring Boot 的实现中,我通过以下方式实现了这一点:


服务器端:

@CrossOrigin(origins = "http://my-cross-origin-url.com", allowCredentials = "true")
@Controller
@RequestMapping(path = "/something")
public class SomethingController {
  ...
}
Run Code Online (Sandbox Code Playgroud)

origins = "http://my-cross-origin-url.com"部分将添加Access-Control-Allow-Origin: http://my-cross-origin-url.com到每个服务器的响应头

allowCredentials = "true"部分将添加Access-Control-Allow-Credentials: true到每个服务器的响应头中,这是我们让客户端读取 cookie 所需要的


客户端:

import { HttpInterceptor, HttpXsrfTokenExtractor, HttpRequest, HttpHandler, HttpEvent } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable } from 'rxjs';

@Injectable()
export class CustomHttpInterceptor implements HttpInterceptor {

    constructor(private tokenExtractor: HttpXsrfTokenExtractor) {
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // send request with credential options in order to be able to read cross-origin cookies
        req = req.clone({ withCredentials: true });

        // return XSRF-TOKEN in each request's header (anti-CSRF security)
        const headerName = 'X-XSRF-TOKEN';
        let token = this.tokenExtractor.getToken() as string;
        if (token !== null && !req.headers.has(headerName)) {
            req = req.clone({ headers: req.headers.set(headerName, token) });
        }
        return next.handle(req);
    }
}
Run Code Online (Sandbox Code Playgroud)

通过这个类,您实际上可以为您的所有请求注入额外的内容。

第一部分req = req.clone({ withCredentials: true });,是您发送带有withCredentials: true选项的每个请求所需要的。这实际上意味着将首先发送一个 OPTION 请求,以便您在发送实际的 POST/PUT/DELETE 请求之前获得您的 cookie 和其中的授权令牌,这些请求需要将此令牌附加到它们(在标头中),在命令服务器验证并执行请求。

第二部分是专门处理所有请求的反 CSRF 令牌的部分。在需要时从 cookie 中读取它并将其写入每个请求的标头中。

想要的结果是这样的:

回复 要求

  • 实际实施。我决定发布它的原因是,我花了很多时间搜索相同的问题并将不同帖子中的片段添加到一起以实现它。通过这篇文章作为比较,人们应该更容易做同样的事情。 (4认同)

Abd*_*ipo 6

对于 Express,请将 Express 库升级到4.17.1最新的稳定版本。然后;

在 CorsOption 中:设置origin为您的本地主机 url 或前端生产 url ,credentials例如true

  const corsOptions = {
    origin: config.get("origin"),
    credentials: true,
  };
Run Code Online (Sandbox Code Playgroud)

我使用config npm module动态设置我的原点。

然后,在 res.cookie 中:

对于 localhost:您根本不需要设置 SameSite 和 secure 选项,您可以根据您的用例httpOnly设置truehttp cookie 以防止 XSS 攻击和其他有用的选项。

对于生产环境,跨域请求需要设置为sameSiteto ,跨域请求需要设置为to 。请记住,仅适用于 Express 最新版本,因为目前最新的 chrome 版本仅设置 cookie ,因此需要安全选项。nonesecuretruesameSitehttps

这是我如何让我的动态变得动态

 res
    .cookie("access_token", token, {
      httpOnly: true,
      sameSite: app.get("env") === "development" ? true : "none",
      secure: app.get("env") === "development" ? false : true,
    })
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

38834 次

最近记录:

5 年,12 月 前