全端勇士之路 Node.js 基礎學習-會員機制(1)

前言

接下來將會來講如何設置會員機制,但是這邊將會使用到的是 firebase 的會員驗證機制

起手式

這邊就不附上如何快速產生 Express 的方式了,因為這邊我會直接使用 Express 產生器來產生。

直接跳到開啟 Firebase 後台,然後點一下 Authentication

Authentication

點一下 登入方式,並將以下方法打開

電子郵件/密碼

這邊我也直接放是我會使用的套件

1
npm install --save express-session nodemailer connect-flash csurf express-validator dotenv

app.js 內容也一併附上(很長)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var session = require('express-session');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var flash = require('connect-flash');
var csurf = require('csurf');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var authRouter = require('./routes/auth');

var csrfProtection = csurf({ cookie: true });

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
}))
app.use(flash());
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/login',csrfProtection ,authRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};

// render the error page
res.status(err.status || 500);
res.render('error');
});

module.exports = app;

接下來這邊還有一個重點,我們要使用 firebase 的登入認證之前還必須安裝一個套件,也就是 firebase-admin 還要建立 .env,如果不清楚可以看這篇 詳細說明

大致上操作都與上面這篇文章雷同,所以大致上結構會像這樣

結構

Router

目前 auth 內容只有這樣子

1
2
3
4
5
6
7
8
9
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});

module.exports = router;

在這邊 res.render我們 index 要修改成 login

1
2
3
router.get('/', function(req, res, next) {
res.render('login', { title: '登入畫面' });
});

而 EJS 頁面非常簡單,只是一個單純登入而已,基本上執行起來畫面就像這樣

Image

除了登入我們也要製作註冊的 router,這邊 EJS 一樣我就忽略了,因為比較沒有什麼

1
2
3
4
5
6
7
8
9
10
router.get('/signup', function(req, res, next) {
res.render('signup', {
csrfToken: req.csrfToken(),
title: '註冊帳號'
});
});

router.post('/signup', function(req, res, next) {
res.render('signup', { title: '註冊帳號' });
});

製作註冊 router

接下來就來開始製作註冊帳號的 router,首先要先接上 firebase,透過 firebase 本身提供的 API createUserWithEmailAndPassword 來建立帳號,但是在那之前必須先確保 signup 頁面的表單資料會正確的傳到伺服器,所以可以這樣測試

1
2
3
4
router.post('/signup', function(req, res, next) {
console.log(req.body);
res.render('signup', { title: '註冊帳號' });
});

如果正確接收到就會像這樣 (密碼欄位不用擔心,進入 firebase 的時候會加密,所以不可能取得)

表單資料

firebase-connect

確保表單資料有傳到伺服器後就可以開始實作註冊帳號哩,但是在那之前必須先連結 firebase,這邊你可能會覺得很詭異,前面不是已經載入一個 firebaseAdmin 了嗎?為什麼還要載入一個 firebase?

首先我們載入的 firebaseAdmin 主要是提供授權方面

那個接下來要設置的是 firebase-connect,這個功能可以呼叫各種 firebase 的 API,舉凡稍後我們要做的註冊帳號,所以首先先建立一個檔案叫 firebase-connect.js 於 connection 資料夾下

firebase-connect.js

那麼內容的取得在 專案設定 中

專案設定

然後拉到下方可以看到 Firebase SDK snippet,在這邊我們不會使用 CDN 得方式

Firebase SDK snippet

這邊我們所有資料都是採用 env 環境變數所傳入,另外這邊還要安裝一個套件,在前面文章沒有講到

1
npm install --save firebase

然後將 .env 改成以下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Firebase Admin
FIREBASE_DATABASEURL=
FIREBASE_TYPE=
FIREBASE_PROJECT_ID=
FIREBASE_PRIVATE_KEY_ID=
FIREBASE_PRIVATE_KEY=
FIREBASE_CLIENT_EMAIL=
FIREBASE_CLIENT_ID=
FIREBASE_AUTH_URL=
FIREBASE_TOKEN_URL=
FIREBASE_AUTH_PROVIDE_X509_CERT_URL=
FIREBASE_CLIENT_X509_CERT_URL=

# Firebase connect
FIREBASE_API_KEU=
FIREBASE_AUTH_DOMAIN=
FIREBASE_MESSAGINGSENDERID=
FIREBASE_STORAGEBUCKET=
FIREBASE_APPID

並且將剛剛取得得 Firebase SDK snippet 及內容改成以下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var firebase = require('firebase');
require('dotenv').config();

var firebaseConfig = {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.FIREBASE_DATABASEURL,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: "",
messagingSenderId: process.env.FIREBASE_MESSAGINGSENDERID,
appId: process.env.FIREBASE_APPID
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);

module.exports = firebase;

接下來在 auth.js 中引入 firebase,並將 router 改成以下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
router.post('/signup', function(req, res, next) {
var email = req.body.email;
var password = req.body.password;
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(function(){
res.redirect('/login/signup')
})
.catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
console.log(errorCode, errorMessage);
res.redirect('/login/signup')
});
});

接下來就可以試著註冊看看,註冊成功的話就可以在後台看到剛剛註冊得帳號哩

註冊成功

最後我使用 flash 將註冊成功與否訊息往前傳給使用者,所以最終 router 是這樣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
router.get('/', function(req, res, next) {
res.render('login', { title: '登入畫面' });
});

router.get('/signup', function(req, res, next) {
res.render('signup', {
success: req.flash('info'),
csrfToken: req.csrfToken(),
title: '註冊帳號'
});
});

router.post('/signup', function(req, res, next) {
var email = req.body.email;
var password = req.body.password;
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(function() {
req.flash('info','註冊成功');
res.redirect('/login/signup');
})
.catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
req.flash('info', errorMessage);
res.redirect('/login/signup');
});
});

Liker 讚賞

這篇文章如果對你有幫助,你可以花 30 秒登入 LikeCoin 並點擊下方拍手按鈕(最多五下)免費支持與牡蠣鼓勵我。
或者你可以也可以請我「喝一杯咖啡(Donate)」。

Buy Me A Coffee Buy Me A Coffee

Google AD

撰寫一篇文章其實真的很花時間,如果你願意「關閉 Adblock (廣告阻擋器)」來支持我的話,我會非常感謝你 ヽ(・∀・)ノ