JavaScript >> Javascript 文檔 >  >> JavaScript

如何在操縱桿中連接用戶帳戶和經過身份驗證的路由

如何在 Joystick 中創建用戶帳戶、登錄用戶並幫助他們重置密碼以及如何創建基於用戶登錄狀態重定向的受保護路由。

開始使用

在本教程中,我們將使用 CheatCode 的全棧 JavaScript 框架 Joystick。 Joystick 將前端 UI 框架與用於構建應用的 Node.js 後端結合在一起。

首先,我們要通過 NPM 安裝 Joystick。確保在安裝之前使用 Node.js 16+ 以確保兼容性(如果您需要學習如何安裝 Node.js 或在計算機上運行多個版本,請先閱讀本教程):

終端

npm i -g @joystick.js/cli

這將在您的計算機上全局安裝操縱桿。安裝好之後,接下來我們新建一個項目:

終端

joystick create app

幾秒鐘後,您將看到一條消息已註銷到 cd 進入你的新項目並運行 joystick start

終端

cd app && joystick start

在此之後,您的應用應該可以運行了,我們可以開始了。

添加一些全局 CSS

在我們深入研究用戶帳戶的邏輯之前,很快,我們將添加一些全局 CSS 來清理我們的 UI:

/index.css

*, *:before, *:after {
  box-sizing: border-box;
}

body {
  font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif;
  font-size: 16px;
  background: #fff;
  margin: 20px;
}

form {
  width: 100%;
  max-width: 400px;
}

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 20px;
}

.form-field {
  margin-bottom: 20px;
}

label {
  font-size: 15px;
  font-weight: bold;
  display: block;
  margin-bottom: 10px;
  display: flex;
}

label a {
  display: inline-block;
  margin-left: auto;
  font-weight: normal;
  color: #aaa;
}

input {
  width: 100%;
  max-width: 100%;
  border: 1px solid #ddd;
  padding: 10px 15px;
  border-radius: 3px;
  font-size: 16px;
}

input:focus {
  outline: 0;
  border: 1px solid #0099ff;
  box-shadow: 0px 0px 0px 3px rgba(0, 153, 255, 0.3);
}

.input-hint {
  font-size: 14px;
  margin-bottom: 0px;
}

.input-hint.error {
  color: red;
}

button {
  padding: 10px 15px;
  font-size: 16px;
  background: #0099ff;
  color: #fff;
  border-radius: 3px;
  border: none;
}

在本教程的後面部分,我們的 UI 將僅包含用於管理用戶帳戶的表單。為了讓我們的 UI 更容易理解,我們在 /index.css 中添加了一些全局 CSS 文件位於我們應用程序的根目錄。此文件由 /index.html 中的 Joystick 自動加載 項目根目錄下的文件(為您的應用中的所有頁面呈現的基本 HTML 模板)。

除了表單樣式,我們還為 box-sizing 添加了一些簡單的重置 屬性(這確保在瀏覽器中遵守填充和邊距)和 body 元素,設置默認字體,字體大小,甚至為 <body></body> 添加了一個小邊距 所以我們的內容從瀏覽器邊緣偏移了一點。

添加路線和頁面

深入研究代碼,我們的目標是連接一組頁面來管理帳戶的整個生命週期。現在,我們要在服務器上設置一系列路由,將頁面呈現給瀏覽器中的用戶:

  • /signup 將呈現一個表單,用戶可以在其中創建新帳戶。
  • /login 將呈現一個表單,用戶可以在其中登錄現有帳戶。
  • /recover-password 將呈現一個表單,用戶可以在其中觸發現有帳戶的密碼重置請求。
  • /reset-password/:token 將呈現一個表單,用戶可以在其中輸入新密碼並更新他們在數據庫中的用戶記錄。

Joystick 應用程序中的所有路由都傳遞給 node.app() 函數的選項對象,位於/index.server.js 項目根目錄下的文件:

/index.server.js

import node from "@joystick.js/node";
import api from "./api";

