点数
60点
感想
書籍のタイトルにReactとあるが、結局Reactは出てこなかった。。
最後に「次回はReactを使用して…」と書いてあるが、続編は発売されていないらしい。。。
OAuthを使ったTwitter認証やmoment-timezoneなどは参考になったが、全体的にわかりづらかった。
OAuth
Twitterを使ったログイン
TwitterはOAuth1.0aに対応している。
以下の手順でAPI keyを取得することができる。
※事前にTwitter Developer Accountの登録が必要
https://www.itti.jp/web-direction/how-to-apply-for-twitter-api/
- https://developer.twitter.com/en/appsの「Create an app」をクリック。
- 「Enable Sign in with Twitter」をチェック。
- 「Website URL」にサイトのURL、「Callback URLs」に認証後のリダイレクト先URLを入力。
- 「Keys and tokens」タブにAPI keyとAPI secret keyが表示される。
passport-twitter
ExpressでTwitterを使用したOAuth認証を行うためのミドルウェア。
トークンはハードコードせずに、環境変数から取得するとよい。
- インストール
npm install passport-twitter --save-dev
- 環境変数をセット
export TWITTER_CONSUMER_KEY=xxxxx
export TWITTER_CONSUMER_SECRET=xxxxx
export TWITTER_CALLBACK_URL=xxxxxx
- app.js
const http = require('http');
const express = require('express');
const passport = require('passport');
const TwitterStrategy = require('passport-twitter').Strategy;
const session = require('express-session');
const app = express();
const twitterConfig = {
consumerKey: process.env.TWITTER_CONSUMER_KEY,
consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
callbackURL: process.env.TWITTER_CALLBACK_URL,
};
app.use(session({
secret: 'b87ef9fb4a152dbfe4cf4ea630444474',
resave : false,
saveUninitialized : false,
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new
TwitterStrategy(twitterConfig,
// 認証後のアクション
(token, tokenSecret, profile, done) => {
// callbackURLへリダイレクトされる
return done(null, profile);
}
));
app.get('/', (req, res, next) => {
res.send(`id:${req.session.user.id}`);
});
app.get('/oauth/twitter', passport.authenticate('twitter'));
app.get('/oauth/twitter/callback', passport.authenticate('twitter'),
(req, res, next) => {
req.session.user = req.session.passport.user;
return res.redirect("/")
}
);
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
const server = http.createServer(app);
server.listen('3000');
connect-mongo
セッション情報をメモリではなくMongoDBに保存するために必要なライブラリ。
デフォルトではsessionsという名前のコレクションに格納される。
- インストール
npm i connect-mongo --save-dev
- app.js
const MongoStore = require('connect-mongo')(session);
// 〜省略〜
app.use(session({
secret: 'b87ef9fb4a152dbfe4cf4ea630444474',
resave : false,
saveUninitialized : false,
store: new MongoStore({
mongooseConnection: mongoose.connection,
db: 'chatapp',
ttl: 14 * 24 * 60 * 60,
}),
// cookie: { secure: true },
}));
セキュリティ
helmet
セキュリティー関連の9個のHTTP ヘッダーを適切な値にセットしてくれるミドルウェア。
https://www.npmjs.com/package/helmet
使い方は、requireでモジュールを読み込んでuseでミドルウェアとして利用するだけ。
npm install helmet --save-dev
- app.js
const helmet = require('helmet');
// 〜省略〜
app.use(helmet());
csurf
CSRF対策のためのミドルウェア。
- インストール
npm install --save-dev csurf
- app.js
const csrf = require('csurf');
const csrfProtection = csrf();
// フォームと送信先のルーティングでミドルウェアを使う
app.get('/form', csrfProtection, (req, res, next) => {
res.render('index', {csrf: req.csrfToken()});
});
app.post('/', csrfProtection, (req, res, next) => {
res.render('index', {message: req.body.message});
});
- テンプレート
input(type="hidden" name="_csrf" value=csrf)
エラーはExpressデフォルトのエラーハンドラで処理する。err.code
にEBADCSRFTOKEN
がセットされる。
app.use(function(err, req, res, next) {
log.error(err);
if (err.code === 'EBADCSRFTOKEN'){
res.status(403)
}else{
res.status(err.status || 500);
}
return res.render('error', {
message: err.message,
status: err.status || 500
});
});
cors
最近はCORS(Cross-Origin Resource Sharing)を解除してAPIを公開する需要が増えてきた。
CORSを許可するにはHTTPヘッダに許可するための記述が必要となる。
Expressではcorsというミドルウェアを使う。
- インストール
npm install cors --save-dev
- app.js
const cors = require('cors');
// 全てのルーティングでCORSを許可する場合
app.use(cors());
// 特定のルーティングのみCORSを許可する場合
app.get('get-json', cors(), (req, res, next) => {
res.json({hoge: 'hogehoge'});
});
オプションを指定すると、ホストやHTTPメソッド単位での許可が可能となる。
https
Expressではhttpsミドルウェアを使うことで、プロトコルをhttpsにすることができる。
httpsミドルウェアはExpressに含まれているので個別のインストールは不要。
秘密鍵とサーバ証明書はあらかじめ用意しておく。
const fs = require('fs');
const https = require('https');
const options = {
key: fs.readFileSync('../lets_encript.key'),
cert: fs.readFileSync('../lets_encript_fullchain.crt')
};
// 〜省略〜
const server = https.createServer(options, app);
server.listen(3000);
moment-timezone
JavaScriptのDateオブジェクトは実行環境によっては世界標準時となってしまう。そして出力が見づらい。
moment-timezoneがその2つを解決してくれる。
※moment-timezoneはmoment.jsの上位互換版
- インストール
npm install moment-timezone --save-dev
- app.js
const moment = require('moment-timezone');
moment.tz.setDefault("Asia/Tokyo");
console.log(moment().format('YYYY-MM-DD HH:mm:ss'));
moment.jsはサーバのロケールを設定する必要がある。
moment-timezoneの場合は必要ない。
https://www.kwbtblog.com/entry/2019/10/05/152745
Expressでのログアウト処理
passportを使うとreq.isAuthenticated()
メソッドが追加される。
req.isAuthenticated()
を使ってログイン状態を判定するミドルウェア(関数)をルーティングに追加する。
const checkAuth = (req, res, next) => {
if (req.isAuthenticated()) {
next();
}
else {
res.redirect('/oauth/twitter');
}
};
app.get('/', checkAuth, csrfProtection, (req, res, next) => {
// 処理
});
また、passportを使うとreq.logout()
メソッドが追加される。
app.get('/logout', checkAuth, (req, res, next) => {
req.logout();
delete req.session.user;
res.redirect('/');
});
コメント