首先,写一个简单的注册页面sign_up.html(前端)
1 | <div class="form-wrapper"> |
把用户输入的内容放到一个哈希中(前端)
1 | let $form = $('#signUpForm') |
给server.js里添加一个路由,如果请求路径是/sign_up,就显示当前目录下的sign_up.html文件(后端)
1 | if(path === '/sign_up'){ |
node server 8080
打开server,访问http://localhost:8080/sign_up
就可以看到我们写的注册页面。
尝试发送一个Ajax post请求:jQuery.post() (前端)
1 | $.post('/sign_up', hash) |
打印出来一个html格式的字符串,因为server.js中写明了只要请求路径是/sign_up就表示请求成功,返回字符串。
由于这是一个post请求,如果在路由里将请求方式的限制为get,则会打印出‘error’:(后端)
1 | if(path === '/sign_up' && method === 'GET'){ |
所以要再添加一个请求方式为post的路由:(后端)
1 | if(path === '/sign_up' && method === 'POST'){ |
现在用户向sign_up发送post请求,服务器得到的请求的第四部分是一个字符串'email=1&password=2&password_confirmation=3'
,使用split()方法将其变成哈希:(后端)
1 | let strings = body.split('&') // ['email=1', 'password=2', 'password_confirmation=3'] |
以上所做的事情总结起来就是:
客户端收集form表单内容到一个hash中,作为一个字符串传给服务端,
服务端以一个字符串的形式拿到表单内容,
再将其还原为一个hash。
这就是前端向后台传数据的方式:前端把所有东西变成一个字符串传给后台,后台从字符串里按照所要的结构解析出来。
现在服务器有了一个包含表单信息的hash,继续进行验证:(后台)
1 | let {email, password, password_confirmation} = hash |
(前端)
1 | $.post('/sign_up', hash) |
前端也可以在发起请求之前进行一些验证:(前端)jQuery.each()
1 | $form.find('.error').each( (index, span) => { |
现在,我们实现的功能是邮箱、密码、验证密码必填,密码与验证密码相同(前端验证),邮箱中必须有‘@’(后端验证)。
由于前后端代码都是JS,所以后端的验证前端都能做到。但是前端可以不验,后端必须要验。例如用curl
发请求的话,可以直接与服务器交流。所以不能依赖浏览器上的JS,必须确保后端是安全的。
验证成功之后,服务器需要将得到的信息保存到数据库中。这里我们在当前目录下创建db/users
文件作为数据库,初始化为一个空数组[]
。(后端)
1 | var users = fs.readFileSync('./db/users', 'utf8') |
现在有个问题,同一个邮箱可以多次注册。服务器可以在将信息存入数据库之前验证邮箱是否已注册:(后端)
1 | var users = fs.readFileSync('./db/users', 'utf8') |
至此注册过程完成。接着来做登录功能。
首先写一个登录页面sign_in.html:(前端)
1 | <body> |
在服务器上给sign_in.html写一个路由:(后端)
1 | else if (path === '/sign_in' && method === 'GET') { |
登录页面与注册页面相似,客户端将表单信息收集到一个哈希中,在发起请求时传一个字符串给后端;后端将得到的字符串解析为哈希。
后端得到包含email和password的哈希后,与数据库进行对比(看数据库里有没有一样的email和password),认证用户:(后端)
1 | let { email, password } = hash |
登录成功时跳转到首页:(前端)
1 | $.post('/sign_in', hash) |
现在有一个问题:即使没有登录,用户也可以直接访问首页,与登录后看到的页面相同。
这里我们需要用到Cookies。HTTP Set-Cookie
服务器在认证用户成功后,给返回的响应头中添加Set-Cookie
:(后端)
1 | if (found) { |
选中开发者工具的Preserve log,再次登录。
我们可以看到,在向sign_in发起请求时,得到的响应头中有一项Set-Cookie: sign_in_email=1@luke.com
,而请求成功后接着对主页发起的请求的请求头中带着这个Cookie:Cookie: sign_in_email=1@luke.com
。
这就是Cookie的作用:服务器响应中给页面发送一个Cookie,之后同源发起的请求都带着这个Cookie作为识别。
理解:第一次进公园时售票员给你两天的票(Set-Cookie),票就是Cookie,两天内可以多次进入公园,每次都要带着票给售票员看。
Cookie特点:
- 服务器通过
Set-Cookie
响应头设置Cookie - 浏览器得到Cookie之后,每次请求都要带上Cookie
- 服务器读取Cookie就知道登录用户的信息
问题:
- 我在Chrome登录得到了Cookie,用Safari访问,Safari会带上Cookie吗?
no - Cookie存在哪?
Window存在C盘的一个文件里,其他系统也都存在硬盘的一个文件里。 - Cookie能作假吗?
可以。Chrome开发者工具Application-Cookies就可以改。所以Cookie是不安全的。HttpOnly
可以限制。 - Cookie有有效期吗:
默认有效期20分钟左右,由浏览器决定。后端可以强制设置有效期。
现在我们让登录的用户在跳转到首页时可以看到自己的密码:(后台)
1 | if (path === '/') { |
index.html:
1 | <body> |
总结一下流程:
- 用户打开sign_up注册,向服务器发送post请求,发送email,password,password_confirmation;
- 服务器验证通过,把用户信息写进数据库,并告诉用户注册成功;
- 用户打开sign_in登录,发送post请求,发送email和password;
- 服务器认证通过,Set-Cookie;
- 用户带着Cookie打开首页,发送get请求;
- 服务器读取Cookie,从Cookie中得到email,根据email从数据库找到匹配的用户信息写入页面;
- 这样登录的用户进入首页时可以看到自己的信息;
- 没有登录的访客进入首页看到不同的页面。
完