走進Vue的秘密森林 02:製作登入頁面

在把環境設置完成後,接著要來建立後台登入頁面
這次製作的網站中,分為前台消費者使用頁面以及後台管理頁面

在製作後台管理頁面時,首先要建立的是登入頁面
後台管理頁面通常是由廠商/客戶端使用,所以我們會在這邊建立一個登入頁面,防止前台的商品被隨便更動

建立登入頁面

建立pages資料夾 & 新增login頁面

1.在components資料夾下,建立一個pages資料夾,之後建立的頁面都會放在這邊

2.新增一個login.vue檔,並到index.js檔中將login檔案import及定義routes路徑。
※ 用 export 可以指派函式、物件或變數,透過 import 宣告給外部檔案引用。

1
import Login from '@/components/pages/Login';

3.這裡使用的是bootstrap example套入樣式至login頁面
https://getbootstrap.com/docs/4.4/examples/

並將example的css樣式用scoped方式只新增在此頁
程式碼如下:

1
2
3
4
5
<style scoped>

<!-- 此處為login css樣式 -->

</style>

結果如下:

前端 axios 請求附帶 Cookies 設定

1.至main.js將前端cookie的開關打開,如此可以透過API的回應檢查目前狀態為登入或登出,甚至可以檢查用戶是否仍持續登入

把 cookie 開關打開的方式:

1
axios.defaults.withCredentials = true;

後端設定 token based 的做法 (jwt)

1.先取目前用戶的 token id
2.把 token id 設定 session cookie
3.設定到 request.cookie 裡面
之後用戶呼叫的 api 需要驗證的話,就可以從設定的 request.cookie 的值取出來,用 Node.js 後端做驗證

後端跨域設定:
在 apps.js 設定跨域處理

1
2
3
4
5
6
7
8
9
10
11
12
app.all('*', (req, res, next) => {
res.header('Access-Control-Allow-Headers', 'Content-Type,Authorization, Accept,X-Requested-With,x-csrf-token');
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header('Access-Control-Allow-Credentials', true);
// 這裡不能用 * 號, 要改成 domain 的方式才能設置 cookies
res.header('Access-Control-Allow-Origin', req.headers.origin);
if (req.method === 'OPTIONS') {
res.send(200);
} else {
next();
}
});

新增API連接

使用參數:

1
2
3
4
user: {
username: '',
password: '',
},

並在input中加入:

1
2
v-model="user.username"  <!-- 帳號 -->
v-model="user.password" <!-- 密碼 -->

並製作登入的事件,將事件@submit.prevent="signin"綁定在form上
結果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<form class="form-signin" @submit.prevent="signin">
<h1 class="h3 mb-3 font-weight-normal">請先登入</h1>
<label for="inputEmail" class="sr-only">Email address</label>
<input type="email" id="inputEmail" class="form-control" v-model="user.username" placeholder="Email address" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" id="inputPassword" class="form-control" v-model="user.password" placeholder="Password" required>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> 記住帳號
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<p class="mt-5 mb-3 text-muted">&copy; 2020 壹壹玖餐飲集團股份有限公司 All Rights Reserved.</p>
</form>

並在下方export中增加一個 methods,登出事件亦同:

1
2
3
4
5
6
7
8
9
10
11
12
13
methods: {
signin() {
const api = `${process.env.VUE_APP_APIPATH}/admin/signin`; //將API更改為登入用
console.log(api);
const vm = this;
this.$http.post(api , vm.user).then((response) => { //vm.user = 帳號+密碼
console.log(response.data);
if (response.data.success) { // 若data回傳成功,路徑會導回首頁
vm.$router.push('/');
}
});
}
}

登入驗證&阻擋

初步的登入頁面就製作後,我們要來設置應該登入頁面的驗證及阻擋
這裡會使用的一個功能叫:導航守衛

1.製作導航守衛以驗證使用者是否為登入狀態下進入網址
至main.js使用 router.beforeEach 註冊一個全局前置守衛:

1
2
3
router.beforeEach((to, from, next) => {
// ...
});

2.並在要阻擋的頁面中設置路由訊息

1
meta: { requiresAuth: true },  // 路由訊息

結果如下:

1
2
3
4
5
6
7
8
9
10
export default new VueRouter({
routes: [
{
name: 'Login',
path: '/login',
component: () => import('@/components/pages/admin/Login'),
meta: { requiresAuth: true }, // 路由訊息
},
]
});

※ 此時頁面會被阻擋,無法輸入路徑直接跳至該頁面

3.在步驟1的router.beforeEach中加入if判斷式**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  if (to.meta.requiresAuth) {  // 若要前往的頁面具有requiresAuth的話,就不會放行
const api = `${process.env.VUE_APP_APIPATH}/api/user/check`;
const vm = this; // vm = data
axios.post(api).then((response) => { // 因不是在vue下執行此元件,所以此處的this.$http使用axios替代
if (response.data.success) { // 若成功登入→放行;若非登入狀態,則會跳回登入頁面
next();
}else {
next({
path: '/login',
});
}
});
}else { // 反之,若無requiresAuth的話,會直接放行至下一頁
next();
}
});

如此一來,這個登入頁面就完成阻擋的功能,無法直接輸入網址跳過登入頁到後台管理內頁啦!