ホームページ  >  記事  >  ウェブフロントエンド  >  ノードの実践: ログイン検証に Cookie とセッションを使用する

ノードの実践: ログイン検証に Cookie とセッションを使用する

青灯夜游
青灯夜游転載
2022-12-01 20:16:252716ブラウズ

ノードの実践: ログイン検証に Cookie とセッションを使用する

元アドレス: https://ailjx.blog.csdn.net/article/details/127909213

著者: 海中BBQレストラン ai

前のセクションでは、シンプルなユーザー管理システムのプロジェクト構造を作成して最適化し、

Cookie セッションのログイン検証の動作原理についても説明しました。本システムの機能 ここでは実際にCookie-Sessionを利用して本システムのログイン認証機能を実装していきます。 [関連チュートリアルの推奨事項: nodejs ビデオ チュートリアル ]

えっ?

セッションクッキーをまだ理解していません!前の記事を確認してください: Cookie セッション ログイン認証の仕組みの詳細な説明

##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 です。
Request

routes
ディレクトリに新しい

login.js を作成します。このファイルは、login## のページ ルーティングを定義します。 # page: <pre class="brush:js;toolbar:false;">var express = require(&quot;express&quot;); var router = express.Router(); /* GET login page. */ router.get(&quot;/&quot;, function (req, res, next) { res.render(&quot;login&quot;); }); module.exports = router;</pre>app.js にページ ルーティングをマウントします:

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

プロジェクトを開始し、http://localhost:3000/login## にアクセスします。 #通常表示:

##2️⃣ ノードの実践: ログイン検証に Cookie とセッションを使用するservices/UserService.js に API インターフェース

を定義します インターフェイスのモデル (M 層 ) を定義します。

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

インターフェイスの制御層 (C 層 ) を controllers/ で定義します。 UserController.js :

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.jsApi を定義します:

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

この時点で、ログイン ページは次のようになります。セットアップ:

3️⃣ セッションの設定ノードの実践: ログイン検証に Cookie とセッションを使用する

前のセクションのCookie-Sessionログイン検証の仕組み 冒頭でわかったこと:

図 1

このプロセスは明らかにより複雑です。# には

があります。 ##expressノードの実践: ログイン検証に Cookie とセッションを使用する 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是无效的,相当于是没有激活的信用卡
    })
);
設定後、次のことがわかります。ブラウザに AilixUserSystem という名前の

cookie があることを確認します。

これは、express-session が原因です。自動的に

cookie

を解析し、ノードの実践: ログイン検証に Cookie とセッションを使用するcookie

をフロントエンドに設定します。これは、図 1 の

3 と 6 に相当します (前半: SessionId## によるクエリ) #セッション)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);
   }
},
# をリクエストしますユーザーのログイン情報を保存するために、user フィールドが ##req.session に追加されます。この手順は、図 1 の #1 に相当します (SessionId は

express-session

Module になります)自動的に生成されます)、2

req.sessionsession オブジェクトです。このオブジェクトは req に存在しますが、実際にはreq.session

は、設定した
cookie

に基づいているため、ユーザーがシステムにアクセスするときの req.session は異なります ( によって Express-session モジュール (AilixUserSystem) によって自動的に生成され、システムにアクセスする各ユーザーによって生成される cookie は一意であるため、その req はsession もユニークです。 リクエストを受信したら session を確認し、次のコードを app.js に追加します: <pre class="brush:php;toolbar:false">// 设置中间件:session过期校验 app.use((req, res, next) =&gt; {     // 排除login相关的路由和接口     // 这个项目中有两个,一个是/login的页面路由,一个是/api/login的post api路由,这两个路由不能被拦截     if (req.url.includes(&quot;login&quot;)) {         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(&quot;api&quot;)             ? res.status(401).send({ msg: &quot;登录过期!&quot;, code: 401 })             : res.redirect(&quot;/login&quot;);     } });</pre>注: これコードはルーティング設定の前にある必要があります。

このコードでは、

req.session.myData = Date.now(); を通じて session オブジェクトを変更し、それによって session をトリガーします。

有効期限の更新 (
myData

session
この属性とその値

Date.now()session オブジェクトを変更するだけですツール、 自体には意味がありません )、req.session を変更できる限り、他の方法を使用することもできます。

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

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

ノードの実践: ログイン検証に Cookie とセッションを使用する

这个时候需要让前端自己对返回结果进行判断从而进行下一步的操作(如回到登录页或显示弹窗提示),该系统中前端是使用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 とセッションを使用するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。