NodeJS开发博客(三) 数据的保存

什么是cookie

存储在浏览器的一段字符串(最大5k)

跨域不共享

格式如 k1=v1 k2=v2 因此可以存储结构化数据

每次发送http请求,会将请求域的cookie一起发送给server

server 可以修改 cookie 并返回给浏览器

浏览器也可以通过 JS 修改 cookie (有限制)

参考 lesson5;

---

session方法

首先解释何为 seesion【注意和 sessionStorage做区别】

首先,我大致的知道,session是一次浏览器和服务器的交互的会话,会话是啥呢?就是我问候你好吗?你回恩很好。就是一次会话,那么对话完成后,这次会话就结束了,还有我也知道,我们可以将一个变量存入全部的$_SESSION['name']中,这样php的各个页面和逻辑都能访问到,所以很轻松的用来判断是否登陆。

 
这是我之前理解的session,当然也是对的,只是解释的太肤浅,理解的太表面了,面试官如果听到这样的答案其实是不太满意的。我参考了其他的很多资料,彻底理解清楚session。
 
在说session是啥之前,我们先来说说为什么会出现session会话,它出现的机理是什么?我们知道,我们用浏览器打开一个网页,用到的是HTTP协议,学过计算机的应该都知道这个协议,它是无状态的,什么是无状态呢?就是说这一次请求和上一次请求是没有任何关系的,互不认识的,没有关联的。但是这种无状态的的好处是快速。
 
所以就会带来一个问题就是,我希望几个请求的页面要有关联,比如:我在www.a.com/login.php里面登陆了,我在www.a.com/index.php 也希望是登陆状态,但是,这是2个不同的页面,也就是2个不同的HTTP请求,这2个HTTP请求是无状态的,也就是无关联的,所以无法单纯的在index.php中读取到它在login.php中已经登陆了!
 
那咋搞呢?我不可能这2个页面我都去登陆一遍吧。或者用笨方法这2个页面都去查询数据库,如果有登陆状态,就判断是登陆的了。这种查询数据库的方案虽然可行,但是每次都要去查询数据库不是个事,会造成数据库的压力。
 
所以正是这种诉求,这个时候,一个新的客户端存储数据方式出现了:cookie。cookie是把少量的信息存储在用户自己的电脑上,它在一个域名下是一个全局的,只要设置它的存储路径在域名www.a.com下 ,那么当用户用浏览器访问时,php就可以从这个域名的任意页面读取cookie中的信息。所以就很好的解决了我在www.a.com/login.php页面登陆了,我也可以在www.a.com/index.php获取到这个登陆信息了。同时又不用反复去查询数据库。
 
虽然这种方案很不错,也很快速方便,但是由于cookie 是存在用户端,而且它本身存储的尺寸大小也有限,最关键是用户可以是可见的,并可以随意的修改,很不安全。那如何又要安全,又可以方便的全局读取信息呢?于是,这个时候,一种新的存储会话机制:session 诞生了。
 
我擦,终于把session是怎么诞生的给圆清楚了,不容易啊!!!
 
好,session 诞生了,从上面的描述来讲,它就是在一次会话中解决2次HTTP的请求的关联,让它们产生联系,让2两个页面都能读取到找个这个全局的session信息。session信息存在于服务器端,所以也就很好的解决了安全问题。
 
--------
 session 保存数据的问题:
 
 
 
解决方案:
web server 最常用的缓存数据库,数据存放在内存中;
相比于 mysql,访问速度快 内存和硬盘不是一个数量级的
但是成本高,可存储的数据量小(内存的硬伤)
 

安装 redis

mac:访问  https://brew.sh/index_zh-cn ,执行


/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

就能安装上 brew
执行 redis-server
然后新打开终端执行 redis-cli


最基本的命令:
set myname lihua
get myname
keys * //可以看到当前所有的key
del myname //删除key
目的: nodejs 连接 redis 的demo;  封装成工具函数,可以供 API 使用
首先启动 redis: redis-server 端口是 6379

新建一个项目,npm init
然后 安装redis: npm i redis --save
新建index文件:
const redis = require('redis')
//创建客户端
const client = redis.createClient(6379,'127.0.0.1');

client.on('error',err=>{
    console.error(err)
})
//redis.print 会在执行完命令后打印出是否正确
client.set('myname','zhangsan2',redis.print)
client.get('myname',(err,val)=>{
    if(err){
        console.log(err);
        return;
    }
    console.log('val:',val);
    client.quit()
})

执行 node index.js 

然后可以启动 redis-cli 查看 get myname

============================

接下来开始操作原来的博客项目,首先安装 redis: npm i redis -save
详见代码。

===========================
和前端联调

首先npm install http-server -g
http-server -p 8001 //设置端口

===================

nginx介绍:

 



 以上是mac命令,对于windos如下:

1 首先修改配置文件  sudo vi /usr/local/etc/nginx/nginx.conf 

1) 修改 端口为 8080

server{
  listen  8080;
  server_name localhost  
}

2)

location / {
   proxy_pass http://localhost:8001;  
}

location /api/ {
   proxy_pass http://localhost:8000;  
   proxy_set_header Host $host;
}

最后执行 wq 保存退出

然后启动  nginx 

访问http://localhost:8080/ 就可以访问到 localhost:8001 的html

访问的接口api 就访问到了 localhost:8000的api

【所以要同时启动 服务端8000;客户端8001;nginx的服务;redis的服务】【没有启动8080的,但是通过nginx,可以通过8080访问其他端口】

[注意:如果接口访问不到 请注意排查一下是不是接口写的是post,而你用的是get请求]

=========

最后 一些小修改:

admin.html 中,由于只能访问自己的页面:

 
let url = '/api/blog/list?isadmin=1' // 增加一个 isadmin=1 参数,使用登录者的用户名,后端也需要修改 !!!
 
let author = req.query.author || '';
      let keyword = req.query.keyword || '';
      //新增admin部分
      if(req.query.isadmin){
        const loginCheckResult = loginCheck(req);
        if(loginCheckResult){
          //未登陆
          return loginCheckResult
        }
        // 强制查询自己的博客,也就是说有这个参数的时候,不在使用url上给到的usernam
        // 而是使用当前登陆信息中的 username
        author = req.session.username
      }
 ===============
至此,根据分支:trunk.lesson7---是服务端代码 执行npm run dev 运行在 8000端口
分支 trunk.htmls---是客户端代码,执行http-server -port 8001 运行在 8001端口 // 或者 http-server -p 8001
开启 nginx服务,配置了8080端口,和代理8000与8001的接口,可以访问 8080端口
开启redis服务,可以存储相应的 redis数据
 
 
 
//app.js中的session和cookie和redis的配置
const session = require('koa-generic-session');
const redisStore = require('koa-redis');
const { REDIS_CONF } =require('./conf/db');

app.keys=['keys'];
app.use(session({
  cookie:{
    httpOnly:true,
    path:'/',
    maxAge:24*60*60*1000
  },
  store:redisStore({
    all:`${REDIS_CONF.host}:${REDIS_CONF.port}`
  })
}))

//给session赋值的时候,会触发 生成cookie
ctx.session.username = ctx.request.body.username;

cookie-->session-->redis
浏览器和服务器通过cookieid获取到session
保存的session通过app中的配置,会把session保存到redis中,同时会生成一个cookieid;
通过cookied可以获取到所有的session信息

 
原文地址:https://www.cnblogs.com/xiaozhumaopao/p/11105621.html