iT邦幫忙

2023 iThome 鐵人賽

DAY 19
0
自我挑戰組

30 天架設 Node.js - Express 框架:快速學習之路系列 第 19

Day 19 - 身分驗證與授權:實作使用者註冊和登入系統(上)

  • 分享至 

  • xImage
  •  

經過前幾天的介紹,我們已經更熟悉使用 Express 框架,
接下來我們需要實作才能學以致用,

今天開始我們會開始做一個小專案,來記錄我們每個人的書單列表。
首先第一步,就是做註冊和登入系統,

讓我們繼續看下去吧~

實作登入流程

  • 首先,先來做首頁與登入的頁面,可以依自己喜好加上 CSS 樣式。
  • Header 跟 Footer,可以照我們 Day 8 所學到的樣版引擎進行拆分,減少我們重複的程式碼。
    <!-- public/views/index.ejs -->

    <!DOCTYPE html>
      <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="/views/css/index.css">
        <title>首頁</title>
      </head>
        <!-- Header -->
        <%- include('header') %>
        <!-- Header -->
      <body>
        <main>
          <p><%= username %>'s book list  </p>
        </main>
        <!-- Footer -->
        <%- include('footer') %>
        <!-- Footer -->
      </body>
    </html>
    <!-- public/views/signIn.ejs -->

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>sign in</title>
      <link rel="stylesheet" href="/views/css/signIn.css"> <!-- 引入您的 CSS 文件 -->
    </head>
    <body>
        <!-- Header -->
        <%- include('header') %>
        <!-- Header -->
      <main>
        <!-- 註冊表單 -->
        <form action="/signIn" method="post"> 
          <label for="username">Username:</label>
          <input type="text" id="username" name="username" required>
          <br>
          <label for="password">Password:</label>
          <input type="password" id="password" name="password" required>
          <br>
          <button type="submit">Login</button>
          <div class="login-text">Already have an account?<a href="/login">Click here to log in.</a></div>
          <div>
            <% if (error) { %>
              <p><%= error %></p>
            <% } %>
          </div> 
        </form>
      </main>
        <!-- Footer -->
        <%- include('footer') %>
        <!-- Footer -->
    </body>
    </html>
    <!-- public/views/login.ejs -->

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Log in</title>
      <link rel="stylesheet" href="/views/css/login.css"> <!-- 引入您的 CSS 文件 -->
    </head>
    <body>
        <!-- Header -->
        <%- include('header') %>
        <!-- Header -->
      <main>
        <!-- 登入表單 -->
        <form action="/login" method="post"> 
          <label for="username">Username:</label>
          <input type="text" id="username" name="username" required>
          <br>
          <label for="password">Password:</label>
          <input type="password" id="password" name="password" required>
          <br>
          <button type="submit">Login</button>
          <div class="login-text">Don't have an account yet?<a href="./signIn">Click here to register.</a></div>
          <div>
            <% if (error) { %>
              <p><%= error %></p>
            <% } %>
          </div>      
        </form>
      </main>
        <!-- Footer -->
        <%- include('footer') %>
        <!-- Footer -->
    </body>
    </html>

login.ejs 需要注意 <form action="/login" method="post"> 的地方,
我們填完表單送出時,會打 POST /login 方法,
usernamepassword 資料傳遞過來,
所以我們需要創一個 POST /login 的路由,來處理傳過來的登入表單資料。


express-session 套件介紹

  • 因為我們需要記住使用者已經當入的狀態,
    所以接下來會介紹 express-session 這個套件來將使用者資料儲存在 session。

  • app.js 檔案,載入 express-session 套件,並使用 app.use() 調用此套件。

        // app.js
    
        app.use(session({
          secret: 'your-secret-key', // 建議將此替換為實際的安全密鑰
          resave: false, // 是否每次都重新保存 session,預設為 true
          saveUninitialized: false, // 是否每次都重新產生 session,預設為 true
          cookie: { secure: false } // 建議在生產環境中將其設置為 true,以使用HTTPS
        }))
        app.use(router)
    

    app.use(session()) 的 middleware 需要設置於 app.use(router) 之前,這樣執行 router 時才能取得 session 資訊。

  • 因為我們每頁都要確認該使用者是否為登入狀態,可以新增一個 middleware 資料夾,並新增一個 auth.js 檔案,將我們判斷是否登入的 middleware 方法寫在這裡。

  • 我們用 session 來判別是否該使用者的登入狀態,並且判斷 登入 / 未登入兩種狀況 →

    • 未登入:如果沒有 session 表示該使用者沒有登入過,就會導去我們的登入頁。
    • 已登入:就可以查看我們所建立的書單頁面。

    一般都是儲存不太重要的資料作為判別,千萬不要把使用者密碼也存起來哦!

      ```jsx
          // middleware/auth.js
    
          function requireLogin(req, res, next) {
            if (req.session && req.session.user) {
              // 用戶已經登入,繼續執行下一個中間件或路由處理程序
              return next()
            } else {
              // 用戶未登入,重定向到登入頁面或其他處理方式
              return res.redirect('/login')
            }
          }
    
          module.exports =requireLogin
      ```
    
  • 在今天設置的首頁和登入頁(index.ejslogin.ejs)加入 GET 方法,這樣瀏覽器輸入 localhost:3000/localhost:3000/ login 才能 render 出 首頁和登入頁的畫面。

    • 將 login和 signIn 模組化。

          // routes/modules/index.js
      
          router.get('/', requireLogin, (req, res) => {
            res.render('index', {'username': req.session.user})
          })
      
          // routes/modules/login.js
      
          router.get('/', (req, res) => {
            res.render('login')
          })
      
          // routes/modules/signIn.js
          router.get('/', (req, res) => {
            res.render('signIn')
          })
      
    • 將兩個模組導入我們的 index.js

          // routes/index.js
      
          const express = require('express')
          const router = express.Router()
      
          const index = require('./modules/index')
          const login = require('./modules/login')
          const signIn = require('./modules/signIn')
      
          router.use('/', index)
          router.use('/login', login)
          router.use('/signIn', signIn)
      
  • 還記得我們剛剛建立判斷是否登入的 middleware 嗎?

    如果我們希望在一進首頁時就確認該使用者是否登入,所以我們就要在進到首頁路由前,判斷是否為登入狀態,如果沒有登入過就要導去登入頁。

        const requireLogin = require('../../middleware/auth') // 引入判斷是否登入的模組
    
        router.get('/', requireLogin, (req, res) => { // 在進入首頁時判斷是否為登入狀態
          res.render('index')
    })
    

今天先介紹到這邊~
剩下我們明天再繼續介紹!


上一篇
Day 18 - Express 必備:介紹常用的套件(下)
下一篇
Day 20 - 身分驗證與授權:實作使用者註冊和登入系統(中)
系列文
30 天架設 Node.js - Express 框架:快速學習之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言