>  기사  >  웹 프론트엔드  >  노드 실습: 로그인 확인을 위해 Cookie&Session 사용

노드 실습: 로그인 확인을 위해 Cookie&Session 사용

青灯夜游
青灯夜游앞으로
2022-12-01 20:16:252722검색

노드 실습: 로그인 확인을 위해 Cookie&Session 사용

원래 주소: https://ailjx.blog.csdn.net/article/details/127909213

저자: Undersea BBQ Restaurant ai

이전 섹션에서 우리는 간단한 프로젝트 구조를 생성하고 최적화했습니다. 사용자 관리 시스템의 쿠키 세션 로그인 확인의 작동 원리도 설명합니다. 다음으로 이 섹션에서는 실제로 쿠키를 사용하여 기능을 보완해 보겠습니다. 본 시스템의 로그인 인증 기능을 구현하기 위한 세션입니다. [추천 관련 튜토리얼: nodejs 동영상 튜토리얼]Cookie-Session登录验证 的工作原理做了讲解,接下来我们将继续补充这个系统的功能,这一节我们将实战运用Cookie-Session来实现这个系统的登录验证功能。【相关教程推荐:nodejs视频教程

什么?你还不了解sessioncookie!快去看看上篇文章吧:详解 Cookie-Session登录验证 的工作原理

1️⃣ 定义页面路由

vies目录下新建login.ejs

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h1>登录页面</h1>
    <div>用户名:<input type="text" id="username"></div>
    <div>密码:<input type="password" id="password"></div>
    <div><button id="login">登录</button></div>
    <script>
        const uname = document.getElementById("username");
        const pwd = document.getElementById("password");
        const login = document.getElementById("login");
        login.onclick = () => {
            fetch(&#39;/api/login&#39;, {
                method: &#39;POST&#39;,
                body: JSON.stringify({
                    username: uname.value,
                    password: pwd.value
                }),
                headers: {
                    "Content-Type": "application/json"
                }
            }).then(res => res.json()).then(res => {
                // console.log(res);
                if (res.ok) {
                    location.href = "/"
                } else {
                    alert("用户名密码不匹配!")
                }
            })
        }
    </script>
</body>

</html>

注意:页面中请求的接口是POST /api/login请求

routes目录下新建login.js,该文件定义login页面的页面路由:

var express = require("express");
var router = express.Router();

/* GET login page. */
router.get("/", function (req, res, next) {
    res.render("login");
});

module.exports = router;

app.js中挂载页面路由:

// 引入
var loginRouter = require("./routes/login");
// 挂载
app.use("/login", loginRouter);

启动项目,访问http://localhost:3000/login正常显示:

노드 실습: 로그인 확인을 위해 Cookie&Session 사용

2️⃣ 定义API接口

services/UserService.js中定义接口的模型(M层):

const UserService = {
	// .......
    // 登录查询
    login: (username, password) => {
    	// 向数据库查询该用户
        return UserModel.findOne({ username, password });
    },
};

controllers/UserController.js中定义接口的控制层(C层):

const UserController = {
 	// ......
 	// 登录验证
    login: async (req, res, next) => {
        try {
            const { username, password } = req.body;
            const data = await UserService.login(username, password);
            // console.log(data);
            if (data) {
                res.send({ ok: 1, msg: "登录成功!", data });
            } else {
                res.send({ ok: 0, msg: "用户不存在,登录失败!" });
            }
        } catch (error) {
            console.log(error);
        }
    },
};

routes/users.js中定义Api路由:

// 登录校验
router.post("/login", UserController.login);

至此登录页面就搭建好了:

노드 실습: 로그인 확인을 위해 Cookie&Session 사용

3️⃣ 配置session

在上一节Cookie-Session登录验证工作原理的介绍中我们知道:

노드 실습: 로그인 확인을 위해 Cookie&Session 사용

노드 실습: 로그인 확인을 위해 Cookie&Session 사용

这个过程显然是比较复杂的,在express中有一个express-session模块可以大大降低我们的工作量,让我们站在巨人的肩膀上开发!

下载express-session

npm i express-session

app.js中进行配置:

// 引入express-session
var session = require("express-session");

