动态服务器

460 阅读9分钟

与静态服务器的区别

判断依据

  • 是否请求的数据库
  • 没有请求数据库就是静态服务器
  • 请求的数据库就是动态服务器

使用json文件当做数据库

  • 本地服务器,相关文件路径
  • server.js沿用静态服务器文件

11e83930a44e8894c8132dbb042a9ef.png

  • 手动写入users.json文件内容

1635496570(1).png

读数据

  • 引入测试文件,读取json文件中的内容
    • 首先定义请求
    • 请求读取JSON文件(以下简称库)内容,得到的是对象(对象无法识别),再次转化成字符串
    • 调用JSON.parse(),将以上字符串进行解析,得到数组

1635496785(1).png 1635497273(1).png

写入数据

  • 定义一个user3对象,包含着用户参数
  • 将这个对象放入数组里面
  • 定义字符串---JSON.stringify()将数组转化成字符串
  • 将字符串写入对应users.json文件中
  • 此时每当请求一次,user3的信息就会被写入库中 1635497359(1).png

1635497759(1).png

小结

  • 读取数据
    • 先读取json转字符串
    • 再JSON调用函数转数组(反序列化)
  • 存入数据
  • 先数组转字符串,(序列化)
  • 再写入字符串

实现几个功能

目标1

  • 实现用户注册功能
    • 用户提交用户名和密码
    • users.json新增一行数据

思路

  • 清空数据库,预留位置 [ ]

1635498252(1).png

  • 注册页写入表单

1635498841(1).png

  • 引入jQuery

1635499361(1).png

  • 阻止注册按钮默认事件
    • 如果不阻止,点击注册按钮会刷新页面

1635499424(1).png

  • 表单提交事件
    • 阻止默认按钮事件
    • 在form表单里面找到属性为name='name的input标签,然后得到它的值( 即.val( )或者.value( ) )
    • 在form表单里面找到密码框输入的内容()
    • 表单层面完成用户名,密码的获取
  • jQuery引入AJAX
    • 请求方式改为POST,因为GET请求只能将数据传到url里面
    • 获取数据的路径为这个注册页
    • 设置数据的文件类型,识出传的是json文件(JSON.strinify)
    • 发送json文件 1635748655(1).png

