• Cookie、Session、Token(没懂的话再看一遍)


    Cooike、Session、Token

    接触了这么久的Web,有必要好好总结下这一块了

    什么是无状态HTTP协议

    在网络没有当今这么发达的时代,Web基本就是用于文档的浏览,作为服务器而言也就是根据相应,加载对应的相应就是了,也就是说不需要记录你干了什么,你有什么,我只知道你请求了,我返回就是了,咱们到此结束就是了。每次请求都会是一次全新的请求。当然没有什么状态的存储一说。
    所谓无状态HTTP协议,就是没有保存状态罢了。

    会话机制出现

    在这么一种没有存储的情况之下,随着网络技术的发展,Web也变得越来越强大,这时候就出现了会话机制。比如说,登录的时候,进行页面的跳转的时候一般都会发起新的请求,但是逻辑是我希望你登录之后才能看见,这时候,该不会让我一直去登录吧。会话机制就是这么的记住了你的状态,然后实现请求变化的时候也保存了状态。

    主流的三种会话就是 Cooike、Session、Token

    什么是 Cookie

    Cookie存在于客户端 ,Cooike是一种存在于客户端的会话机制,由服务端发送到用户的浏览器并保存到本地的一小块数据,在浏览器下一次请求服务端的时候会带上发送给服务端
    Cooike是不可以跨域的,每一个Cookie都会绑定一个单一的域名,无法再别的域名下使用,一级域名和二级域名是共享的

    查看Cookie,在浏览器的Application中有一个Cooikes的模块存储了该网站的所有的Cooike,当然也可以通过代码document.cookie来获取Cookie的值。
    在这里插入图片描述
    如图所示就是该网站的所有的Cookie,包含了Cookie的name、Value,Domain(实现跨域)、Expires/maxAge(失效时间和最大的保存时间)、Size(大小,最大为4k),HttpOnly(阻止js脚本获取Cooike信息)、Secure(cookie只能通过https发送,不能通过http发送)

    可以看到,Cooike就是这样一个十分具体形象的东西

    客户端设置

    document.cookie = "name=Indomite;age=12"
    

    客户端可以设置Cookie的选项,但是不能设置 httpOnly ,设置好Cookie之后,Cookie被自动添加到request header中,服务器收到Cooike

    服务端的设置
    在response的header中有一项叫做set-cooike,专门用于服务端设置Cooike

    • 一个set-cooike只能设置一个cooike,使用多个的时候需要多次使用set-cooike
    • 服务端可以设置cookie的所有选项: expires, domain, path, secure, HttpOnly

    在这里插入图片描述

    什么是Session

    服务端的Session,Session就是存在于服务端的会话,记录客户端与服务端的童话
    Session基于Cookie实现,Session存在于服务端,但是需要和客户端进行练习的时候,就必须要通过Cookie了,Session_id会存储在Cookie中
    在这里插入图片描述

    Session与Cookie的会话流程

    1. 用户在第一次请求服务端的时候,服务端根据用户提交的相关消息创建对应的Session
    2. 服务端接到请求之后响应,返回Session的唯一标识Session_id给客户端,也就是存储在Cookie的Session信息
    3. 客户端接收到服务端发来的Session_id之后,将信息存入Cooike,同时记录好对应的Session_id属于那个域名
    4. 第二次客户端访问服务端的时候,请求会判断时候存在Cookie信息,存在的话直接发给服务端,服务端从Cookie获取Session_id,根据Session_id查找对应的Session信息,没有的话那状态失败,找到之后就可以进行之后的操作了

    上述可见,Session_id就是连接Session和Cookie之间的桥梁
    Session对应着一台服务器,当存在分布式的时候,服务器之间的Session共享就变得不那么简单了

    什么是Token

    Token令牌,Token就是访问资源接口(API)时所需要的凭证,在服务端将用户的信息通过Base64编码过后传给客户端,每次请求的时候都带上这一信息,服务端拿到之后解密就知道用户是谁了
    Token组成,uid(用户唯一的身份标识)、time(当前的时间戳)、sign(签名、Token前几位以hash算法压缩成的一定长度的字符串)

    特点:服务端无状态化、可扩展性强
    支持移动端设备
    安全、支持跨程序调用
    在这里插入图片描述

    1. 客户端使用用户名跟密码请求登录
    2. 服务端收到请求,去验证用户名与密码
    3. 验证成功后,服务端会签发一个 token 并把这个 token 发送给客户端
    4. 客户端收到 token 以后,会把它存储起来,比如放在 cookie 里或者 localStorage 里
    5. 客户端每次向服务端请求资源的时候需要带着服务端签发的 token
    6. 服务端收到请求,然后去验证客户端请求里面带着的 token ,如果验证成功,就向客户端返回请求的数据

    什么是JWT

    JSON Web Token,是目前最流行的跨域认证的解决方案
    关于JWT的具体参考可以查看阮一峰老师的
    在这里插入图片描述

    JWT认证流程

    1. 用户输入用户名、密码登录,服务端认证成功之后,或返回客户端一个JWT
    2. 客户端将Token保存到本地(localStorage !、Cookie)
    3. 当用户项访问一个受保护的资源的时候,比如说多权限使用,需要请求Authorization使用Bearer添加JWT
    Authorization: Bearer <token>
    

    下面贴一段源码吧

    //index.js
    const Koa = require('koa')
    const Router = require('koa-router')
    const bodyParser = require('koa-bodyparser')
    const {
        sign
    } = require('jsonwebtoken') //签发token
    const {
        secret
    } = require('./config')
    const jwt = require('koa-jwt')({
        secret
    }) //jwt加密解密码中间件
    const admin = require('./middleware/admin')()
    
    const app = new Koa()
    app.use(bodyParser())
    const router = new Router()
    router.post('/api/login', async (ctx, next) => {
        // ctx.request.params URL请求参数
        // ctx.request.query 请求参数
        // ctx.request.header 头参数
        // ctx.request.body json对象参数
    
        const user = ctx.request.body;
        if (user && user.username) {
            let {
                username
            } = user
            const token = sign({
                username
            }, secret, {
                expiresIn: 6000
            })
            ctx.body = {
                message: "得到了Token",
                code: 1,
                token
            }
        } else {
            ctx.body = {
                message: "参数错误",
                code: -1
            }
        }
    })
    
    router.get('/api/userInfo', jwt, async ctx => {
        ctx.body = {
            message: 'Token 鉴权',
            username: ctx.state.user.username
        }
    })
    
    router.get('/api/adminInfo', jwt, admin, async ctx => {
        ctx.body = {
            message: 'Hello Admin',
            username: ctx.state.user.username
        }
    })
    
    app.use(router.routes()).use(router.allowedMethods())
    
    app.listen(3000, () => {
        console.log('app listen 3000');
    })
    
    //config.js
    exports.secret = 'dehiuhsdaf'
    
    //admin.js  中间件
    module.exports = () => {
        return async (ctx, next) => {
            if (ctx.state.user.username === 'admin') {
                next()
            } else {
                ctx.body = {
                    code: -1,
                    message: '用户没有权限'
                }
            }
        }
    }
    
  • 相关阅读:
    Beta 阶段计划
    alpha阶段总结
    冲刺第十天 12.6 THU
    冲刺第九天 12.5 WED
    冲刺第八天 12.4 TUE
    冲刺第七天 12.3 MON
    冲刺第六天 11.30 FRI
    正弦交流电有效值系数sqrt(2)的推导
    关于STM32官方FOC库函数扇区分析中’131072’系数的解释
    闭环系统零、极点位置对时间响应性能指标的影响
  • 原文地址:https://www.cnblogs.com/Indomite/p/14195222.html
Copyright © 2020-2023  润新知