// 配置session:需要放在在路由配置的前面
app.use(
    session({
        name: "AilixUserSystem", // cookie名字
        secret: "iahsiuhaishia666sasas", // 密钥:服务器生成的session的签名
        cookie: {
            maxAge: 1000 * 60 * 60, // 过期时间:一个小时过期
            secure: false, // 为true时表示只有https协议才能访问cookie
        },
        resave: true, // 重新设置session后会重新计算过期时间
        rolling: true, // 为true时表示:在超时前刷新时cookie会重新计时;为false表示:在超时前无论刷新多少次,都是按照第一次刷新开始计时
        saveUninitialized: true, // 为true时表示一开始访问网站就生成cookie,不过生成的这个cookie是无效的,相当于是没有激活的信用卡
    })
);

配置好后,就会发现浏览器中有一个名为AilixUserSystemcookie

노드 실습: 로그인 확인을 위해 Cookie&Session 사용

这是因为express-session会自动解析cookie和向前端设置cookie,相当于是노드 실습: 로그인 확인을 위해 Cookie&Session 사용中的3、6(前半部分:通过SessionId查询到Session ,我们不再需要手动对cookie进行操作。

4️⃣ 权限验证

在登录成功时设置session

// controllers/UserController.js
// ....
// 登录校验
login: async (req, res, next) => {
   try {
       const { username, password } = req.body;
       const data = await UserService.login(username, password);
       // console.log(data);
       if (data) {
           // 设置session:向session对象内添加一个user字段表示当前登录用户
           req.session.user = data; // 默认存在内存中,服务器一重启就没了
           res.send({ ok: 1, msg: "登录成功!", data });
       } else {
           res.send({ ok: 0, msg: "用户不存在,登录失败!" });
       }
   } catch (error) {
       console.log(error);
   }
},

我们向req.session中添加了一个user字段,来保存用户登录的信息,这一步相当于是 노드 실습: 로그인 확인을 위해 Cookie&Session 사용中的1(SessionId会由express-session模块自动生成)、2

req.session是一个session对象,需要注意的是这个对象虽然存在于req中,但其实不同的人访问系统时他们的req.session是不同的,因为 req.session是根据我们设置的cookie(由express-session模块自动生成的AilixUserSystem )生成的,每一个人访问系统所生成的cookie是独一无二的,所以他们的req.session也是独一无二的。

在收到请求时校验session,在app.js添加以下代码:

// 设置中间件:session过期校验
app.use((req, res, next) => {
    // 排除login相关的路由和接口
    // 这个项目中有两个,一个是/login的页面路由,一个是/api/login的post api路由,这两个路由不能被拦截
    if (req.url.includes("login")) {
        next();
        return;
    }
    if (req.session.user) {
        // session对象内存在user,代表已登录,则放行
        // 重新设置一下session,从而使session的过期时间重新计算(在session配置中配置了: resave: true)
        // 假如设置的过期时间为1小时,则当我12点调用接口时,session会在1点过期,当我12点半再次调用接口时,session会变成在1点半才会过期
        // 如果不重新计算session的过期时间,session则会固定的1小时过期一次,无论这期间你是否进行调用接口等操作
        // 重新计算session的过期时间的目的就是为了防止用户正在操作时session过期导致操作中断
        req.session.myData = Date.now();
        // 放行
        next();
    } else {
        // session对象内不存在user,代表未登录
        // 如果当前路由是页面路由,,则重定向到登录页
        // 如果当前理由是api接口路由,则返回错误码(因为针对ajax请求的前后端分离的应用请求,后端的重定向不会起作用,需要返回错误码通知前端,让前端自己进行重定向)
        req.url.includes("api")
            ? res.status(401).send({ msg: "登录过期!", code: 401 })
            : res.redirect("/login");
    }
});

注意:这段代码需要在路由配置的前面。

这段代码中我们通过req.session.myData = Date.now();来修改session对象,从而触发session过期时间的更新(sessionmyData这个属性以及它的值 Date.now()只是我们修改session对象的工具,其本身是没有任何意义的),你也可以使用其它方法,只要能将req.session

뭐? 아직도 세션, 쿠키를 이해하지 못하시네요! 이전 기사를 읽어보세요. 쿠키 세션 로그인 확인의 작동 원리에 대한 자세한 설명🎜

1️⃣ 페이지 라우팅 정의

🎜 vies 디렉터리에 새 login.ejs를 만듭니다. 🎜
<button>退出登录</button>
🎜 🎜참고: 페이지에서 요청된 인터페이스는 POST /api/login 요청입니다. 🎜🎜🎜경로에서 새 login.js를 생성하세요. > 디렉토리 이 파일 login 페이지의 페이지 경로를 정의합니다: 🎜
const exit = document.getElementById('exit')

// 退出登录
exit.onclick = () => {
  fetch("/api/logout").then(res => res.json()).then(res => {
    if (res.ok) {
      location.href = "/login"
    }
  })
}
🎜 app.js에서 페이지 경로를 마운트합니다: 🎜
const UserController = {
 	// ......
    // 退出登录
    logout: async (req, res, next) => {
        // destroy方法用来清除cookie,当清除成功后会执行接收的参数(一个后调函数)
        req.session.destroy(() => {
            res.send({ ok: 1, msg: "退出登录成功!" });
        });
    },
};
🎜 프로젝트를 시작하고 http://localhost: 3000/login일반 표시: 🎜🎜여기에 그림 삽입 설명🎜

2️⃣ API 인터페이스 정의

🎜services/UserService. js 인터페이스 모델 정의(M 레이어): 🎜
// 退出登录
router.get("/logout", UserController.logout);
🎜 controllers/에서 인터페이스의 제어 레이어(<strong>C 레이어</strong>)를 정의합니다. UserController.js: 🎜
npm i connect-mongo
🎜 routes/users.js에서 Api 경로를 정의하세요. 🎜
// 引入connect-mongo
var MongoStore = require("connect-mongo");

// 配置session
app.use(
    session({
        name: "AilixUserSystem", // cookie名字
        secret: "iahsiuhaishia666sasas", // 密钥:服务器生成的session的签名
        cookie: {
            maxAge: 1000 * 60 * 60, // 过期时间:一个小时过期
            secure: false, // 为true时表示只有https协议才能访问cookie
        },
        resave: true, // 重新设置session后会重新计算过期时间
        rolling: true, // 为true时表示:在超时前刷新时cookie会重新计时;为false表示:在超时前无论刷新多少次,都是按照第一次刷新开始计时
        saveUninitialized: true, // 为true时表示一开始访问网站就生成cookie,不过生成的这个cookie是无效的,相当于是没有激活的信用卡
        store: MongoStore.create({
            mongoUrl: "mongodb://127.0.0.1:27017/usersystem_session", // 表示新建一个usersystem_session数据库用来存放session
            ttl: 1000 * 60 * 60, // 过期时间
        }), // 存放数据库的配置
    })
);
🎜이제 로그인 페이지가 설정되었습니다: 🎜🎜🎜

3️⃣ 세션 구성

🎜이전 섹션의 쿠키 세션 로그인 확인 작동 원리 소개에서 우리는 다음을 알고 있습니다. 🎜🎜🎜
사진 1
🎜이것 프로세스는 확실히 더 복잡합니다. express에 express-session 모듈이 있어 작업량을 크게 줄이고 개발에서 거대 기업의 어깨에 설 수 있게 해줍니다! 🎜🎜express-session 다운로드: 🎜rrreee🎜 app.js에서 구성: 🎜rrreee🎜구성 후에는 cookie라는 브라우저를 찾을 수 있습니다. > 코드>AilixUserSystem: 🎜🎜여기에 이미지 설명 삽입 🎜🎜express-session이 자동으로 쿠키를 구문 분석하고 쿠키를 프런트 엔드로 설정하기 때문입니다. 3과 동일 및 그림 1의 6(전반: SessionId를 통해 Session 쿼리), 더 이상 쿠키를 수동으로 확인할 필요가 없습니다. 작동하다. 🎜

4️⃣ 권한 확인

🎜로그인 성공 시 세션 설정: 🎜rrreee🎜We 사용자 로그인 정보를 저장하기 위해 user 필드가 req.session에 추가되었습니다. 이 단계는 그림 1의 1과 같습니다(SessionId는 express-session 모듈이 자동으로 생성됨), 2. 🎜🎜🎜req.sessionsession 개체입니다. 이 개체는 req에 존재하지만 실제로는 다른 개체에서 액세스됩니다. req.session은 우리가 설정한 쿠키를 기반으로 하기 때문에 시스템을 실행할 때 req.session이 다릅니다. express-session 모듈은 자동으로 AilixUserSystem )을 생성합니다. 시스템에 액세스하는 각 사람이 생성하는 쿠키는 고유합니다. req.session도 고유합니다. 🎜🎜🎜요청을 받으면 session을 확인하고 app.js에 다음 코드를 추가하세요. 🎜rrreee🎜🎜참고: 이 코드는 라우팅 구성 앞에 있어야 합니다. . 🎜🎜🎜이 코드에서는 req.session.myData = Date.now();를 통해 session 객체를 수정하여 session을 트리거합니다. 만료 시간 업데이트(sessionmyData 및 해당 값 Date.now())는 session를 수정하는 것입니다. >개체 도구, 자체는 의미가 없습니다). req.session을 수정할 수 있는 한 다른 방법을 사용할 수도 있습니다. 🎜