node.app({
  api,
  routes: {
    "/dashboard": (req, res) => {
      res.render("ui/pages/dashboard/index.js", {
        layout: "ui/layouts/app/index.js",
      });
    },
    "/signup": (req, res) => {
      res.render("ui/pages/signup/index.js", {
        layout: "ui/layouts/app/index.js",
      });
    },
    "/login": (req, res) => {
      res.render("ui/pages/login/index.js", {
        layout: "ui/layouts/app/index.js",
      });
    },
    "/recover-password": (req, res) => {
      res.render("ui/pages/recoverPassword/index.js", {
        layout: "ui/layouts/app/index.js",
      });
    },
    "/reset-password/:token": (req, res) => {
      res.render("ui/pages/resetPassword/index.js", {
        layout: "ui/layouts/app/index.js",
      });
    },
    "*": (req, res) => {
      res.render("ui/pages/error/index.js", {
        layout: "ui/layouts/app/index.js",
        props: {
          statusCode: 404,
        },
      });
    },
  },
});

默認情況下,當你運行 joystick create ,為您設置的項目模板為我們定義了兩條路線 /* .前者渲染一個示例 Joystick 組件,後者渲染當前 URL 找不到匹配路由時顯示的 404 或“錯誤”頁面。

對於我們的工作,我們將從替換 / 開始 帶有將充當虛假“登錄”頁面的路線的路線。在上面的代碼中,我們做了幾件事:

  1. 交換/ /dashboard 的路線 在 /ui/pages/dashboard/index.js 處路由和渲染定義為操縱桿組件的頁面 .
  2. 對於我們上面列出的每個頁面,在 routes 下定義一個路由 對像傳遞給 node.app() 的選項 .這是 Joystick 用來為我們啟動 Express.js 服務器的函數。當該服務器啟動時,我們在 routes 下列出的每個路由 被添加為 HTTP GET 路由。
  3. 對於每個路由,使用 @joystick.js/ui 渲染定義為操縱桿組件的頁面 在 /ui/pages 我們應用根目錄下的目錄。

為了讓它工作,我們需要確保我們所有的頁面都在 /ui/pages 中定義 目錄。

接下來,讓我們繼續創建一些框架頁面作為佔位符(之後我們將花費大部分教程來連接這些頁面):

/ui/pages/dashboard/index.js

import ui from '@joystick.js/ui';

const Dashboard = ui.component({
  render: () => {
    return `
      <div>
        <p>Dashboard</p>
      </div>
    `;
  },
});

export default Dashboard;

/ui/pages/signup/index.js

import ui from '@joystick.js/ui';

const Signup = ui.component({
  render: () => {
    return `
      <div>
        <p>Signup</p>
      </div>
    `;
  },
});

export default Signup;

/ui/pages/login/index.js

import ui from '@joystick.js/ui';

const Login = ui.component({
  render: () => {
    return `
      <div>
        <p>Login</p>
      </div>
    `;
  },
});

export default Login;

/ui/pages/recoverPassword/index.js

import ui from '@joystick.js/ui';

const RecoverPassword = ui.component({
  render: () => {
    return `
      <div>
        <p>RecoverPassword</p>
      </div>
    `;
  },
});

export default RecoverPassword;

/ui/pages/resetPassword/index.js

import ui from '@joystick.js/ui';

const ResetPassword = ui.component({
  render: () => {
    return `
      <div>
        <p>ResetPassword</p>
      </div>
    `;
  },
});

export default ResetPassword;

有了這些,現在,如果我們在瀏覽器中的 http://localhost:2600 加載我們的應用程序 並檢查我們在上面定義的每個路由,我們應該看到我們的佔位符組件。

現在,為了開始工作,我們將連接 /signup 頁面。

連接註冊頁面

可以預見的是,/signup 頁面將是我們的用戶可以創建帳戶的地方。首先,讓我們為頁面添加 HTML 標記並討論發生了什麼,然後添加功能以創建帳戶。

/ui/pages/signup/index.js

import ui from '@joystick.js/ui';

const Signup = ui.component({
  render: () => {
    return `
      <form>
        <div class="form-grid">
          <div class="form-field">
            <label for="firstName">First Name</label>
            <input type="text" name="firstName" placeholder="First Name" />
          </div>
          <div class="form-field">
            <label for="lastName">LastName</label>
            <input type="text" name="lastName" placeholder="LastName" />
          </div>
        </div>
        <div class="form-field">
          <label for="emailAddress">Email Address</label>
          <input type="email" name="emailAddress" placeholder="Email Address" />
        </div>
        <div class="form-field">
          <label for="password">Password</label>
          <input type="password" name="password" placeholder="Password" />
        </div>
        <button type="submit">Sign Up</button>
      </form>
    `;
  },
});

export default Signup;

上面,我們開始構建我們的 /signup 通過在我們組件的 render() 中填寫 HTML 頁面 功能。

我們的表單會很簡單:只需輸入幾個輸入,要求輸入姓名、電子郵件地址和密碼,然後是提交按鈕。

/ui/pages/signup/index.js

import ui, { accounts } from '@joystick.js/ui';

const Signup = ui.component({
  events: {
    'submit form': (event, component) => {
      event.preventDefault();
      component.validateForm(event.target, {
        rules: {
          firstName: {
            required: true,
          },
          lastName: {
            required: true,
          },
          emailAddress: {
            required: true,
            email: true,
          },
          password: {
            required: true,
            minLength: 6,
          },
        },
        messages: {
          firstName: {
            required: 'First name is required.',
          },
          lastName: {
            required: 'Last name is required.',
          },
          emailAddress: {
            required: 'An email address is required.',
            email: 'Please use a valid email.',
          },
          password: {
            required: 'A password is required.',
            minLength: 'Please use at least six characters.',
          },
        },
      }).then(() => {
        accounts.signup({
          emailAddress: event.target.emailAddress.value,
          password: event.target.password.value,
          metadata: {
            name: {
              first: event.target.firstName.value,
              last: event.target.lastName.value,
            },
          },
        }).then(() => {
          location.pathname = '/dashboard';
        });
      });
    },
  },
  render: () => {
    return `
      <form>
        ...
      </form>
    `;
  },
});

export default Signup;

現在來看看有趣的東西。首先,我們要提請注意我們文件的頂部。請注意,我們為變量 accounts 添加了一個額外的命名導入 來自 @joystick.js/ui 包裹。此對象包含 Joystick 的所有與帳戶相關的功能(對我們服務器上預定義帳戶路由的 HTTP 調用)。對於這個組件,我們將使用 accounts.signup() 功能。

在調用該函數之前,我們將利用 .validateForm() Joystick 包含在我們的 component 中的方法 實例。如果我們看上面的代碼,我們在這裡做的是為 submit 添加一個事件監聽器 <form></form> 上的事件 我們在 render() 中向下渲染 功能。

分配給 'submit form' 的函數內部 事件——這是每當 submit 時都會調用的事件 在我們的表單上檢測到事件——我們首先調用 event.preventDefault() 停止將表單內容序列化為查詢參數並嘗試將它們提交到 URL 的默認瀏覽器行為(在非 JavaScript 應用程序中,表單的內容通常作為 HTTP POST 請求發送到由 action <form></form> 上的屬性 元素)。

相反,我們希望完全控製表單的提交事件,而是調用 accounts.signup() 我們在上面暗示的功能。不過,在此之前,我們想使用 component.validateForm() (在 component 上的操縱桿內部為我們預定義 我們可以在事件處理程序中訪問的實例作為處理程序回調函數的第二個參數)來驗證用戶的輸入是否符合我們的期望。

這裡,.validateForm() 接受兩個參數:首先,一個代表 <form></form> 的 DOM 節點 我們要驗證第二個,具有兩個屬性的選項對象,rulesmessages . rules 包含我們每個輸入的驗證規則,將每個輸入的特定規則設置為匹配 name 的屬性 render() 中輸入的屬性 功能。

對於每個屬性,我們傳遞一個對象,其中包含我們要為每個輸入設置的各個規則。在這裡,我們使用了三個規則:

  1. required 它將輸入標記為需要一個值。
  2. email 這會將輸入標記為需要有效的電子郵件地址。
  3. minLength 它將輸入標記為需要一個長度等於傳遞值的值(這裡是密碼字段上的 6)。

為了改善表單的用戶體驗和反饋,如果用戶未能通過任何驗證,.validateForm() 函數將自動在有問題的輸入下方呈現錯誤消息,顯示 messages 中定義的錯誤消息之一 rules 下設置的對象 .

對於我們在 rules 下指定的每個規則 ,我們還為每個規則傳遞相應的消息。所以,對於 password 字段,因為我們有一個 required 規則和一個 minLength 規則,如果用戶的輸入不符合這些規則,我們會提供錯誤消息。

.validateForm() 之後 被調用,假設用戶的輸入是“好的”並且符合我們的驗證,.then() 回調(.validateForm() 返回一個 JavaScript Promise 給我們)將被觸發。如果驗證失敗,.catch() 回調將被觸發(我們已經跳過了這裡的定義,但是如果你想向用戶顯示額外的反饋——比如 toast 警報——可以在 .catch() 中完成 )。

.then() 內部 回調,我們終於調用了 accounts.signup() 傳遞帶有函數期望的字段的對象。為了我們的需要,我們通過了三個:

  • emailAddress 設置為 emailAddress 的值 我們表單上的字段,通過 event.target.emailAddress.value 訪問 event.target 是我們的表格,emailAddress 是帶有 name 的輸入 屬性等於 emailAddress , 和 value 是該輸入的當前值。
  • password 設置為 password 的值 我們表單上的字段,遵循與 emailAddress 相同的邏輯 .
  • metadata 設置為我們要分配給用戶記錄的雜項值的對象,這裡是 name 對於用戶設置為包含 first 的對象 和 last 具有相應 firstName 值的屬性 和 lastName 我們表單中的字段。

類似於 .validateForm() , accounts.signup() 函數返回一個 JavaScript Promise,所以我們再次添加一個 .then() 成功創建用戶後將觸發該函數的回調。在裡面,因為我們知道我們有一個登錄用戶(操縱桿會自動在瀏覽器中設置一個帶有用戶登錄令牌的 cookie)我們將用戶重定向到 /dashboard 我們之前設置的路線(location.pathname 是在 window.location 上設置的值 設置後會將瀏覽器重定向到該路徑的對象)。

這樣做是為了註冊。好消息:我們的其餘頁面都遵循完全相同的模式,因此我們會更快地瀏覽它們。

連接登錄頁面

繼續/login 頁面,讓我們看一下完整的組件並回顧一下我們在上面學到的內容:

/ui/pages/login/index.js

import ui, { accounts } from '@joystick.js/ui';

const Login = ui.component({
  events: {
    'submit form': (event, component) => {
      event.preventDefault();
      component.validateForm(event.target, {
        rules: {
          emailAddress: {
            required: true,
            email: true,
          },
          password: {
            required: true,
            minLength: 6,
          },
        },
        messages: {
          emailAddress: {
            required: 'An email address is required.',
            email: 'Please use a valid email.',
          },
          password: {
            required: 'A password is required.',
            minLength: 'Please use at least six characters.',
          },
        },
      }).then(() => {
        accounts.login({
          emailAddress: event.target.emailAddress.value,
          password: event.target.password.value,
        }).then(() => {
          location.pathname = '/dashboard';
        });
      });
    },
  },
  render: () => {
    return `
      <form>
        <div class="form-field">
          <label for="emailAddress">Email Address</label>
          <input type="email" name="emailAddress" placeholder="Email Address" />
        </div>
        <div class="form-field">
          <label for="password">Password <a href="/recover-password">Forget your password?</a></label>
          <input type="password" name="password" placeholder="Password" />
        </div>
        <button type="submit">Log In</button>
      </form>
    `;
  },
});

export default Login;

再次,同樣的想法。在頂部我們導入 ui 來自 @joystick.js/ui , 調用 ui.component() 設置我們的組件。在render()中 函數,我們為表單添加 HTML 標記。

events 中 對象——請記住,這些是 Joystick 將代表我們自動監聽的 DOM 事件——我們為 submit form 定義了一個監聽器 事件。所以很明顯,在Joystick中定義事件時,我們使用事件處理函數的key/property名稱來描述:

  1. 類型 我們正在監聽的 JavaScript DOM 事件(例如,submit , click , keyup 等)。
  2. 我們想要監聽事件的選擇器(這裡是 form 標籤,但它也可以是像 .login-form 這樣的 CSS 類 )。

對於該鍵/屬性名稱,我們分配該事件發生時要調用的函數。在裡面,我們確保調用 event.preventDefault() 確保瀏覽器 在瀏覽器中執行默認行為,序列化我們的表單值並嘗試將它們 HTTP POST 到 action 我們表單上的屬性(不存在)。

接下來,我們帶回我們的 .validateForm() 作為 @joystick.js/ui 的一部分自動交給我們的函數 通過 component 實例。對於那個函數,就像我們之前看到的那樣,我們為我們的表單傳入 DOM 元素(這裡,只是拉出 target 來自瀏覽器中原始 DOM 事件的屬性),後跟一個選項對象,描述我們要驗證表單的規則 by 以及在用戶輸入未通過驗證時顯示的錯誤消息。

因為我們期望 .validateForm() 要返回一個 JavaScript Promise,我們鏈接一個 .then() 最後回調,我們可以調用 accounts.login() 函數(accounts.signup() 的同級 我們之前在 accounts 上使用的函數 從 @joystick.js/ui 導入的對象 )。

event.target 到對像上的那個函數 代表我們的表單,我們傳遞 emailAddress 的值 字段(請記住,這映射到帶有 name 的輸入 屬性)和 password 字段。

假設我們用戶的電子郵件地址和密碼與用戶匹配,accounts.login() 將返回一個 JavaScript Promise,我們將其鏈接為 .then() 回調到處理成功狀態。在那個回調中,就像我們在 /signup 上所做的一樣 頁面,我們重定向到 /dashboard 通過設置 pathname 進行路由 window 上的屬性 的location 對象(同樣,我們還沒有定義或導入這個——它在瀏覽器中全局存在)。

這對於 /login 頁。現在,讓我們繼續進行密碼恢復和重置。

連接密碼恢復頁面

為了重置用戶的密碼,我們需要生成重置嘗試/令牌並將其添加到數據庫中的用戶記錄中。為此,我們將構建一個“恢復密碼”頁面,用戶可以在其中輸入他們的電子郵件以啟動重置嘗試。

好消息:我們在上面學到的一切也適用於這裡。讓我們看一下完整的組件,因為它沒有太多代碼:

/ui/pages/recoverPassword/index.js

import ui, { accounts } from '@joystick.js/ui';

const RecoverPassword = ui.component({
  events: {
    'submit form': (event, component) => {
      event.preventDefault();
      component.validateForm(event.target, {
        rules: {
          emailAddress: {
            required: true,
            email: true,
          },
        },
        messages: {
          emailAddress: {
            required: 'An email address is required.',
            email: 'Please use a valid email.',
          },
        },
      }).then(() => {
        accounts.recoverPassword({
          emailAddress: event.target.emailAddress.value,
        }).then(() => {
          window.alert(`Check your email at ${event.target.emailAddress.value} for a reset link.`);
        });
      });
    },
  },
  render: () => {
    return `
      <form>
        <div class="form-field">
          <label for="emailAddress">Email Address</label>
          <input type="email" name="emailAddress" placeholder="Email Address" />
        </div>
        <button type="submit">Reset Password</button>
      </form>
    `;
  },
});

export default RecoverPassword;

同樣,雖然它可能很無聊,但我們想強調遵循模式的重要性。在這裡,我們按照我們上面看到的完全相同的步驟,渲染我們的 HTML,添加一個事件監聽器,驗證我們的表單,然後執行相關的操作(在這種情況下,調用 accounts.recoverPassword() 並傳遞一個 emailAddress )。

還有一個組件(向我們介紹了一些新功能):重置密碼。

連接密碼重置頁面

使用 /recover-password 提交恢復密碼嘗試後 我們在上面連接的頁面,如果您的 config.smtp 設置存在於您的 settings.<env>.json 項目根目錄下的文件,Joystick 將嘗試發送密碼重置電子郵件。在開發中,Joystick 會自動註銷一個密碼重置 URL 到您的終端(您啟動 Joystick 應用程序的地方)進行測試。

該 URL 轉到 /reset-password/:token :token 是動態生成的令牌,例如 joXUGGscutZcvanJQ8Ao9qABjZkGUdSB 映射到 passwordResetTokens 數據庫中用戶的數組(對應恢復頁面上輸入的電子郵件地址)。

/ui/pages/resetPassword/index.js

import ui, { accounts } from '@joystick.js/ui';

const ResetPassword = ui.component({
  events: {
    'submit form': (event, component) => {
      event.preventDefault();
      component.validateForm(event.target, {
        rules: {
          newPassword: {
            required: true,
            minLength: 6,
          },
          repeatNewPassword: {
            required: true,
            minLength: 6,
            equals: event.target.newPassword.value,
          },
        },
        messages: {
          newPassword: {
            required: 'Must enter a new password.',
            minLength: 'Password must be at least six characters.',
          },
          repeatNewPassword: {
            required: 'Must repeat new password.',
            minLength: 'Password must be at least six characters.',
            equals: 'Passwords must match.',
          },
        },
      }).then(() => {
        accounts.resetPassword({
          token: component.url.params.token,
          password: event.target.newPassword.value,
        }).then(() => {
          window.alert(`Password reset, logging you back in...`);
          location.pathname = '/dashboard';
        });
      });
    },
  },
  render: () => {
    return `
      <form>
        <div class="form-field">
          <label for="newPassword">New Password</label>
          <input type="password" name="newPassword" placeholder="New Password" />
        </div>
        <div class="form-field">
          <label for="repeatNewPassword">Repeat New Password</label>
          <input type="password" name="repeatNewPassword" placeholder="Repeat New Password" />
        </div>
        <button type="submit">Reset Password</button>
      </form>
    `;
  },
});

export default ResetPassword;

類似的概念有一些細微的差別。我們如何為我們的組件渲染 HTML 和事件監聽器的使用是相同的,但仔細看兩件事:rules.validateForm()什麼 我們正在傳遞給 accounts.resetPassword() .

對於規則,我們使用了一個奇怪的規則,equals .請注意,這設置為等於帶有 name 的輸入的值 屬性等於 newPassword .這是因為對於此頁面,為了重置某人的密碼,我們希望確認他們在之前正確輸入了新密碼 改變它。

其次,在我們對 accounts.resetPassword() 的調用中 注意我們傳遞了一個 token 設置為 component.url.params.token 的字段 .在操縱桿中,有關當前 URL 的信息在 url 中可用 組件實例上的對象。在這裡,我們說“給我們 :token 的當前值 URL 中的參數。”

該令牌通過他們的 passwordResetTokens 映射到數據庫中的某個用戶 大批。當我們調用 accounts.resetPassword() ,假設令牌有效,用戶密碼更新,令牌過期(從他們的passwordResetTokens中刪除 數組),用戶自動登錄。

我們在 .then() 中暗示了這一點 accounts.resetPassword() 的回調 通過提醒用戶自動登錄,然後將他們重定向到 /dashboard 假設我們在瀏覽器的 cookie 中有一個登錄用戶令牌(在此處表示為 joystickLoginToken )。

添加經過身份驗證的公共路由

雖然我們已經設置了所有的帳戶頁面,但在結束之前,看看在 Joystick 中創建經過身份驗證的路由與公共路由是很重要的。 “經過身份驗證的路線”是需要登錄用戶才能查看的路線,而“公共路線”是不需要的路線 需要登錄用戶才能查看。

在 Joystick 中,我們有兩個輔助方法來管理服務器上的這個進程:.ifLoggedIn().ifNotLoggedIn() , 都分配給 req.context 我們路由中入站 HTTP 請求的對象。回到服務器,讓我們看看它們是如何工作的:

/index.server.js

import node from "@joystick.js/node";
import api from "./api";

node.app({
  api,
  routes: {
    "/dashboard": (req, res) => {
      req.context.ifNotLoggedIn('/login', () => {
        res.render("ui/pages/dashboard/index.js", {
          layout: "ui/layouts/app/index.js",
        });
      });
    },
    "/signup": (req, res) => {
      req.context.ifLoggedIn('/dashboard', () => {
        res.render("ui/pages/signup/index.js", {
          layout: "ui/layouts/app/index.js",
        });
      });
    },
    "/login": (req, res) => {
      req.context.ifLoggedIn('/dashboard', () => {
        res.render("ui/pages/login/index.js", {
          layout: "ui/layouts/app/index.js",
        });
      });
    },
    "/recover-password": (req, res) => {
      req.context.ifLoggedIn('/dashboard', () => {
        res.render("ui/pages/recoverPassword/index.js", {
          layout: "ui/layouts/app/index.js",
        });
      });
    },
    "/reset-password/:token": (req, res) => {
      req.context.ifLoggedIn('/dashboard', () => {
        res.render("ui/pages/resetPassword/index.js", {
          layout: "ui/layouts/app/index.js",
        });
      });
    },
    "*": (req, res) => {
      res.render("ui/pages/error/index.js", {
        layout: "ui/layouts/app/index.js",
        props: {
          statusCode: 404,
        },
      });
    },
  },
});

回到我們的 index.server.js 內部 文件並查看我們的路線,我們可以看到這兩個函數在起作用。它們被設計成像句子一樣閱讀。

"如果用戶不是 登錄,去這條路線,否則運行這個功能,”或“如果用戶 登錄,去這個路由,否則運行這個函數。”這裡的想法是我們應用程序中的一些路由需要用戶,而其他的不需要。這有雙重目的:加強我們應用程序的安全性和改善用戶體驗(用戶體驗)。

例如,如果到達 /dashboard route 需要一個用戶(可能是因為在我們的應用程序中,儀表板會加載私人數據),如果用戶沒有登錄,我們不希望用戶能夠訪問該路由。通過 UX 鏡頭查看,通過重定向用戶遠離他們試圖訪問的內容,我們傳達他們沒有滿足查看該頁面的必要要求(並希望重定向到像 /login 這樣的頁面 告知他們需要登錄才能到達那裡)。

相反,當涉及到 .ifLoggedIn() ,我們希望與已登錄的用戶溝通,他們無法返回僅用於已登錄的頁面退出 用戶。這不是關於安全性,而是更多關於用戶體驗和避免出現複雜錯誤的問題。

那應該這樣做。讓我們試駕一下,看看一切如何。

總結

在本教程中,我們學習瞭如何利用 Joystick 的內置帳戶系統為我們的應用程序連接帳戶流。我們學習瞭如何註冊新用戶、登錄現有用戶以及為忘記密碼的現有用戶實施密碼恢復工作流程。我們還學習瞭如何使用操縱桿的內置 .ifLoggedIn() 創建“受保護”路線 和 .ifNotLoggedIn() 在 HTTP 請求上定義的函數,以幫助我們提高安全性和用戶體驗。


Tutorial JavaScript 教程
  1. 揭秘 JWT:如何保護您的下一個 Web 應用程序

  2. React Js 中的組件類型⚛️

  3. Adonis JS 中的社交登錄和身份驗證

  4. 在矽谷初創公司領導開發者關係

  5. 樣式和類

  6. Covid19 Italy - 我的國家的項目

  7. 檢查頁面上是否存在 Javascript 腳本

  1. 如何在 Nuxt Config 中使用 Firebase 環境變量

  2. 前 30 名 Javascript 面試熱身練習第 3 部分

  3. 如何使用安全的私有 npm 註冊表

  4. 帶有 RobotJS 的 NodeJS 桌面自動化,(但有一個程序可以讓你解僱 h̶i̶r̶e̶d̶😄)

  5. 使用 Firebase 和 Formik 創建表單

  6. 使用 Bootstrap 模式上的 Put 方法的 React 幫助

  7. 10+ 單選按鈕 CSS 樣式示例

  1. 回調函數,像我 5 一樣向我解釋。

  2. 從 Markdown 文件建立一個文檔站點

  3. 構建以太坊氣體追踪器

  4. 使用 Firebase 函數和 Nodemailer 發送電子郵件