In the recent new project, the user login needs to use cookies to remember the user and verify the identity.

In the previous project, cookies were not used to record user login status, but an identity identifier was carried in the header of the request for verification, and the general scheme was as follows:

  • The client uses the POST request to submit the user and password to the server for login.
  • The server verifies whether the user is valid. If the user is valid, a unique authId is generated and returned to the client. The client stores this authId locally (for example, localStorage).
  • The client adds this authId to the header each time it requests authentication.
  • The server checks whether the current authId is valid. If the authId is valid, the current user is valid and the operation is allowed.
  • When a client user logs out, it sends a DELETE request telling the server user to log out and delete the local authId.
  • The server deletes the current authId data after receiving the deregistration request.

The above scheme, if other clients know this authId, can simulate the identity of other clients. It is not safe, so it is deprecated.

Remember users with cookies

In the new project, you will adopt the approach described in this article – using cookies to remember users. The main process is:

  • The client uses the POST request to submit the user and password to the server for login.
  • The server verifies whether the user is legitimate. If legitimate, a unique authId will be generated and returned to the client in the form of cookies.
  • When the client requests the server again, it will carry the cookie that has been obtained before to the server, and the server verifies whether it is legal. If it is legal, it can continue to operate.
  • When a client user logs out, a delete request is sent to tell the server user to log out, and the server deletes the login id. The whole process can be summarized as follows:

Angular is used to build single-page client applications in the foreground, Node is used to build servers in the background, and data is stored in mongodb. These three technologies and basic knowledge of cookies are not introduced in this article. Interested students can learn about them. The following code is the simplest get/ POST request, but it is also the most core part. Other tedious operations related to login, interested students can supplement by themselves.

From start — > end, problems encountered

First of all, I used the most basic POST request, and the server only simply returned data. Part of the simple but core code is as follows:

/ / client ({$HTTP method: "POST", url: 'http://127.0.0.1:8888/rest/user' data: {name: 'xxx',password:'***'} }).success(function (data) { console.log('login success,data is:'+data); }).error(function (data) { console.log('login error'); }).then(function () { console.log(arguments); }); // server var cookie = "authId=" + authId; res.setHeader('Content-Type', 'application/json; charset=utf-8'); res.setHeader('Set-Cookie', cookie + '; Max-Age=3600; HttpOnly=false; Path=/; '); res.writeHead(200, {'Content-Type': 'text/plain'}); res.end();Copy the code

Check chrome debugging, found that although the server side of the cookie pushed over, but the overall problem, prompt as follows:

XMLHttpRequest always load http://127.0.0.1:8888/rest/user. Response to a preflight request doesn 't pass the access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:62427' is therefore not allowed access.Copy the code

After analyzing the problem, it is found that the request from the client cannot access the request from the server across domains. The resource header of the request does not carry information that allows the request to cross. Following this tip, we improved the server code slightly as follows:

// server var cookie = "authId=" + authId; res.setHeader('Content-Type', 'application/json; charset=utf-8'); res.setHeader('Set-Cookie', cookie + '; Max-Age=3600; HttpOnly=false; Path=/; '); Res.setheader (' access-Control-allow-origin ', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); res.writeHead(200, {'Content-Type': 'text/plain'}); res.end();Copy the code

The first sentence allows access to requests from any domain. The second sentence allows access to requests from any domain. Add and run again, the message is as follows:

XMLHttpRequest always load http://127.0.0.1:8888/rest/user. Request header field the content-type is not allowed by Access-Control-Allow-Headers in preflight response.Copy the code

The content-Type header field in the request from the client is not carried in the header of the response message from the server.

var cookie = "authId=" + authId; res.setHeader('Content-Type', 'application/json; charset=utf-8'); res.setHeader('Set-Cookie', cookie + '; Max-Age=3600; HttpOnly=false; Path=/; '); 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'); res.writeHead(200, {'Content-Type': 'text/plain'}); res.end();Copy the code

When we run the code again, we find no error message, but when we request the server again, we find that the client request does not carry the cookie information, which is obviously not what we want:

After consulting for some time, I learned that the client will carry cookies to the server by default. However, when the client requests cross-domain requests, the cross-domain request itself has risks, while carrying cookies also has risks. Therefore, during cross-domain access, the client does not carry the cookie returned by the server. In this case, we need to set “withCredentials” to true on both the client and the server. The code is as follows:

/ / client ({$HTTP method: "POST", url: 'http://127.0.0.1:8888/rest/user', withCredentials: true data: {name: 'xxx',password:'***'} }).success(function (data) { console.log('login success,data is:'+data); }).error(function (data) { console.log('login error'); }).then(function () { console.log(arguments); }); // server var cookie = "authId=" + authId; res.setHeader('Content-Type', 'application/json; charset=utf-8'); res.setHeader('Set-Cookie', cookie + '; Max-Age=3600; HttpOnly=false; Path=/; '); 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 '); res.setHeader(' access-Control-allow-headers ',' content-type ') SetHeader (' access-Control-allow-credentials ', true); // Set the Credentials to true. res.writeHead(200, {'Content-Type': 'text/plain'}); res.end();Copy the code

After running, another error message is found as follows:

XMLHttpRequest always load http://127.0.0.1:8888/rest/user. Response to a preflight request doesn 't pass the access control check: A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost:62427' is therefore not allowed access.Copy the code

After analyzing the error, we found that the reason was that when the carried credentials parameter was set to true, the source allowing cross-domain requests could not be set to generic “*”, so we modified the code again as follows :(final code)

/ / client ({$HTTP method: "POST", url: 'http://127.0.0.1:8888/rest/user', withCredentials: true data: {name: 'xxx',password:'***'} }).success(function (data) { console.log('login success,data is:'+data); }).error(function (data) { console.log('login error'); }).then(function () { console.log(arguments); }); // server var cookie = "authId=" + authId; res.setHeader('Content-Type', 'application/json; charset=utf-8'); res.setHeader('Set-Cookie', cookie + '; Max-Age=3600; HttpOnly=false; Path=/; '); Res.setheader (' access-Control-allow-origin ', '*'); // Replace the generic "*" res.setHeader(' access-Control-allow-origin ', 'http://localhost:62427') with the current client origin; res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); Res. setHeader(' access-Control-allow-headers ', 'content-type '); res.setHeader(' access-Control-allow-headers ',' content-type ') // Set the Credentials to true res.setHeader(' access-Control-allow-credentials ', true); res.writeHead(200, {'Content-Type': 'text/plain'}); res.end();Copy the code

At this point, when the server requests the server for the first time, the server returns cookie information. In the future, every time the client requests the server, the header of the client will carry cookie information, and the effect is shown as follows:

The last

These are some of the problems and simple solutions when using cookies to remember the user’s identity. In Angular applications, HTTP communication may be used more often than not, as long as the parameters of GET/POST/PUT/DELETE request, Set “withCredentials” to true.

☜ ☜ ☜wechat“” “Reward click on the scan code to reward ~~~ ^_^“” “alipay☞ ☞ ☞