內容目錄
[Node.js] 使用 Firebase 對於 Web Authentication 帳號建立與認證
在 Vuetify SPA 開發 建置了基本的框架,接下來將與 Firebase 的認證機制作整合。首先,依 Firebase 對於 Realtime Database 的初步使用 先申請一個專案,並在此專案加入對 web app 的支援,此時應該可以得到 Firebase 對此的 config 資料。
展示網址 : https://polinwei.github.io/vue2-vuetify/
設定 Realtime Database & 認證機制
建立一個節點 logs 可以供帳號註冊及登入時,記錄帳號的資訊
設定對 節點: logs 的讀寫規則
這裡設定對於 logs 這個節點的規則:只有註冊的帳號可以讀寫。
{ "rules": { ".read": false, ".write": false, "vue2-spa" :{ ".read":"true", ".write":"false", "logs" :{ ".read": false, ".write": false, "$data": { ".read": "auth.uid != null", ".write": "auth.uid != null", }, } } } }
若不想控管權限,只要有資料就可以寫入的話,可以設定規則如下
{ "rules": { ".read": false, ".write": false, "$data": { ".read": true, ".write": "!data.exists()", }, } }
進階的規則,可以參考官方文件: https://firebase.google.com/docs/database/security。
啟用認證以 “電子郵件/密碼”
建立一個註冊及登入的畫面
HTML 的部份如下:
<template> <v-container> <v-card width="500" class="mx-auto my-auto"> <v-card-title> <h1>Login</h1> </v-card-title> <v-card-text> <v-form ref="form"> <v-text-field v-model="loginFormData.email" :rules="emailRules" label="Email" prepend-icon="mdi-account-circle" clearable /> <v-text-field v-model="loginFormData.password" :rules="[(v) => !!v || 'Password is required']" :type="showPassword ? 'text' : 'password'" label="Password" clearable prepend-icon="mdi-lock" :append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'" @click:append="showPassword = !showPassword" /> </v-form> </v-card-text> <v-divider></v-divider> <v-card-actions> <v-btn color="error" @click="reset">Reset</v-btn> <v-btn color="warning" @click="btnRegister">Register</v-btn> <v-btn color="info" @click="btnLogin">Login</v-btn> </v-card-actions> </v-card> <v-snackbar v-model="snackbar" :timeout="msg.timeout" top right color="pink" > {{ msg.text }} <template v-slot:action="{ attrs }"> <v-btn text v-bind="attrs" @click="snackbar = false"> Close </v-btn> </template> </v-snackbar> <v-overlay :value="overlay"> <v-progress-circular indeterminate size="64" ></v-progress-circular> </v-overlay> </v-container> </template>
針對於 JavaScript ,作細部的說明
安裝 Firebase 套件 與 vue-monent
/** https://firebase.google.com/docs/web/setup#node.js-apps */ $ npm install firebase --save $ npm install vue-moment
import 必要的 Firebase
// Firebase App (the core Firebase SDK) is always required // and must be listed first import firebase from "firebase/app"; // Add the Firebase products that you want to use import "firebase/auth"; import "firebase/firestore"; import "firebase/database";
頁面建立時,要初始 Firebase
created() { // Initialize Firebase firebase.initializeApp(this.firebaseConfig); }
帳號註冊時的作業
要使用 firebase.auth().createUserWithEmailAndPassword(email, password)
來作帳號註冊。註冊後,使用 firebase.auth().currentUser.sendEmailVerification()
來發送驗證信件。為了不讓申請者重覆送出註冊資料,在這裡需要使用 async
& await
,並且利用遮罩 v-overlay
來作屏避。
async btnRegister() { if (this.$refs.form.validate()) { this.overlay=true; await firebase .auth() .createUserWithEmailAndPassword( this.loginFormData.email, this.loginFormData.password ) .then((authCredential) => { this.fbUser = authCredential.user; firebase .auth() .currentUser.sendEmailVerification() .then(async () => { // 取得註冊當下的時間 //let date = new Date(); //let now = date.getTime(); let now = this.$moment().format("YYYY-MM-DD HH:MM"); let YM = this.$moment().format("YYYY-MM"); firebase .database() .ref("/vue2-spa/logs/" + YM + "/" + this.fbUser.uid) .set({ signup: now, email: this.loginFormData.email, }) .catch((error) => { // Handle Errors here. this.msg.text = error; this.snackbar = true; }); // Verification email sent. this.snackbar = true; this.msg.text = "註冊成功, 已發出信件"; await setTimeout(() => { this.$router.push("/home"); this.overlay=false; }, this.msg.timeout); }) .catch(function(error) { // Handle Errors here. this.msg.text = error; this.snackbar = true; this.overlay=false; }); }) .catch((error) => { // Handle Errors here. this.msg.text = error; this.snackbar = true; this.overlay=false; }); } else { this.msg.text = "送出錯誤"; this.snackbar = true; } }
當帳號以 email 註冊後,會發驗證信件
帳號登入時的作業
登入時,利用 firebase.auth().signInWithEmailAndPassword 來作認證,在此會使用屬性 authCredential.user.emailVerified 來驗證註冊的帳號是否有點選驗證連結來啟用。
async btnLogin() { if (this.$refs.form.validate()) { this.overlay=true; await firebase .auth() .signInWithEmailAndPassword( this.loginFormData.email, this.loginFormData.password ) .then((authCredential) => { // POST TO SERVER this.fbUser = authCredential.user; if (this.fbUser.emailVerified) { // 取得登入當下的時間 let now = this.$moment().format("YYYY-MM-DD HH:MM"); let YM = this.$moment().format("YYYY-MM"); firebase .database() .ref("/vue2-spa/logs/" + YM + "/" + this.fbUser.uid) .update({ signin: now, email: this.loginFormData.email, }) .then(async () => { // signed in and go to home page. this.snackbar = true; this.msg.text = "登入成功, 將轉至首頁"; await setTimeout(() => { this.$router.push("/home"); this.overlay=false; }, this.msg.timeout); }) .catch((error) => { // Error occurred. Inspect error.code. this.msg.text = error; this.snackbar = true; this.overlay=false; }); } else { this.snackbar = true; this.msg.text = "請先驗證信箱, 再登入"; this.overlay=false; } }) .catch((error) => { // Handle Errors here. this.msg.text = error; this.snackbar = true; this.overlay=false; }); } else { this.msg.text = "送出錯誤"; this.snackbar = true; } }
帳號註冊與登入的記錄
Firebase 對於 Realtime Database 提供 firebase.database().ref().update() 函數來對某一節點作存取,在一開始的存取規則是對節點: /vue2-spa/logs
且必需是有註冊的帳號才有權限讀取,所以程式段是這麼寫的. 這樣就可以了.
let now = this.$moment().format("YYYY-MM-DD HH:MM"); let YM = this.$moment().format("YYYY-MM"); firebase.database().ref("/vue2-spa/logs/" + YM + "/" + this.fbUser.uid) .update({ signin: now, email: this.loginFormData.email, })
參考:
https://firebase.google.com/codelabs/firebase-get-to-know-web
https://firebase.google.com/docs/reference/node
https://www.oxxostudio.tw/articles/201904/firebase-realtime-database-rules.html
你必須 登入 才能發表評論。