preface

Recently, while testing the company’s systems in a local development environment, I encountered a cross-domain problem that prevented me from logging in to obtain user rights. Originally, as long as the local browser stored the cookie information of the target server, cross-domain request can be sent, but the strange thing is that cookie has been obtained by enabling the CORS same-origin request. The cross-domain situation still occurs in the system started in the local development environment, and it is found that the request does not automatically carry cookies. Why is CORS enabled and cross-domain problems still occur?

The article Outlines

  • To analyze problems

    • Why is there a cross-domain problem
    • How to solve cross-domain problems
    • Why do CROSS-domains still occur when CORS is enabled
  • To solve the problem

    • Disable same-site in the browser

    • Use a third-party agent

To analyze problems

Why is there a cross-domain problem

Cross-domain is essentially a secure way for browsers to implement the Same Origin Policy. For the definition of homologous site, the URL protocol (Protocol), port (port), and host (host domain name) are identical. Same-origin policies restrict access to resources from two different source sites, and cross-domain problems can occur if the front end wants to send site data to different source sites via XMLHttpRequest.

Such as A source for: http://store.company.com/dir/page.html, and B of the following sources. Reference from MDN Definition of an Origin

URL Outcome Reason
http://store.company.com/dir2/other.html Same origin Only the path differs
http://store.company.com/dir/inner/another.html Same origin Only the path differs
https://store.company.com/page.html Failure Different protocol
http://store.company.com:81/dir/page.html Failure Different port (http:// is port 80 by default)
http://news.company.com/dir/page.html Failure Different host

However, the local front-end service http://localhost:9096 and the server http://api.backend.com are from different sources, causing cross-domain resource access restrictions.

How to solve cross-domain problems

There are many ways to solve cross-domain problems, such as using JSONP, CORS, Proxy and other solutions. In the company’s project, the CORS scheme is used.

CORS cross-domain resource sharing was introduced to address the network-level limitations of the same Origin policy. It is an HTTP header based mechanism that allows the server to identify other origins (domains, protocols and ports) other than its own, so that the browser can access and load these resources.

How to enable this function? For example, if the login interface makes a simple request, the origin field is added to the request sent by the browser. The Origin field indicates the source (protocol + domain name + port) from which the request is sent. Based on this value, the server decides whether to approve the request or not.

GET /cors HTTP/1.1 + Origin: http://api.backend.com Host: localhost:9096 Accept-language: zh-cn,zh Connection: Keep alive - the user-agent: Mozilla / 5.0... .Copy the code

If the domain name specified by Origin is within the licensed range, the server sets the response header access-Control-allow-Origin, and the browser checks this field to Allow XMLHttpRequest to get the result properly, otherwise, an error is thrown.

+ Access-Control-Allow-Origin: http://localhost:9096
Set-cookie: token=xxxx; Path=xxx
Copy the code

At the same time, the server maintains the login status of the user through the session-cookie mechanism, and then uses set-cookie to tell the browser to write cookies.

After a successful login, the client sends a getUser interface to obtain user permission information and sends the Cookie to the server.

CORS requests do not send cookies and HTTP authentication information by default. To send cookies to the server, the withCredentials attribute needs to be set to true in the Ajax request, and the server needs to specify the access-Control-allow-credentials field:

+ Access-Control-Allow-Credentials: true
Copy the code

Access-control-allow-origin cannot be set to an asterisk and must specify a specific domain name consistent with the requested web page. This allows normal access to server resources with cookies from different sources.

Why do CROSS-domains still occur when CORS is enabled

By checking the Chrome Network of the browser, it is found that the browser request sent by the getUser interface does not normally carry the Cookie field after successful login. There are many ways to check the problem that cookies cannot be carried.

  • Browsers can disable cookieschrome://settings/cookies? search=cookie
  • As a result of browser plugins, you can consider using traceless mode testing
  • Whether to enable some tools to simulate requests, network Settings problems
  • Is it a Cookie property setting problem, such as domain, path, expiration time, etc.
  • .

After careful investigation, it was found that the problem was caused by the Same-Site property of the Cookie set by the browser, so that the Cookie could not be carried normally.

Cookie’s same-site property is designed to prevent cSRF-cross-site-request-forgery, a cross-site Request Forgery attack in which a Cookie has not expired when the victim visits a website. An attacker can obtain user information by sending a fake link to a victim and tricking them into clicking on it.

Standing with the Same – Site named, it with cross Site, what is the difference between cross-domain, understand the difference between them is helpful to our better understanding of the Same Cookie – Site property.

The difference between same-site, cross-site and cross-origin

Cross domain

In essence, it is a security means for the browser to implement the Same Origin Policy. For the definition of homologous site, the URL protocol (Protocol), port (port), and host (host domain name) are identical.

Co-station and cross-station

As long as the eTLD+1 of two urls is the same, it is the same; otherwise, it is the cross-site, and protocol and port need not be considered.

ETLD: effective top-level domain (eTLD), which is registered in the Public Suffix List maintained by Mozilla, such as.com,.org, and.com

ETLD +1: valid top-level domain name + secondary domain name, such as Taobao.com, Baidu.com, sugarat.top

Refer to the MDN developer.mozilla.org/en-US/docs/…

Cookies are the Same – at Site

Most websites use cookies to store login status, so it is particularly important to protect cookies from being used by three sites. We can set the Samesite attribute value of cookies reasonably to defend against CSRF attacks.

  • strict: strictly verifies whether the site is of the same origin
  • lax: Loose verification. In the case of cross-site, cookies will be carried when links are opened from third-party websites and forms submitted by GET are submitted. However, cookies will be prohibited if the URL is loaded through tags such as IMG or IFrame in third-party websites
  • none: Does not verify whether the third-party site is of the same origin or the same site. Cookies are sent in any case

