既存システムの認証方法でAppBeadsにログイン
はじめに
社内の既存システムをAppBeadsのノーコードツール(タイニーApp)で内製化してリプレースすることになりました。
既存のシステムを使いながら少しずつリプレースするので、既存のアカウントでAppBeadsにログインできるようにします。
既存システムの認証方法
既存システムには次のようなテーブルがあります。
(実際のテーブルはもう少し複雑ですが、この記事では主要な項目のみに簡略化しました。)
| テーブル名 | 内容 |
|---|---|
| M_USER | ユーザー情報 |
| 項目 | カラム名 | 型 | 備考 |
|---|---|---|---|
| ユーザー名 | USER_NM | VARCHAR2(30 CHAR) | 主キー |
| 表示名 | DISP_NM | VARCHAR2(30 CHAR) | |
| パスワード | PASSWORD | VARCHAR2(100 CHAR) | パスワードのハッシュ値 |
| メール | VARCHAR2(50 CHAR) |
ログイン画面で入力されたログイン名とパスワードがこのテーブルに登録されている内容と合致すれば認証成功です。
古いシステムは SAML や ActiveDirectory ではなく、このような認証方法が多いようです。
データベースの設定
既存のデータベース(オラクル)を使うので、まずはデータベースの設定をします。
AppBeadsにログインして、メニューの [設定] をクリックします。
ユーザーが未登録の状態ならログイン名とパスワードを入力しないでログインできます。


[+データベースを追加する] をクリックして、既存のデータベースに接続するための情報を入力します。
データベース名: INTERNAL_DB
表示名: 社内データベース
入力し終えたら、画面右上の [保存] をクリックしてから、一旦、ログアウトします。

AppBeadsのカスタマイズ
AppBeadsには認証方法をカスタマイズする仕組みが用意されています。
AppBeadsには、ログインや排他制御など、システムの共通処理をカスタマイズするためのモデル(PHP)があります。
カスタマイズ用モデルのファイル名はab_custom.phpで、modelsフォルダにあります。
AppBeadsのインストール先に models というフォルダがあります。
このフォルダ内の ab_custom.php というソースファイルに認証方法をプログラミングします。(言語はPHP)

私はプログラミングができないので、今回は取引先のIT会社に依頼しました。
AppBeadsはオープンソースなので、特定のIT業者でなくてもカスタマイズを依頼できます。
ab_custom.php には次のような個所があり、checkPassword という関数がコメントアウトされています。
/**
* パスワードを検査する
*
* @param string $loginName ログイン名
* @param string $password パスワード
* @return bool true: 認証成功、false: 認証失敗
*/
/*
public function checkPassword($loginName, $password) {
}
*/
この checkPassword をアンコメントして、次のような認証処理をプログラミングします。
/**
* パスワードを検査する
*
* @param string $loginName ログイン名
* @param string $password パスワード
* @return bool true: 認証成功、false: 認証失敗
*/
public function checkPassword($loginName, $password) {
// ログイン名とパスワードが正しいかユーザーマスターを検索するSQL文
$sql = '-- AB_DATABASE:INTERNAL_DB'."\n"; // 社内データベース(INTERNAL_DB)に接続する
$sql .= 'SELECT *'."\n";
$sql .= 'FROM M_USER'."\n";
$sql .= 'WHERE UPPER(USER_NM) = UPPER(:LOGIN_NAME)'."\n";
$sql .= 'AND PASSWORD = STANDARD_HASH(:PASSWORD, \'SHA256\')'."\n"; // パスワードをハッシュ値で比較する
// SQLを実行する
$result = $this->abExecSql($sql, ['LOGIN_NAME'=> $loginName, 'PASSWORD'=> $password]);
// 認証成功
if (count($result) > 0) {
// ユーザー情報を更新する
$this->abUpdateUser([
self::AB_LOGIN_NAME => $result[0]['USER_NM'],
self::AB_USER_ID => null,
self::AB_USER_LAST_NAME => null,
self::AB_USER_FIRST_NAME=> $result[0]['DISP_NM'],
self::AB_USER_MAIL => $result[0]['MAIL']
]);
// 認証成功時はtrueを返す
return true;
}
// 認証失敗
return false;
}
checkPassword では2つの処理を行います。
1. 認証処理を行う。
2. 認証成功ならユーザー情報を登録する。
それぞれの処理に分けてプログラムを見てみます。
- 認証処理を行う。
ログイン名(:LOGIN_NAME)とパスワード(:PASSWORD)で M_USER テーブルを検索するSQL文をつくります。
SQL文の先頭にある-- AB_DATABASE:INTERNAL_DBは、設定画面で追加した社内データベースに接続するためのものです。
ログイン名は大小文字を区別しないようにするためUPPERで大文字に変換して比較します。
パスワードはSTANDARD_HASHでハッシュ値に変換して比較します。
// ログイン名とパスワードが正しいかユーザーマスターを検索するSQL文
$sql = '-- AB_DATABASE:INTERNAL_DB'."\n"; // 社内データベース(INTERNAL_DB)に接続する
$sql .= 'SELECT *'."\n";
$sql .= 'FROM M_USER'."\n";
$sql .= 'WHERE UPPER(USER_NM) = UPPER(:LOGIN_NAME)'."\n";
$sql .= 'AND PASSWORD = STANDARD_HASH(:PASSWORD, \'SHA256\')'."\n"; // パスワードをハッシュ値で比較する
abExecSql でSQLを実行します。
SQLのログイン名(LOGIN_NAME)とパスワード(PASSWORD)には、
checkPassword の引数 $loginName と $password を使います。
// SQLを実行する
$result = $this->abExecSql($sql, ['LOGIN_NAME'=> $loginName, 'PASSWORD'=> $password]);
- 認証成功ならユーザー情報を登録する。
SQLの検索結果があれば認証成功です。
M_USER から取得したユーザー情報を abUpdateUser でAppBeadsに登録します。
AppBeadsでは姓と名が別々ですが、既存システムでは分けていません。
だから、名(AB_USER_FIRST_NAME)に表示名(DISP_NM)を入れて、姓(AB_USER_LAST_NAME)は空欄(null)にします。
// 認証成功
if (count($result) > 0) {
// ユーザー情報を更新する
$this->abUpdateUser([
self::AB_LOGIN_NAME => $result[0]['USER_NM'],
self::AB_USER_ID => null,
self::AB_USER_LAST_NAME => null,
self::AB_USER_FIRST_NAME=> $result[0]['DISP_NM'],
self::AB_USER_MAIL => $result[0]['MAIL']
]);
// 認証成功時はtrueを返す
return true;
}
既存システムのアカウントでログイン
ab_custom.php を編集したら、既存システムのアカウントでAppBeadsにログインします。

無事にログインできました。

ユーザーが登録されたことを確認するためユーザー管理画面を開きます。

[検索] をクリックします。

既存システムのユーザー情報が登録されています。

おわりに
今回は既存システムのデータベースを参照して認証を行いましたが、SAML や ActiveDirectory で認証を行う場合でも checkPassword に処理を書きます。(と、エンジニアの方が言っていました。)
Discussion