node/expressで、 CSRF対応の例 #node #javascript
■ 概要:
node / Express で、CSRFセキュリティ対応の例となります。
■ 環境
node
express
■ 参考
先人様の記事を、参考にしました。
https://qiita.com/kmatae/items/0ce25ac6bde0b301402a
■ 参考の設定
■ npm 追加
npm install csrf --save
npm install express-session --save
■ 実装など
・express-session 読込
var session = require('express-session');
・login ルーティング 読込み
var loginRouter = require('./routes/login');
・express-session 設定
// CSRF
app.use(session({
secret: 'secret key',
resave: false,
saveUninitialized: false,
cookie: {
//生存期間は3日
maxAge: 3 * 24 * 60 * 1000,
//httpsを使用しない
secure: false
}
}));
・login ルーティング
app.use('/login', loginRouter);
・app..js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var session = require('express-session');
//
var indexRouter = require('./routes/index');
var loginRouter = require('./routes/login');
var app = express();
const expressLayouts = require('express-ejs-layouts');
app.use(expressLayouts);
// 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(express.static(path.join(__dirname, 'public')));
app.use(function(req,res,next){
next();
});
// CSRF
app.use(session({
secret: 'secret key',
resave: false,
saveUninitialized: false,
cookie: {
//生存期間は3日
maxAge: 3 * 24 * 60 * 1000,
//httpsを使用しない
secure: false
}
}));
// route
app.use('/', indexRouter);
//app.use('/tasks', tasksRouter );
app.use('/login', loginRouter);
// api
//app.use('/api', apiRouter );
// 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;
・login.js , Get:画面表示, POST:CSRF 処理
・APIで、CSRFトークン判定
失敗:例外処理で、NGコードのレスポンス返す
OK: OKコードのレスポンス返す
var express = require('express');
var router = express.Router();
var csrf = require('csrf');
var tokens = new csrf();
/********************************
*
*********************************/
router.get('/', function(req, res) {
try{
var secret = tokens.secretSync();
var token = tokens.create(secret);
req.session._csrf = secret;
res.cookie('_csrf', token);
res.render('login');
} catch (e) {
console.log(e);
}
});
/********************************
*
*********************************/
router.post('/', function(req, res){
var ret_arr = {ret:0, msg:""}
try{
var data = req.body
console.log(data )
var secret = req.session._csrf;
var token = req.cookies._csrf;
if(tokens.verify(secret, token) === false)
{
throw new Error('Invalid Token');
}else{
console.log("Success, Token");
}
delete req.session._csrf;
res.clearCookie('_csrf');
ret_arr.ret = 1
res.json( ret_arr )
} catch (e) {
console.log(e);
res.json(ret_arr);
}
});
module.exports = router;
■ 参考の画面ejs
views/login.ejs
<div id="app">
<h1>Login</h1>
<hr />
<div class="form-group">
<label for="TopicTitle">mail :</label>
<input type="text" class="form-control" v-model="mail">
</div>
<div class="form-group">
<label for="TopicContent">password :</label>
<input type="password" class="form-control" v-model="password">
</div>
<button v-on:click="send_post">ログイン</button>
</div>
■ テスト
・ curlで、ブラウザ以外で不正アクセス/テストする場合
curl -X POST http://localhost:3000/login -d "mail=hoge" -d "password=1111"
実行すると、サーバーログに、Invalid Token 等出力されます
Error: Invalid Token
at /home/naka/work/node/express/app9_auth/routes/login.js:43:19
at Layer.handle [as handle_request] (/home/naka/work/node/express/app9_auth/node_modules/express/lib/router/layer.js:95:5)
at next (/home/naka/work/node/express/app9_auth/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/home/naka/work/node/express/app9_auth/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/home/naka/work/node/express/app9_auth/node_modules/express/lib/router/layer.js:95:5)
at /home/naka/work/node/express/app9_auth/node_modules/express/lib/router/index.js:281:22
at Function.process_params (/home/naka/work/node/express/app9_auth/node_modules/express/lib/router/index.js:335:12)
at next (/home/naka/work/node/express/app9_auth/node_modules/express/lib/router/index.js:275:10)
at Function.handle (/home/naka/work/node/express/app9_auth/node_modules/express/lib/router/index.js:174:3)
at router (/home/naka/work/node/express/app9_auth/node_modules/express/lib/router/index.js:47:12)
この記事が気に入ったらサポートをしてみませんか?