##本記事を読む前の注意事項
現在ではAWSにUser Poolsという機能があります。
そちらを利用してログイン・ログアウトを実装したほうが遥かに効率が良いです。Amazon Cognito User Poolsを使って、webサイトにユーザ認証基盤を作るをご参照ください
概要
会員登録機能をサーバレスアーキテクチャで実装する に引き続き、今度はログイン・ログアウトの機能をAWSで構成を組みます。
アーキテクチャ
テーブル構成
DynamoDBでテーブルを構成します。
Usersテーブル
ユーザ情報を格納するテーブルです。ログインフォームからの情報を付きあわせて認証を行います。
項目 | 制約 | 備考 |
---|---|---|
Hash key | 会員IDとなるメールアドレスを保存 | |
password | パスワード | |
※実運用ではパスワードは暗号化して保存しましょう。また、登録日などの項目も運用次第で必要になると思います。 |
Sessionテーブル
セッション情報を格納するテーブルです。ログインが成功したら発行したセッションIDをこのテーブルに書き込み、ユーザのログイン、ログアウトの状態を管理します。
項目 | 制約 | 備考 |
---|---|---|
session_id | Hash key | セッションID |
Usersテーブルとの付き合わせ用 | ||
※実運用では、登録日などの項目も持たせて、セッションタイムアウト時間も設けたほうが良いです。 |
Lambdaファンクション
###ログイン処理
入力値として、emailとパスワードを受け取ります。
ログインに成功すればセッションIDを返します。webシステムで使う場合はこのセッションIDをcookieに保存して引き回してあげましょう
var aws = require("aws-sdk");
var doc = require('dynamodb-doc');
var crypto = require('crypto');
var dynamo = new doc.DynamoDB();
exports.handler = function(event, context) {
if ( typeof event.email === 'undefined' || typeof event.password === 'undefined' ) {
context.fail("Login failed");
}
if ( event.email === '' || event.password === '' ) {
context.fail("Login failed");
}
console.log(event.email);
var dynamoRequest = {
TableName: 'users',
Key: {
"email": event.email
}
};
dynamo.getItem(dynamoRequest, function (err, res) {
if (err) {
console.log(err);
return;
} else {
console.log(event.email);
console.log(res);
if ( Object.keys(res).length > 0 && res.Item.password === event.password ) {
var date = new Date() ;
var session_id = md5_hex(date.getTime() + event.email);
var dynamoRequest = {
TableName: 'session',
Item: {
'session_id':session_id,
'email':event.email
}
};
dynamo.putItem(dynamoRequest, function(err, data){
if (err) {
console.log(err);
} else {
context.succeed({session_id:session_id});
}
});
} else {
context.fail("Login failed");
}
}
});
};
function md5_hex(src) {
var md5 = crypto.createHash('md5');
md5.update(src, 'utf8');
return md5.digest('hex');
}
###ログアウト処理
入力値としてセッションIDを渡して、Sessionテーブルからレコードを削除します。
var aws = require("aws-sdk");
var doc = require('dynamodb-doc');
var dynamo = new doc.DynamoDB();
exports.handler = function(event, context) {
var dynamoRequest = {
TableName: 'session',
Key: {
"session_id": event.session_id
}
};
dynamo.deleteItem(dynamoRequest, function (err, res) {
if (err) {
console.log(err);
return;
} else {
context.succeed({ret:'true'});
}
});
}
API Gateway
上記のLambdaファンクションをAPIとして設定してあげます。
webシステムをフロントとして組み込む
S3においたHTML上でJavaScriptからこれらのAPIを叩いてシステム化を行います。
ログイン処理はこんな感じでAjaxで行います。ちなみにjQueryで書いてます
$("#login").on( "click", function(){
var data = {
email:$("#email").val(),
password:$("#password").val()
}
$.ajax( {
url:'<API Gatewayエンドポイント>',
method: "POST",
crossDomain: true,
data: JSON.stringify(data),
success: function(response) {
if ( typeof response.session_id !== 'undefined' ) {
$.cookie("serverless_website_session_id", response.session_id, {path:"/"});
location.href = "/mypage";
} else if ( response.errorMessage === 'Login failed' ) {
$('#error').text('Login failed');
}
}
});