SPIRAL ver.2 では、標準機能としてログイン日時を自動で登録する仕組みは提供していません。
そのため、ログイン履歴を確認したい場合は、管理画面の「認証エリアログ」から確認いただけますが、
こちらはサイト全体の管理権限をお持ちの方のみ閲覧可能となっています。
アプリ利用者がユーザの最終ログイン日時を把握したい場合には、
ログイン日時を保存しておくことで、
「最新のログイン日時」だけでなく「前回ログイン日時」も取得可能となり、
不正アクセスの早期発見など、セキュリティ対策にも活用できます。
本記事では、PHPとAPIを組み合わせて、
認証DBに「ログイン日時」と「前回ログイン日時」を登録する方法をご紹介します。
実装の概要
今回の実装では、ブラウザのCookieに格納されている「セッション」を取得し、PHPのセッションと比較します。
比較をすることで「新規ログイン」または「ログイン状態」かを判断し、「新規ログイン」の際に認証DBに「最終ログイン日時」「前回ログイン日時」を更新する処理を行います。
確実にセッションを確認するため、認証エリアの各ページのPHPにプログラムを設定ください。
また、ログアウトを行い、ログアウトページに遷移した際にはセッションを破棄するため、ログアウトページのPHPにセッション破棄のプログラムを設定します。
※PHPのセッションがない場合には、Cookieの「セッション」を格納し、認証DBに対し更新処理をします。
ログアウトを行わず、時間でログアウトした場合にも再ログインでログイン日時は更新されます。
※ログイン中に、セッション破棄のページにアクセスして認証エリアのぺージに戻る場合、ログイン日時が更新されます。
2. ページのPHPが動作し、Cookieに格納されている「セッション」と、PHPのセッションを比較
3. 「2」の比較により、セッションが異なる場合、PHPのセッションをCookieに格納されている「セッション」に更新
4. 「3」と同時に、APIで認証DBの【「前回ログイン日時」を「最終ログイン日時」に更新】、【「最終ログイン日時」を現在時間】に更新】
5. ログアウトを行った際に遷移するログアウトトップページでPHPのセッションを破棄する
実装手順
1. 認証DBにフィールドを追加
認証エリアに設定しているDBを、認証DBとします。
認証DBには、ログイン日時の情報を保持するため、「最終ログイン日時」「前回ログイン日時」の2フィールドを追加で用意します。
| 項目名 | 識別名 | フィールドタイプ |
|---|---|---|
| 最終ログイン日時 | lastLogin | 日時 |
| 前回ログイン日時 | previousLogin | 日時 |
2. 認証エリアのページにPHPコードを記載
ログイン日時を正しく取得するためには、認証エリアの各ページにコードを記載する必要があります。
各ページのPHPにコードを記載した場合、コードを変更した際に前ページ変更が必要となってしまいます。
そのため、PHPモジュールにコードを記載し、各ページではモジュールを呼び出す設定を推奨しております。
設定する際には、サイトのPHPモジュール をご覧ください。
<?php
//------------------------------
// 設定値
//------------------------------
define("API_URL", "https://api.spiral-platform.com/v1");
define("API_KEY", "APIキー");
define("APP_ROLE", "アプリロール識別名");
define("DB_ID", "DBID");
define("APP_ID", "アプリID");
define("Area_ID","認証エリアID");
//------------------------------
// 認証レコード情報を取得
//------------------------------
$lastLogin = $SPIRAL->getAuthRecordByFieldId("xx"); // 最終ログイン日時
$_id = $SPIRAL->getAuthRecordByFieldId("_id"); // id
//------------------------------
// Cookieのセッションキーを取得
//------------------------------
$Cookie_Name = "asid_" . Area_ID;
$Cookie_Session = $_COOKIE[$Cookie_Name];
//------------------------------
// PHPのSessionの取得
//------------------------------
session_start();
if (!isset($_SESSION['PHP_session'])) { // PHPのセッションが存在しない場合、作成
$_SESSION['PHP_session'] = "";
}
$PHP_session = $_SESSION['PHP_session'];
//------------------------------
// 現在日時をUTC形式で取得
//------------------------------
$now = new DateTime('now', new DateTimeZone('UTC'));
$DateFormat = $now->format('Y-m-d\TH:i:s\Z');
//------------------------------
// API実行
// ------------------------------
$commonBase = CommonBase::getInstance();
if($Cookie_Session != $PHP_session){ // CookieのセッションとPHPのセッションが異なる場合に動作
// セッションの更新
$_SESSION['PHP_session'] = $Cookie_Session;
// 更新するデータを指定
$UpdateData = array(
"lastLogin" => $DateFormat,
"previousLogin" => $lastLogin
);
$recordId = $_id;
$resultRecordUpdate = $commonBase->apiCurlAction("PATCH", "/apps/". APP_ID. "/dbs/". DB_ID. "/records/". $recordId, $UpdateData);
} else {
// セッションの更新
$_SESSION['PHP_session'] = $Cookie_Session;
}
//------------------------------
// 共通モジュール
//------------------------------
class CommonBase {
/**
* シングルトンインスタンス
* @var UserManager
*/
protected static $singleton;
public function __construct() {
if (self::$singleton) {
throw new Exception('must be singleton');
}
self::$singleton = $this;
}
/**
* シングルトンインスタンスを返す
* @return UserManager
*/
public static function getInstance() {
if (!self::$singleton) {
return new CommonBase();
} else {
return self::$singleton;
}
}
/**
* V2用 API送信ロジック
* @return Result
*/
function apiCurlAction($method, $addUrlPass, $data = null, $multiPart = null, $jsonDecode = null) {
$header = array(
"Authorization:Bearer ". API_KEY,
"X-Spiral-Api-Version: 1.1",
);
if($multiPart) {
$header = array_merge($header, array($multiPart));
} else {
$header = array_merge($header, array("Content-Type:application/json"));
}
if(APP_ROLE){
$header = array_merge($header, array("X-Spiral-App-Role: ".APP_ROLE));
}
// curl
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_URL, API_URL. $addUrlPass);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
if ($method == "POST") {
if ($multiPart) {
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
} else {
curl_setopt($curl, CURLOPT_POSTFIELDS , json_encode($data));
}
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
}
if ($method == "PATCH") {
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
}
if ($method == "DELETE") {
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
}
$response = curl_exec($curl);
if (curl_errno($curl)) echo curl_error($curl);
curl_close($curl);
if($jsonDecode){
return $response;
}else{
return json_decode($response, true);
}
}
}
?>
| API_URL |
リクエスト先URLの固定部分です。 固定値ですので特に変更する必要はありません。 |
|---|---|
| API_KEY |
発行したAPIキーを設定してださい。 別途権限の付与が必要になります。 |
| APP_ROLE |
設定したアプリロールの識別名を入れてください。 全権限の場合は値は空で大丈夫です。 |
| DB_ID | レコード操作を行うDBのIDを設定してください。 |
| APP_ID | レコード操作を行うDBがあるアプリのIDを設定してください。 |
| Area_ID | 認証エリアの設定モーダルから確認できる、認証エリアのIDを設定してください。 |
▼認証レコード情報を取得について
| getAuthRecordByFieldId("xx") | xxの値に、DBの「最終ログイン日時」のフィールドのID(1、2など)を指定します。 |
|---|---|
| getAuthRecordByFieldId("_id") | 固定値ですので特に変更する必要はありません。 |
3. ログアウト後ページに、PHPコードを記載
セキュリティ対策のため、ログアウト後ページに、セッション破棄を行うプログラムを追加します。
▼PHPコード
<?php
session_start();
if (isset($_SESSION['PHP_session'])) { // PHPセッションがある場合
unset($_SESSION['PHP_session']); // PHPセッションを破棄
}
?>
実行結果
初回のログイン、またはログアウトを行いセッションが更新された際にアクセスするとログイン日時を更新します。
リロードや、他の認証ページに遷移していても、セッションが同じ場合にはログイン日時は更新されません。
また、ログアウト後にセッションが破棄されており、再ログインした際に、ログイン日時が更新されます。
まとめ
この実装により、認証DBにてユーザの最終ログイン日時を確認することや、前回ログイン日時を取得し不正ログインの検知に役立てることもできます。