获取post数据

  • 首先解决路径为/register,返回404问题(上面ajax的url没有html后缀,写错了)
    • 添加判断条件,如果路径为/register 并且是POST请求
    • 响应头内容改写
    • 如果不是(即正常的带后缀路径)
    • 将响应主体放到else部分
  • 获取POST请求得到的数据
    • 定义一个空数组,目的是将数据分段获取(不能确定数据的长度和
    • 请求监听文件上传,获取一小段数据,并将数据放到数组里面
    • 监听请求的结束事件,响应结束

1635839587(1).png

  • 服务器显示一长串编码
    • 使用Buffer,将这个编码改为可识别的字符串(不属于前端内容,不深究),此时得到了可理解的字符串 1635841504(1).png

1635841657(1).png

  • 将注册数据存入数据库内
    • 将字符串变成对象
    • 声明一个新的用户对象,name就是对象的name,apassword就是对象的password(这里的对象是指传进来的)
    • 用户数据组成的数组:将新用户对象放入
    • 将数据写入users.json文件中
    • 补充:考虑到空数组的情况,声明数组的最后一个对象
    • 声明新用户对象的时候,如果不存在,它的id就是1
    • 当注册新的用户的时候,他们的数据就会写入user.json文件里面,有连续的id,完整的用户名和密码 1635842943(1).png

1635843311(1).png

  • 注册成功,跳转到登录页面 -注册页调用ajax部分使用.then,如果成功,提示注册成功并且跳转登录页 1635844075(1).png

目标1 思路总结 重要!!!!!!!!!!!!!

  • 实现用户注册功能
    • 当用户提交用户名和密码
    • users.json里面就新增一行数据
  • 思路
    • 前端写一个form,让用户填写用户名和密码
    • 前端监听submit事件
    • 前端发送POST请求,数据位于请求体
    • 后端接收POST请求
    • 后端获取请求体中的name和password
    • 后端存储数据

目标2

  • 用户登录功能
  • 主页:补充注册成功跳转登录页
    • 提示部分,拼接 你好+用户名
    • 然后链接,点击跳转到登录页

1635859645(1).png

登录页

  • 静态网页
    • 格式,内容与注册页同理
    • 类名、id调整即可
    • then(),如果成功,提示登录成功,跳转到相应的页面

1635859989(1).png

  • 后台服务器,实现如果输入的用户名、密码有误,提示错误
    • 设置后台服务器路由选择
    • 如果条件满足,逻辑参照注册后台
    • 此时响应结束逻辑有所改动
      • 去除之前新用户id判断,应为只是判断输入内容是否在user.json文件里面
      • 声明这个用户变量((输入的) 在userArray(现有的)数据里面寻找,条件是用户名,密码相等
      • 如果返回值是undefined,状态码400,响应提示用户名,密码不匹配
      • 如果成功,状态码200,响应结束 1635860077(1).png
  • 直接返回错误码
    • 原先的不匹配提示直接变成json,返回的响应头设置成json
    • 输入不存在的用户名和密码,返回json文件,显示错误码(这里的错误码自己定义) 1635902956(1).png

1635903036(1).png

  • 登录成功跳转到首页
    • sign_in的主页location改为home.html

    • 后台,路径设置,如果路径是home.html,响应返回home字符串

144629f59d9afe4a39bbfece33f899e.png 1635903692(1).png

目标3 显示用户已登录

  • 如何识别跳转的主页是登录过的还是直接输入url的(目前为止,两种方式原理是一样的)

使用cookie

  • 定义
    • cookie是服务器给浏览器的字符串
    • 浏览器必须保存这个字符串(cookie),除非删除
    • 之后发起相同二级域名请求,浏览器必须附上cookie

应用

  • 在响应头部的cookie里面添加“logined=1”字符串(登录后台)
  • 此时登录成功之后,响应头部里面出现了cookie内容 1635908495(1).png

1635908551(1).png

  • home主页读取cookie

    • 声明cookie,为请求头部里的cookie(语法查文档)
    • 判断,如果有cookie,读取home.html内容,转字符串,这个字符串叫string
    • string字符串里面把home.html的占位符替换成“已登录”
    • 反之,思路与存在cookie一样,显示未登录
  • 效果:如果常规登录,可以看到主页内容,如果启用隐私模式,或者手动删除cookie,跳转页面显示未登录 1635931418(1).png

  • set-cookie的详细用法:developer.mozilla.org/zh-CN/docs/…

  • 设置cookie

    • 默认状态下,前端是可以访问,修改cookie
    • 添加HttpOnly,保证前端不可读取并修改cookie(防止用户修改cookie)

1635999768(1).png

home.html如何识别用户id?(用户是谁)

  • 将cookie内容修改
    • 此时home主页就识别出了用户的id 1636003270(1).png

1636003317(1).png

  • 如何得到cookie?
    • 首先打印出cookie,是字符串
    • 然后字符串用;分开
    • 输出得到数组 1636003672(1).png

1636003707(1).png

1636003830(1).png

1636003857(1).png

  • 如何识别cookie里面的id与数据库里面的id相吻合?即判断当主页请求发来,如何判断是已经登录还是未登录,防止未登录直接访问到登录成功才能看到的内容
    1. 得到cookie里面的id (声明叫做userId)
      • cookie字符串分割,因为原字符串以;分割,所以split参数为;,就是把;去掉,然后分割几个部分转化成数组,类似于['项目1','项目2',...]
      • 然后数组调用filter()函数筛选,s作为被筛选变量,调用indexof,找到user_id=xxx这个字符串,然后从=符号分割,拿到id数值,这个数值是字符串
      • 此步骤可以逐步使用console.log调试,判断不同阶段的结果,数据类型然后调用合适的API
      • 调用try catch函数
    2. 判断cookie的id是否与数据库里面的相吻合,这一步就是判断输入路径的时候,判断是否是登录过的
    • 判断是否得到了cookie的id数值(字符串)userId作为判断条件
    • 如果存在,首先读取数据库信息
    • 主页读取文件,显示设置照旧
    • 声明一个用户user,这个user指的是数据库里面的,在数据库里面找到这个user,寻找条件是user的id转化成字符串与coolie里面的id相同
    • 如果数据库里面存在这样的用户,即两个id吻合,主页显示已经登录
    • 反之,主页显示未登录 1636007488(1).png

目标4: 续添加一个小功能,登录成功,主页显示用户名

  • 主页添加占位符
  • 如果成功,将占位符变成用户名
  • 如果失败,占位符替换成空字符串
  • 注意逻辑,失败了根源上是没有获得cookie,所以执行语句在没有cookie条件里面执行 1636010091(1).png

1636010170(1).png

image.png

image.png

存在呢BUG,目前为止,用户是可以篡改

-登录完成之后,将cookie里面的id更改

  • 再次刷新,以另外一个id的身份登录

23f3d985b59b90fd6f196b575af4699.png

image.png

目标5,防止用户篡改user_id

思路一:加密

  • 将user_id加密发送给前端,后端读取user_id时解密,但是有安全漏洞
  • 漏洞:解密后的内容可以无限期使用
  • 解决方法:JWT

思路二:把信息隐藏在服务器里

  • 把用户信息放在服务器的x里,再给信息一个随机的id
  • 把随机id发给浏览器
  • 后端下次读取id时,通过x[id]获取用户信息
  • 因为id很长而且随机,所以无法篡改id
  • X是文件,不能用内存,因为断电内存就清空
  • 这个x又被叫做session(会话)

代码实现

  • 创建session文件
    • 首先手写session内容,user_id作为一个对象存在session里面(仅仅是样式)

    • 此时只能得到这个随机数,但是对应的用户id对象是无法查看的 1636012188(1).png

1636012193(1).png

  • 之传入session的id(随机的)
  • 在登录路由设置
  • 声明随机数 random
  • 声明session,读取session文件然后转为对象
  • session里面的random属性值为user_id:用户的id
  • 写入session文件,但是浏览器无法查看具体内容
  • 响应返回session的随机id
  • 此时登录,响应头里的cookie只能查看session的id随机数,具体的用户id无法查看

1636012970(1).png

1636013238(1).png