登录实现方案与实践

1、cookie是什么
◆存储在浏览器的一段字符串,最大5kb
◆每个域都可有一个cookie , 跨域不共享
◆格式如k1=v1; k2=v2; k3=v3; ( 可结构化)

2、cookie会随http请求传递给服务端
◆每次 http请求, cookie都会随着传递到服务端
◆服务端可修改 cookie再返回给前端
◆默认, 跨域不可传递cookie
3、 服务端操作 cookie

// 服务端操作 cookie

const http = require('http')

const server = http.createServer((req, res) => {

    // 设置 cookie
    res.setHeader('Set-Cookie', 'c=200')

    // 获取 cookie
    const cookieStr = req.headers.cookie
    console.log('cookie is ', cookieStr)

    // // 结构化 cookie(概念很重要)
    // cookieStr: 'a=100; b=200' --> { a: '100', b: '200' }
    const cookieObj = {}
    cookieStr.split(';').forEach(cookieItemStr => {
        const arr = cookieItemStr.trim().split('=')
        const key = arr[0] // 'a'
        const val = arr[1] // '100'
        cookieObj[key] = val
    })
    console.log('cookie obj is', cookieObj)

    res.end('cookie test')
})

server.listen(3000)
console.log('server listening on 3000 port')

4、Koa2设置或者获取cookie

// Koa2 操作 cookie

const Koa = require('koa')
const app = new Koa()

app.use(async (ctx) => {

    // 设置 cookie
    ctx.cookies.set('a', '500')

    // 获取 cookie
    console.log('cookie is', ctx.cookies.get('a'))

    ctx.body = 'cookie test by Koa2'
    // // 结构化,koa2 已经做好了

})

app.listen(3000)

5、cookie如何用于登录校验
◆请求登录接口,成功则设置cookie,如user=zhangsan
◆前端再请求其他接口,就会带着上述cookie【同域下】
◆服务端判断cookie有无 user=zhangsan,即可验证
6、cookie和session
1、cookie不能暴露用户名
◆上一节, cookie中有 user = zhangsan
◆cookie 存放用户信息明文,非常危险
◆解决方案:cookie存一个用户标识,如userld=123

2、session是什么
◆cookie 存储用户标识,如userId
◆用户信息则存储到session中
◆session 即用户信息的存储,和cookie有对应关系
——————————————————————
// 模拟 session 它是一个全局对象,它的key就是用户标识,它的value就是存储的用户信息
session简单的小例子:

// Koa2 操作 cookie

const Koa = require('koa')
const app = new Koa()

// 模拟 session
const SESSION_DATA = {
    '123': {
        user: 'zhangsan',
        age: 20
    },
    '456': {
        user: 'lisi'
    },
    '789': {
        user: 'shuangyue'
    }
}

app.use(async (ctx) => {
    // 加入用户登录成功,服务端设置 cookie (userId ,不能泄露用户信息)
    ctx.cookies.set('userId', '123')

    // 其他接口,获取 cookie
    const userId = ctx.cookies.get('userId')
    const userInfo = SESSION_DATA[userId]
    userInfo.user // 用户名

    ctx.body = 'cookie test by Koa2'
})

app.listen(3000)

7、Koa2实现登录
1、安装插件

koa-generic-session --save

2、在app.js文件中引入和配置

引入
const session = require('koa-generic-session')
配置
app.keys = ['wertwe^&&*UUI123123'] // 秘钥
// 自定配置了 cookie 和 session
app.use(session({
  // 配置 cookie
  cookie: {
    path: '/', // cookie 在根目录下有效
    httpOnly: true, // cookie 只允许服务端来操作
    maxAge: 24 * 60 * 60 * 1000 // cookie 的过期时间
  }
}))

定义路由:router/index.js

router.get('/session-test', async (ctx, next) => {
  // ctx.session
  if (ctx.session.viewcount == null) {
    // 用户尚未访问
    ctx.session.viewcount = 0
  }
  // 用户已经访问过了
  ctx.session.viewcount++ // 递增

  // 返回
  ctx.body = {
    title: 'session-test',
    viewcount: ctx.session.viewcount
  }
})

8、模拟登录和验证

// 模拟登录
router.get('/login-mock', async (ctx, next) => {
  let str = ''
  const query = ctx.query // url 参数,querystring
  if (query.username) {
    // 模拟登录成功
    ctx.session.userInfo = {
      username: query.username
    }
    str = 'login ok'
  } else {
    // 模拟登录失败,不用处理 session
    str = 'login failed'
  }

  ctx.body = str
})

// 模拟登录验证
router.get('/login-check-mock', async (ctx, next) => {
  ctx.body = ctx.session.userInfo || {}
})

9、完善登录功能,连接数据库

// 登录(对接数据库的)
// 为了方便同域的测试,暂用 get 请求
router.get('/login', async (ctx, next) => {
  const { username, password } = ctx.query // get 请求
  // const { username, password } = ctx.request.body // post 请求

  // 查询数据库
  const user = await User.findOne({
    username,
    password
  })

  if (user != null) {
    // 登录成功,设置 session
    ctx.session.userInfo = user // 所有的用户信息
    // 返回
    ctx.body = {
      errno: 0,
      data: user
    }
    return
  }
  // 登录失败,不用操作 session
  ctx.body = {
    errno: -1,
    message: '用户名或密码错误'
  }
})

10、登录验证的中间件

// 登录验证的中间件

async function loginCheck (ctx, next) {
    const userInfo = ctx.session.userInfo
    if (userInfo && userInfo.username) {
        // 登录验证成功
        await next()
        return
    }
    // 登录失败
    ctx.body = {
        errno: -1,
        message: '请登录'
    }
}

module.exports = loginCheck

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容