directory

  • 1. Bugs
  • 2. Try to solve the case
  • 3. Cross-domain detailed solution
    • 3.1 What is sympatric (homology)?
    • 3.2 What is cross-domain (how does cross-domain happen?)
    • 3.3 What Are The Cross-domain Security Issues?
    • 3.4 What Is the Browser Same-Origin Policy?
    • 3.5 What is CORS (Cross-Domain Resource Sharing)?
    • 3.6 “Simple” and “Complex” cross-domain request lifetime
  • 4. To summarize
  • reference
  • Update record
  • Related articles recommended

1. Bugs

Two onsite systems integrate the same single sign-on. The browser refreshes twice when one system jumps to the other.

Oddly enough, if you turn on F12, you can’t repeat the problem.

2. Try to solve the case

Open the console and the problem is solved? How strange! Static files are no longer cached in the browser after the console is opened.

Enable F12 Disable console Network –> Disable cache Settings, and sure enough, the problem can be repeated, front-end JS requests are indeed cached.

The reason for the two refreshes is as follows: The front-end JS cache causes that the asynchronous permission data request interface does not have the permission (the request is refreshed for the first time), and the SSO service is redirected to obtain the Service ticket. After the login, the sso service requests the permission data interface again (the request is refreshed for the second time). The page is displayed successfully.

I’m not familiar with browser behavior, so this is just a guess.

In this paper, single sign-on (SSO) is implemented on the CAS interface. Therefore, after the application session expires or expires, you need to obtain the Service ticket from the SSO again.

Refresh the browser twice to capture fiddler packets as shown below:

After the first asynchronous request, the 302 redirects to the single sign-on service because there is no permission. Here the console prompts for cross-domain requests, which are explained in the cross-domain section.

The front end clearly says it’s not a front end problem, it can’t be solved.

The front end of my company is hard.

In the background processing, the background is the SpringBoot project, add configuration:

spring:
  resources:
    cache:
      cachecontrol:
        max-age: 0
Copy the code

Front-end files are not cached. Problem solved.

After caching is disabled, the address bar will not refresh twice. Fiddler captures packets as shown in the following figure:

With the problem resolved, I became interested in the cross-domain error. Before also read many cross – domain article, always cross – domain cloud in fog. The Spring Festival finds out the cross domain article that collects, read up well, gain somewhat, borrow this article to share hurriedly come out.

3. Cross-domain detailed solution

Do web development, work must have encountered the following browser console error:

No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

The header of the requested cross-domain resource response does not contain access-Control-Allow-Origin information.

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at example.com/

The same origin policy forbids reading cross-domain resources.

Access to fetch at ‘example.com’ from origin ‘http://localhost:3000’ has been blocked by CORS policy.

Access to domain https://example.com resources in domain http://localhost:3000 is prohibited.

Now that you know what these errors really mean, you can handle cross-domain problems.

3.1 What is sympatric (homology)?

  1. Same protocol (HTTP, HTTPS)
  2. Same host name/IP (127.0.0.1, localhost, google.com)
  3. Same port (80, 443, 8080)

All three conditions are homologous, otherwise it’s a different domain.

Note: The localhost hostname will eventually resolve to 127.0.0.1 at the network layer, but for the browser’s same-origin policy, localhost and 127.0.0.1 are different hostnames, and if they are different, they are cross-domain.

3.2 What is cross-domain (how does cross-domain happen?)

The World Wide Web, which came out in 1989, started out as text-only HTML.

The world’s first Web page, containing only plain text and hyperlinks.

The tag was introduced in 1993 to allow image resources to be loaded during HTML rendering so that images can be displayed in plain text. Tags like this allow loading of subresources in HTML:

  • <ifame>
  • <link>
  • <form>
  • <audio>
  • <video>
  • <script>

Subresources are external resources such as forms, files, audio and video, scripts, etc.

Subresource is loaded when a field contains an HTML render with the above tag, and a cross-domain request occurs when the subresource is from a different source than the current field. For example, an XMLHttprequest (Ajax) request in one domain to an interface in another domain is a cross-domain request.

3.3 What Are The Cross-domain Security Issues?

In most cases, the loading of subresources such as files, audio and video files, scripts, etc. from one domain to another does not cause security problems, but in some cases, there are security risks if you do not restrict them.

For example, a domain that provides a cookie/session authentication based mail sending interface allows cross-domain requests from any domain to the interface. Then malicious websites may arbitrarily call the sending mail interface to attack websites after obtaining valid cookies.

Some students may ask: If the email sending interface needs authentication to be successfully invoked, how can it be successfully invoked without authentication information?

In fact, after the user logs in to the browser, the user information is stored in the browser (cookie). In this case, malicious websites may be attacked by malicious scripts carrying user information.

3.4 What Is the Browser Same-Origin Policy?

Since cross-domain requests have security issues, browsers impose restrictions called “browser same-origin policies.”

The same origin policy prevents reading resources that are requested across domains.

This is a broad definition. In fact, browsers have different limiting policies for different subresources, as described below.

