cookie的工作流
Cookie可以通过服务器进行设置,相当于服务器给用户贴的一个标签,用于跟踪用户的状态
HTTP协议本身是无状态的,而应用服务器想保存一些状态,cookie应运而生,由服务器颁发,通过服务器设置的cookie信息通过响应头返回给浏览器,浏览器将响应头中的cookie信息保存在本地,当下次向服务器发送HTTP请求时,就自动将保存的这些cookie信息添加到HTTP请求头中,传递给服务器
这样的交互,服务器就可以在cookie里记录一些用户相关的信息,比如是否登录,账号等,然后根据这些信息做一些动作,比如接下来的示例中的保存登录状态的实现,就利用cookie。还有一些电子商务网站,实现购物车时也可能用到cookie
使用cookie保持登入态
在看cookie保存用户登录状态的效果前,我们先看下header中的cookies信息记录
header中的cookies
首次登入
响应头信息中增加Set-Cookie参数,但请求头信息中没有Cookie参数
第一次登入后已经将cookie存到了内存中
非首次登入
如果再次点击登录请求按钮,且在没有清空cookie的情况下,发送不同于前一个用户的登录信息,就会出现以下头部信息
此时本地的cookie信息也得到了更新
请求头中的Cookie字段是浏览器发送给服务器的cookie信息,cookie的值是之前存入内存中的userInfo("userName":"zhangsan")。响应头中的Set-Cookie字段是服务器返回给浏览器的cookie信息(实际上,随着用户登录信息的更新,cookie的值又被重新设置了)
因为没有使用删除已有cookie的直接方法,所以在使用相同的路径(path)、域(domain)和安全选项(secure)的情况下,会再次设置原cookie
上面的登入状态,是当我们登录成功后,在这个页面刷新,页面没有保存登录状态。接下来的效果是,后台cookie保存了用户登录状态,登录后刷新页面直接显示首页信息
使用cookie保持登入态
效果demo主要是通过express+nodejs实现的
处理POST正文数据
我们在demo中使用了HTML表单来接收用户名和密码,当我们提交表单信息时,浏览器会把表单内的数据按一定的格式组织之后编码进body,POST到指定的服务器地址
用户名和密码,在服务器端,可以通过HTML元素的名字属性的值找出来
服务器解析表单数据这一过程,是用express的body-parser中间件,只需要简单的配置即可:
var bodyParser = require("body-parser") // 加载body-parser模块
...
// 应用中间件
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
express.Request对象req内有解析好的body,使用
app.post("/login",function(req,res,next){
var userName = req.body.userName
var password = req.body.password
...
}
就可以直接访问用户名和密码,也就是在HTML的input元素中的用户表单值,即建立关联
cookie
cookie存储的是一些key-value对。在express里,Request和Response都有cookie相关的方法。Request实例req的cookies属性,保存了解析出的cookie,如果浏览器没发送cookie,那这个cookies对象就是一个空对象
var Cookies=require('cookies')
app.use(function (req,res,next) {
req.cookies=new Cookies(req,res)
next();
})
实例化一个Cookies()方法,用来设置cookie,res.cookies.set('userInfo',JSON.stringify(...))
,再通过res.cookies.get('userInfo')
的方法来获取cookie
app.use(function (req,res,next) {
req.cookies=new Cookies(req,res)
console.log('cookies',typeof res.cookies.get('userInfo')) //返回 string
//解析用户的cookie信息
req.userInfo={};
var cookiesUserInfo=res.cookies.get('userInfo')
if(cookiesUserInfo){
try{
req.userInfo=JSON.parse(cookiesUserInfo)
}catch(e){}
}
next()
})
第一次点击登录按钮post用户数据时,可以看到已经将用户基本信息写入响应头的set-Cookie了
app.post("/login",function(req,res,next){
var userName = req.body.userName
var password = req.body.password
console.log("User name = "+ userName +",password is" + password)
if(userName===''||password==='') {
resoinseData.code = 1
resoinseData.message = "用户名和密码不能为空!"
res.json(resoinseData) // json格式返回给前端
return
}else {
resoinseData.code = 200
resoinseData.message = "登录成功!请再次刷新页面"
resoinseData.userInfo = {
_id:"5a40caa218013c1dd4eadcb0",
userName:userName,
password:password
}
req.cookies.set('userInfo',JSON.stringify(resoinseData.userInfo))
res.json(resoinseData)
return
}
})
再次刷新页面时,请求头中已经出现了设置的cookie,用户进入免登入状态
app.get("/",function(req,res,next){
if(req.userInfo.userName) {
res.sendFile(path.resolve("index.html")) // 如果请求头中有cookie信息,则加载首页
}else {
res.sendFile(path.resolve("login.html")) // 如果请求头中没有cookie信息,则重新跳转登录页
}
})
再次点击退出按钮时,通过res.cookies.set('userInfo',null)
会将先前设置的cookie信息删除,再次进入登入页
app.post("/loginout",function(req,res,next){
req.cookies.set('userInfo',null)
res.sendFile(path.resolve("login.html")) // 用户登出后再次跳转登录页
})
整个保持登入态的工作流:
用户登录 - 前端发送登录请求 - 后端保存用户cookie - 页面刷新 - 前端判断用户cookie存在 - 显示登录状态 - 用户退出 - 前端发送退出请求 - 后端清空用户cookie - 页面跳转登录页
完整的demo可以查看cookie-demo