Pre-code download
Github.com/18888628835…
preface
When we log in to a web page, as long as the input account password, if the account password is the same as when registering, then it will prompt login success and jump to the page, if the failure will prompt failure. So, what data conversion has taken place from user registration to login, and how does the interaction between the front and back end occur? This is the problem I want to describe today. This blog is a record of simulating small functions of user login, and I will repeat what I have learned here.
Before I started, I had to use JSON files as my database for device reasons, and everything revolved around JSON files.
The whole page jump process looks like this: Register — login– home page index
Our preferred goal is to set a small target and simulate a registration function first
Registration procedure
-
We need to write a registration page
-
Use jquery ajax to transfer data to the back end
-
The back end receives the data and uses Node.js to process it
-
Put the data into a JSON file
Of course, before doing this, we need to write the basic code of the static server, which can be viewed in the pre-code.
The preparatory work
- Three HTML pages: login, registration and home page respectively
- A server written in simple Node.js
- A JSON file named mysql is used as the database
The pre-work code is in the init folder of the pre-code download
The registration page uses Ajax
How to create a form form is not explained here, here is ajax jquery code for further explanation
const $form = $('form') $form.on('submit', (e) => {e.preventDefault() const userId = $form.find('input[name=userid]').val( $form.find('input[name=password]').val() $.ajax({url: './registered', method: 'POST', contentType: "text/json; Charset = utF-8 ", data: json.stringify ({// must convert to a JSON string before passinguserId: userid, password: password})})Copy the code
Jquery’s Ajax wrapper is called when the form triggers a Submit event. Since the default behavior when submitting the form is to refresh the page, we first block the default behavior with e.preventDefault(), and then pass an object with jquery’s Ajax wrapper. Note that it is important to use json.stringfy () to pass the user-written value, because if I do not do this, I will never get the pass encoding right when I write the back-end code.
Write to the server node.js
We can use the Request. on(‘data’,()=>{}) event to retrieve JSON data passed by AJAX. Since bytes may be passed in segments, we use a [] array to prevent data being passed
Const ajaxData = [] request.on('data', (data) => {ajaxdata.push(data) //Copy the code
Then use the request.on(‘end’,()=>{}) event to receive all the downloaded code
Query the contents of the JSON file
// Node reads data from a JSON file
Const fs = require('fs') // const data = fs.readfilesync ('./mysql.json') // const mysql = json.parse (data)Copy the code
Turn ajax data into objects
Const jsonData = json.parse (string) const string = buffer.concat (ajaxData).toString()Copy the code
Write data to a file
const newdata = {
id: id,
userid: jsondata.userid,
password: jsondata.password
}
mysql.push(newdata)
fs.writeFileSync('./mysql.json', JSON.stringify(mysql))
Copy the code
Id value
Since all data tables in the database always follow an absolutely unique code, after we get the Ajax data and process it, we need to give an ID and save it to the file along with the ajax data we get
let id = mysql[mysql.length - 1] ? (mysql[mysql.length-1]. Id +1) : 1; (mysql[mysql.length-1]Copy the code
The registration page writes functions that ajax passes successfully
As the Ajax standard uses promise objects, the. Then () function can be used. When ajax succeeds, the promise object itself will be fulfilled, then the first function parameter of the THEN function will be called, with the code as follows
.then(()=>{ location.href='./login.html' })
At this point, the registration function is basically complete.
The login
The operation during login is almost the same as the code during registration, including the AJAX code. We only need to change the registration in the form form to login, and the code after AJAX success is changed to jump to index.html after success, and the account password error message is displayed if failure.
The location.assign() method is introduced here to jump to the page, because if you use location.href to jump to the page, you might not be able to jump to the prompt box.
location.assign('./index.html')
Copy the code
Server code
We just need to verify that the ajax data submitted is the same as the json file, using the array.prototype. find method
This method returns the value of the first element in the array that satisfies the provided test function. Otherwise return undefined.
The code is as follows:
If (path === '/public/login.html' && request.method === 'POST') {let arr = []// request. On ('data', (data) => { arr.push(data) }) request.on('end', () => { const arrdata = JSON.parse(arr) response.setHeader('Content-type', 'text/html; charset=UTF-8') let sql = JSON.parse(fs.readFileSync('./mysql.json')) const n = sql.find((val) => { return val.password Userid === arrData.password && val.userId === arrdata.userId}) //find the return value if (n === undefined) {response.statusCode = 400 } else {response.statuscode = 200} response.end(' send ')})Copy the code
The above code uses the find method to determine if the value is undefined. If it is, the corresponding data cannot be found in the JSON file, and the front end returns “jump failed”.
Login complete, set a small goal
Registration to login has been completed, now if the verification is successful should jump to the home page. Now I have a new requirement, when I log in and go to the home page, let the home page show that the user is logged in.
But at this time encountered a problem, how to let the server know that I was logged into the home page or not logged into the home page? The difference between the two is that after login, the home page prompts the user to log in, and if not, the home page is in the original state
Enter the home page
cookie
In real life, if we want to enter a charging park, then someone will check the ticket, this ticket is the proof that you have not charged, so the demand above, is similar to this?
Assuming that the user has logged in, the server sends a ticket to the user, so is it possible to achieve the login page and not logged in inconsistent situation?
This ticket is a cookie, it is saved by the browser, we can use the server code to successfully log in to the user to send a cookie, how to set? We set it in the HTTP response header
When the user clicks login, we give this cookie to the user, set-cookie MDN
Note that cookies need to be set by the back-end code and set to not allow the front-end to modify the syntax:
response.setHeader('Set-Cookie', 'xxx=xxx; HttpOnly')Copy the code
However, cookie has a disadvantage, that is, even if the written cookie cannot be tampered with, it can still be modified through the Application of the browser. After tampering, it is equivalent to getting the ticket. Then, if it happens to be the cookie of other users, it is equivalent to getting other users’ data, right?
So how do you solve this security problem?
The session session
In fact, this problem is nothing more than the value of the cookie value problem, if the cookie is enough random digits, then even if the cookie is not modified, because it does not match other users.
So we can solve it like this:
Create a JSON file session. JSON to store the random number and make the random number correspond to the user ID. As long as the cookie is the random number, the user information corresponding to the ID will be sent out.
This method has a fancy name called session
So our design process should be like this:
- First, the user logs on to the home page
- We check the user’s cookie for the specified cookie
- If not, go to the default home page
- If so, we’ll change the default home page username
The data flow should look like this: if the user’s cookie is obtained, then make a judgment to see if it can be found in session.json. If it can be found, then it does represent the target customer, and we take the id of the corresponding target user
So what can we put inside session.json? {” random number “, {id: XXX}}
Login code is perfect
const n = sql.find((val) => { return val.password === arrdata.password && val.userid === arrdata.userid }) // Check whether the login account and password are the same. If (n === undefined) {// If (n === undefined) {// If (n === undefined) {return code 400 response.statusCode = 400} else {response.statusCode = 200 const Parse (fs.readfilesync ('./session.json')) // Read the new session file const random = math.random () // Set a random number session[random] = { 'userid': Fs.writefilesync ('./session.json', json.stringify (session)) // return the cookie to the user with the random number. Responsetheader (' set-cookie ', 'sessionId =${random}; HttpOnly`) }Copy the code
In the code above, I set a random number cookie to the user, which is equivalent to the cookie is a string of very long keys. As long as the user enters the home page, check whether there is this cookie, and then check whether the cookie is correct
The home page code
if (path === '/index.html') { response.statusCode = 200 response.setHeader('Content-type', 'text/html; Parse (fs.readfilesync ('./mysql.json')) charset= utF-8 ') let cookie = request. Parse (fs.readfilesync ('./session.json')) let sessionId try {sessionID = cookie.split('; ').filter(s => s.idexof (" sessionId =") >= 0)[0].split("=")[1] If (sessionId) {// If (sessionid) {// If (sessionid) { Let user = mysql.find((user) => {return user.id === session[sessionId].userId}) let string = "if String = fs.readfilesync ('./public/index.html').toString().replace('{{username}}', Response.write (string)} else {response.write(fs.readfilesync ('./public/index.html')}} else {response.write(fs.readfilesync ('./public/index.html')}} else { response.write(fs.readFileSync('./public/index.html')) } response.end()Copy the code
Stern said
The above code is just a crude description of some of the problems and solutions that exist in front and back end interaction. In the actual development process, we will encounter more complex, more safety related problems, and deepen our understanding and awe of the program as we constantly modify the logic through trial and error.