The same origin policy was introduced in netscape browser 2.02 in 1995 and was originally designed to secure the cross-domain DOM.

Cross-domain requests take three forms:

  1. Cross-origin writes
  2. Cross-origin Embeds
  3. Cross-origin reads

The rules of the same-origin policy are defined as follows:

  • <ifame>: Cross-domain embedding is allowed (appropriateX-Frame-Options).
  • <link>: Cross-domain embedding is allowed (appropriateContent-Type).
  • <form>: Allows cross-domain write.
  • <audio>: Cross-domain embedding is allowed.
  • <video>: Cross-domain embedding is allowed.
  • <script>: Cross-domain embedding is allowed, and some API calls may be prohibited (e.gajaxCross-domain call).
  • <img>: Cross-domain embedding allows cross-domain reading through JavaScript or in<canvas>Loading is disabled.

3.5 What is CORS (Cross-Domain Resource Sharing)?

The same origin policy of the browser can solve many security problems, but its limitation also brings inconvenience.

Cross-origin Resource Sharing (CORS) is used to relax the strict restrictions of the same Origin policy of the browser and facilitate the use of resources in certain scenarios.

Domain request, as shown in figure:

Cross-domain request, as shown:

The preflight request is described below.

3.6 “Simple” and “Complex” cross-domain request lifetime

Here we focus on the process and resolution of ajax cross-domain requests using the browser’s built-in fetch() function.

When Ajax in one domain makes a cross-domain request to an interface in another domain, the lifetime of the request is determined by both the client and the requested resource server. The behavior of the client is specified by the same origin policy of the browser, and the behavior of the requested resource server is provided by the implementation of the resource provider. To be specific:

The “life history” of a request is when the request is initiated by the browser, the server responds to it, and the browser reads the response and displays the process.

If it’s “easy”ajaxCross-domain request, then the browser will allow the request if the server does not contain itAccess-Control-Allow-OrigintheheaderInformation, then the browser will restrict the request to the resourcereponseRead.

If it is “complex”ajaxCross-domain request, then the browser will trigger one of its ownpreflightRequest, according to the corresponding serverheaderInformation determines whether to permit a client request.

“Simple” and “complex” requests are defined by the relevant specification, and a “complex” request must satisfy at least one of the following conditions:

  1. nonGET,POSTorHEADThe request.
  2. The request header information contains divided byAccept,Accept-LanguageorContent-LanguageExternal header information.
  3. requestContent-TypeThe value is notapplication/x-www-form-urlencoded,multipart/form-dataortext/plain.

2. Does not include the header information that the browser automatically adds to the request, such as Origin.

Next, start the HTTP interface service with Crystal and look at the lifetimes of different cross-domain requests:

The basic_greet.cr script is as follows:

require "kemal"

port = 4000

get "/" do
  "Hello world!"
end

get "/greet" do
  "Hey!"
end

post "/greet" do |env|
  name = env.params.json["name"].as(String)
  "Hello, #{name}!"
end

post "/greet_str" do |env|
  name = env.params
  "Hello, success!"
end

Kemal.config.port = port
Kemal.run
Copy the code

Run the sudo crystal run SRC /basic_greet.cr command to enable the interface service.

0). Local request

Domain from http://172.22.27.215:4000/greet interface to send “simple” ajax requests, as shown in figure:

In the same domain request, all is well, the interface can initiate successfully and the browser can read the response interface data.

Different browser consoles are implemented differently (but with the same specification), and FireFox is used as the test browser.

1). “simple” POST cross-domain request

Send a “simple” Ajax request from tianya BBS forum, as shown in the picture:

The interface can be successfully initiated. Procedure CORS header ‘access-Control-allow-origin’ missing, CORS header ‘access-Control-allow-origin’ missing This means that access-Control-Allow-Origin information is missing from the response header.

This is a “simple” request because the content-type is text/plain. Refer to the “complex” request rule above.

This is because the Crystal interface is HTTP. If invoked in the HTTPS domain, the browser will directly prohibit requests for HTTP resources in the HTTPS domain.

2). “complex” POST cross-domain writes

Send “complex” Ajax requests from tianya BBS forum domain.

Console error as shown in the figure:

Network packet capture is shown as follows:

1. In the figure, is the Preflight request. The request method is OPTIONS. 404 Not Found is displayed because the OPTIONS method is Not implemented on the server.

In the figure, 2 is a real POST request, because 1. ‘s preflight request did not get the same origin policy header information, so 2. The actual POST request is blocked at the browser level.

Note that the OPTIONS request 2 in the figure is sent by the browser. The browser carries header information, such as Origin, access-Control-reqest-method, and access-Control-reqest-headers.

In this case, the request lifetime is: the preflight request 404 Not Found, the actual POST request was Not initiated successfully. That is to say: “die before you get started”.

What is the implementation of the “complex” cross-domain request Preflight required to satisfy the browser CORS protocol?