因为我们这个项目是后端渲染模板的项目,并不是前后端分离的项目,所以在配置中间件进行session过期校验拦截路由时需要区分Api路由页面路由

后端在拦截API路由后,向前端返回错误和状态码:

노드 실습: 로그인 확인을 위해 Cookie&Session 사용

这个时候需要让前端自己对返回结果进行判断从而进行下一步的操作(如回到登录页或显示弹窗提示),该系统中前端是使用JavaScript内置的fetch来进行请求发送的,通过它来对每一个请求结果进行判断比较麻烦,大家可以自行改用axios,在axios的响应拦截器中对返回结果做统一的判断。

5️⃣ 退出登录

向首页(index.ejs)添加一个退出登录的按钮:

<button>退出登录</button>

为按钮添加点击事件:

const exit = document.getElementById('exit')

// 退出登录
exit.onclick = () => {
  fetch("/api/logout").then(res => res.json()).then(res => {
    if (res.ok) {
      location.href = "/login"
    }
  })
}

这里调用了GET /api/logout接口,现在定义一下这个接口,在controllers/UserController.js中定义接口的控制层(C层):

const UserController = {
 	// ......
    // 退出登录
    logout: async (req, res, next) => {
        // destroy方法用来清除cookie,当清除成功后会执行接收的参数(一个后调函数)
        req.session.destroy(() => {
            res.send({ ok: 1, msg: "退出登录成功!" });
        });
    },
};

