手把手用koa实现一个登录功能

205 阅读3分钟

1. koa是什么

Koa官网的话来说就是,Koa是基于Node.js平台的下一代web开发框架。

2. koa的功能

作为一个nodejs服务器给web提供服务。

3. koa的使用

1. 安装Koa

npm init -y
npm i koa

注意:使用Koa时node版本需大于 v7.6.0,不然无法支持Es6的async await异步方法

2. 使用

新建一个文件src/index.js

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

app.listen(3000, () => {
    console.log('控制台会打印出`server is listen in 3000~`')
})

  • Koa是一个,使用的时候需要创建一个实例,然后通过调用实例上的listen方法监听一个端口。
  • 然后使用node src/index.js启动服务器,控制台会打印出server is listen in 3000~
  • 可通过http://localhost:3000/来访问服务器,此时页面上会显示Not Found,因为此时我们没做任何的处理。

3. koa的核心概念

3.1. Context(上下文)

Koa将nodejs服务器原生的request和response封装在了Context上下文对象中。

app.use(async ctx => {
    ctx; // koa的上下文对象
    ctx.request; // koa封装的请求对象
    ctx.response; // koa封装的响应对象
})

3.2. 中间件

app.use(async (ctx, next) => {
    // 返回 hello world 作为页面的显示内容
    ctx.body = 'Hello World';
})

中间件顾名思义就是一个中间的处理单元,其中app是Koa的一个实例,先调用app.use注册一个Koa的中间件,然后在回调函数有两个参数,通过ctx可以拿到请求的上下文信息,处理完后调用next接着往下执行,中间件可以使用多个,执行顺序按注册顺序的先后执行。

多个中间件的使用:

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

app.use(async (ctx, next) => {
    console.log('中间件1 开始处理')
    await next()
    console.log('中间件1 处理结束')
})
app.use(async (ctx, next) => {
    console.log('中间件2 开始处理')
    await next()
    console.log('中间件2 处理结束')
})
app.use(async (ctx, next) => {
    console.log('中间件3 开始处理')
    await next()
    console.log('中间件3 处理结束')
})
app.listen(3000, () => {
    console.log('server is listen in 3000~')
})

打印结果如下:

image.png

这个就是著名的洋葱模型,一层一层往里执行,先执行的后结束。

4. 使用koa-generator快速搭建项目

// 先全局安装 koa-generator
npm i koa-generator -g
// 使用 koa2 命令 + 项目名来创建一个项目
koa2 koa-example

5. 实际应用

使用koa简单实现一个登录功能: 客户端代码:

<!-- 创建 login.html 文件 -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login Form</title>
</head>

<body>
    <h1>Login Form</h1>
    <form id="login-form">
        <div>
            <label for="username">Username:</label>
            <input type="text" id="username" name="username" required>
        </div>
        <div>
            <label for="password">Password:</label>
            <input type="password" id="password" name="password" required>
        </div>
        <div>
            <button type="submit">Login</button>
        </div>
    </form>
    <div id="message"></div>

    <script>
        const loginForm = document.querySelector('#login-form');
        const usernameInput = document.querySelector('#username');
        const passwordInput = document.querySelector('#password');
        const messageElement = document.querySelector('#message');

        // 监听提交事件
        loginForm.addEventListener('submit', async (event) => {
            event.preventDefault();

            // 获取用户名和密码
            const username = usernameInput.value;
            const password = passwordInput.value;

            // 发送登录请求
            const response = await fetch('http://localhost:3000/login', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                    username,
                    password
                })
            });

            // 处理响应
            if (response.ok) {
                const user = await response.json();
                messageElement.textContent = `Welcome, ${user.username}!`;
            } else {
                const error = await response.json();
                messageElement.textContent = error.message;
            }
        });
    </script>
</body>

</html>

界面如下:

image.png 服务端代码如下:

// server.js
const Koa = require('koa')
const Router = require('koa-router')
const bodyParser = require('koa-bodyparser')

const app = new Koa()
const router = new Router()

// 添加中间件
app.use(async (ctx, next) => {
    ctx.set('Access-Control-Allow-Origin', '*');
    ctx.set('Access-Control-Allow-Headers', '*');
    await next();
});
app.use(bodyParser());
app.use(router.routes());
app.use(router.allowedMethods());
// 假设这里使用了一个模拟数据库的 users 对象来存储用户信息
const users = {
    'user1': {
      username: 'user1',
      password: 'password1'
    },
    'user2': {
      username: 'user2',
      password: 'password2'
    }
};

router.post('/login', (ctx) => {
    const { username, password } = ctx.request.body
    const user = users[username]
    if (!user) {
        ctx.status = 401
        ctx.body = { message: 'User is Not Found' }
        return;
    }
    if (user.password !== password) {
        ctx.status = 401
        ctx.body = { message: 'Error Password' }
        return;
    }
    ctx.body = { username: user.username }
})

// 启动服务
app.listen(3000, () => {
    console.log('Server running on port 3000');
});

6. 测试应用

我们需要测试三个case:

  1. 用户名和密码都错误
  2. 用户名正确,密码错误
  3. 用户名和密码都正确

先通过在命令行输入 node server.js将服务启动起来:

image.png

case1: 用户名和密码都错误

在页面上输入一个错误的用户名和密码,比如我们输入用户名123,密码456,页面会提示 User is Not Fount

image.png

case2: 用户名正确,密码错误

我们输入一个正确的用户名和错误密码,比如用户名user1,密码password,页面会提示Error Password

image.png

case3: 用户名和密码都正确

我们输入一个正确的用户名和密码,比如用户名user1,密码password1,页面会提示Welcome, user1!,证明此时已经登录成功了。

image.png

当然,这个主要是一个简单的登录模拟,作为学习使用,实际登录场景比这个复杂得多,还要结合数据库sessioncookie以及token等很多东西来实现。