The browser will look for two headers in the response after sending preflight:

  • Access-Control-Allow-Methods:CORSRequest methods allowed by the protocol, for exampleGET,POSTAnd so on.
  • Access-Control-Allow-Headers:CORSProtocol allowed requestsheader, e.g.Content-TypeAnd so on.

For the lifetime of a “complex” request, the above two headers must match the actual client request information, or the actual client request may be blocked at the browser level. To put it bluntly, what method requests and headers the server allows the client to send successfully.

The preflight response can also return two headers that tell the client something:

  • Access-Control-Max-AgeSet:preflightThe number of seconds a request can be cached (default is 5). After the set time, the browser will re-initiate “complex” requestspreflight; Within the set time, no more initiatepreflightRequest (using cachedpreflightRequest).
  • Access-Control-Allow-CredentialsSet:Actual client requestWhether it can carry user information (e.gcookie).

If the server does not return the above two headers, the lifetime of the request is not affected.

That is to say, under the CORS agreement, Access-control-allow-methods and access-Control-allow-headers Headers must be specified in the preflight request response Headers. Then the browser will agree to send the actual client request. Access-control-max-age specifies the duration of the preflight request cache. The default value is 5 seconds. The access-Control-allow-credentials preflight response header tells clients whether the user information can be carried in the actual request, or not.

The actual client request is block-marked here to emphasize that the request is not confused with the Preflight request. When a “complex” cross-domain request is made, the browser first sends a preflight request to “test” whether the server will allow the request. If so, the browser will allow the “complex” request (i.e. the actual client request) to be made immediately after the PreFlight request. Otherwise it will be blocked by the browser.

Implement the preflight request as requested.

“Basic_greet. cr” basic_greet.cr

options "/greet" do |env|
  # Allow `POST /greet`...
  env.response.headers["Access-Control-Allow-Methods"] = "POST"
  # ...with `Content-type` header in the request...
  env.response.headers["Access-Control-Allow-Headers"] = "Content-type"
end
Copy the code

Restart the interface service, and the console requests again, as shown in the figure below:

Access-control-allow-origin information is missing from the response header. In other words, the preflight request was successful. The preflight request response header required by the CORS protocol also exists. However, due to the absence of the Access-Control-Allow-Origin header, the browser Origin policy restricts the Access to the request response.

Env.response. headers[” access-Control-allow-origin “] = “http://bbs.tianya.cn” :

options "/greet" do |env|
  # Allow `POST /greet`...
  env.response.headers["Access-Control-Allow-Methods"] = "POST"
  # ...with `Content-type` header in the request...
  env.response.headers["Access-Control-Allow-Headers"] = "Content-type"
  # ...from https://www.google.com origin.
  env.response.headers["Access-Control-Allow-Origin"] = "http://bbs.tianya.cn"
end
Copy the code

Rerequest:

Preflight request successful, as shown below:

The console still has an actual client request error, but this error is familiar:

No access-Control-allow-Origin information is contained in the response header. The browser cannot read the response content. Add response header information to the interface:

post "/greet" do |env|
  name = env.params.json["name"].as(String)
  env.response.headers["Access-Control-Allow-Origin"] = "http://bbs.tianya.cn"
  "Hello, #{name}!"
end
Copy the code

Rerequest:

The preflight of the “complex” request and the actual client request were successful, realizing the cross-domain resource sharing of the “complex” request.

The entire lifetime of a “complex” request is summarized as shown below:

4. To summarize

  • Look like the problem of metaphysics, its backside has certain reason. Whether it can be accurately identified depends on the understanding of the breadth and depth of the relevant knowledge involved in the problem. To learn more and dabble with curiosity can increase the breadth of knowledge, and to analyze the technical points and their sources with the will of exploration can dig the depth of knowledge.
  • Mature programmers do not know everything, but when faced with problems involving their own areas of ignorance, can quickly identify the blind spot and learn to master.
  • Cross-domain summary: Due to the security risks of cross-domain requests, the same origin policy is configured by the browser to restrict cross-domain requests (to a certain extent). Cross-domain resource sharing relaxes the strict restrictions of the same origin policy based on certain rules, facilitating data interaction between different domains. Cross-domain problems, once they arise (especially when the front end is completely separated from the project), require the front and back ends to work together to solve them. Whether an interface is allowed to be cross-domain requested or not is informed by the server’s oral message to the browser, and the setting of the client’s request parameters, especially the configuration related to cookie information carrying, can only be completed by the client’s understanding of the principle.

reference

  • Ieftimov.com/post/deep-d…
  • Mobilejazz.com/blog/which-…

Update record

  • 2022-02-07 18:10 First submit an article to Brother Feng.
  • 2022-02-08 18:27 wechat public account “Feng Brother painting Halberd” before the article was published reread, optimization, correction.
  • 2022-02-09 12:40 Nuggets column reread, optimise, erratum before publication.

Related articles recommended

  • Front – and back-end split item cross – domain problem with back-end authentication

Wechat public account search “Feng Brother painting Halberd” to follow Feng Brother, the first time to watch more exciting content. You can’t tell the client you want to press F12, can you? (Cross-domain details)