routes/users.js中定义Api路由:

// 退出登录
router.get("/logout", UserController.logout);

6️⃣ 链接数据库

前面我们通过 req.session.user = data;设置的session默认是存放到内存中的,当后端服务重启时这些session就会被清空,为了解决这一问题我们可以将session存放到数据库中。

安装connect-mongo

npm i connect-mongo

connect-mongoMongoDB会话存储,用于用Typescript编写的连接Express

修改app.js

// 引入connect-mongo
var MongoStore = require("connect-mongo");

// 配置session
app.use(
    session({
        name: "AilixUserSystem", // cookie名字
        secret: "iahsiuhaishia666sasas", // 密钥:服务器生成的session的签名
        cookie: {
            maxAge: 1000 * 60 * 60, // 过期时间:一个小时过期
            secure: false, // 为true时表示只有https协议才能访问cookie
        },
        resave: true, // 重新设置session后会重新计算过期时间
        rolling: true, // 为true时表示:在超时前刷新时cookie会重新计时;为false表示:在超时前无论刷新多少次,都是按照第一次刷新开始计时
        saveUninitialized: true, // 为true时表示一开始访问网站就生成cookie,不过生成的这个cookie是无效的,相当于是没有激活的信用卡
        store: MongoStore.create({
            mongoUrl: "mongodb://127.0.0.1:27017/usersystem_session", // 表示新建一个usersystem_session数据库用来存放session
            ttl: 1000 * 60 * 60, // 过期时间
        }), // 存放数据库的配置
    })
);

至此,我们就实现了运用Cookie&Session进行登录验证/权限拦截的功能!

更多node相关知识,请访问:nodejs 教程

위 내용은 노드 실습: 로그인 확인을 위해 Cookie&Session 사용의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 csdn.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제