To solve the problem

The browser disabled the Cookie same-site. Procedure

We can manually disable the Cookie same-site, so that cookies are normally carried to the server. In Chrome, enter Chrome ://flags/

Disable SameSite by default Cookies and Cookies without SameSite must be secure.

  • SameSite by default CookieRules for disabling or enabling SameSite cookies
  • Cookies without SameSite must be secure: When no configuration is setSameSiteProperty or set toNoneTo enable this rule, the cross-site data communication between the front and back ends must be HTTPS.

Before version 91, it was possible to do this. The browser Chrome has been upgraded to version 91, and version 91 is no longer manually closed.

If you want the backend to Set the response header to be closed, Set the Same-Site property to None when setting set-cookie. This is supported only by the HTTPS protocol, and the Secure property must be Set.

Set-Cookie: widget_session=abc123; SameSite=None; Secure
Copy the code

Since you can’t set it manually, is there any other solution?

Option 1: local development will not be upgraded to version 91 for now.

Solution 2: Use reverse proxy to solve this problem.

Let’s talk about plan two.

Use a third-party agent

Before using proxies to solve Cookie portability problems, you need to understand what forward and reverse proxies are.

The difference between forward and reverse proxies is that they provide different service objects,

  • The forward direction is the service to the service acquirer, which is represented by the exit position of the client and mainly solves the problems of the client (such as scientific access to the Internet).
  • The reverse is the service to the service provider, manifested as the network entrance position of the server, mainly to solve the problems of the server (load balancing).

From zhihu a figure www.zhihu.com/question/24…

Forward agent

For example, in the absence of proxies, git clone repositories often have 443 errors, which is the default port open for HTTPS.

git clone https://github.com/alexjoverm/typescript-library-starter.git ts-axios
Cloning into 'ts-axios'.fatal: unable to access 'https://github.com/alexjoverm/typescript-library-starter.git/': LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443 
Copy the code

#Use the SOCKs5 protocolHTTP_PROXY = "socks5: / / 127.0.0.1:1086" HTTPS_PROXY = "socks5: / / 127.0.0.1:1086" git clone https://github.com/alexjoverm/typescript-library-starter.git ts-axios
#Using HTTPHTTP_PROXY = "http://127.0.0.1:1087" HTTPS_PROXY = "http://127.0.0.1:1087" git clone https://github.com/alexjoverm/typescript-library-starter.git ts-axiosCopy the code

Forward proxy: client – proxy server – target server. Then the repository can be downloaded normally.

The reverse proxy

In addition to use reverse proxy for load balancing, you can also use cross-site Cookie to carry the reverse proxy to solve the problem, the core idea is in the front of local use a proxy server, the data transmission way is the target server – a proxy server – the browser, and local proxy server with local browser belongs to stand, don’t cross site problems, There is no restriction of same-origin policy for data transmission between servers, and there is no cross-domain behavior. If Cookie can be forwarded between proxy server and target server, browser can carry Cookie to target server normally.

If you are a Vue project, it is usually constructed by vue-CLI scaffolding. To use the implementation proxy service, you can directly add the devServer.proxy configuration in the VUe.config. js file corresponding to the W configuration of webpack.

module.exports = {
  devServer: {
    port: 9000
    proxy: 'http://backend.com:4000'}}Copy the code

According to devserver. port, the front-end can change the address of the resource request to the corresponding localhost + port form, that is, the front-end can directly request the address of the proxy server, http://localhost:9000, so that the front-end sends the request, because it is the same station as the proxy server, The browser will carry the Cookie, the Cookie through the proxy server to the target server, so that the normal login status can be maintained.

In addition to the above approach, you can also use Node to build a simple proxy server

const http = require("http");
const httpProxy = require("http-proxy"); // Implement the proxy function through HTTP-proxy

const proxy = httpProxy.createProxyServer();

proxy.on("error".function(err, req, res) {
  res.end();
});

const proxy_server = http.createServer(function(req, res) {
  proxy.web(req, res, {
    target: "http://backend.com:18080" // Target server
  });
});

proxy_server.listen(8080.function() { // The port on which the proxy server listens
  console.log("proxy server is running");
});
Copy the code

If the front-end and back-end applications are not on the same server in a production environment, nginx can also be used for proxy forwarding.

  1. Their visithttp://address of the proxy server :9001/eduRequest forward tohttp:// Target server 1:8080
  2. Their visithttp://proxy server ADDRESS :9001/vodRequest forward tohttp:// Target server 2:8081
server { listen 9001; // Proxy server port server_name xxx.xxx // Proxy server domain; Location ~ / edu/{proxy_pass http://target server domain 1:8080; } location ~ /vod/ {proxy_pass http://target server domain 2:8081; }}Copy the code

summary

Cookie same-site processing, in essence, is still a solution to cross-domain problems, which cannot be separated from the industry’s solutions, such as CORS and proxy setting. It can also bypass such processing through token authentication. The front-end gets the token from the server and saves it locally, and writes it into the request header every time a request is made. That’s one way to do it.

The resources

  • Ruan Yifeng explained in detail the CORS mechanism for simple and non-simple request two different processing, as well as client and server configuration differences.

  • When CORS encounters SameSite

  • Browser family Cookie and SameSite properties

  • Git setup proxy

  • Forward proxy and reverse proxy