前回までの話。
ログインチェック作成
いよいよユーザテーブルからログイン可否の判断を行おうと思います。
まず準備として、手動でテーブルにデータを二つ追加しておきます。
違いは、ユーザ権限が1と0です。
パスワードも今は適当で。

Visual Studioに戻ります。
今回、一度ログインするとユーザIDとユーザ名と管理者権限の有無は保持しておきたいので、
SupplyRequestManager.hに、変数とセットゲット関数を加えておきます。
private:
CString m_strUserId; // ユーザID
CString m_strUserName; // ユーザ名
BOOL m_bUserAuth; // 管理者権限
public:
// ユーザID取得
CString strGetUserId() { return m_strUserId; }
// ユーザID設定
void SetUserId(CString strUserId) { m_strUserId = strUserId; }
// ユーザ名取得
CString strGetUserName() { return m_strUserName; }
// ユーザ名設定
void SetUserName(CString strUserName) { m_strUserName = strUserName; }
// 管理者権限取得
BOOL bGetUserAuth() { return m_bUserAuth; }
// 管理者権限設定
void SetUserAuth(BOOL bUserAuth) { m_bUserAuth = bUserAuth; }メンバ変数は、SupplyRequestManager.cppで初期化も忘れずに。
続きまして、MySQLManager.hに、ログインチェック用の関数を追加。
public:
//ログインチェック
BOOL bCheckLogin(CString strId, CString strPassword);MySQLManager.cppで具体的な処理を書きます。
/**
* @fn
* @brief ログインチェック
* @param CString strId ログインID
* CString strPassword ログインパスワード
* @return TRUE ログイン成功
* FALSE ログイン失敗
*/
BOOL CMySQLManager::bCheckLogin(CString strId, CString strPassword)
{
try
{
m_con->setSchema(SCHEMA); // スキーマ選択
sql::SQLString sqlStrId = strConverter(strId); // 型変換
sql::SQLString sqlStrPass = strConverter(strPassword); // 型変換
sql::SQLString strSqlQuery = "SELECT * FROM " + TABLE_USER + " WHERE Id = '" + sqlStrId + "' AND Password = '" + sqlStrPass + "'";
// クエリを実行
std::unique_ptr<sql::PreparedStatement> pstmt(m_con->prepareStatement(strSqlQuery));
std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());
CString strUserName = _T("");
BOOL bUserAuth = FALSE;
if (!res->next())
{
AfxMessageBox(_T("Idまたはパスワードが見当たらない"));
return FALSE;
}
else
{
// userテーブルに該当が存在した
std::string strCol = res->getString("Name"); // 名前列から名前取得
strUserName = strConvertFromUTF8ToUTF16(strCol); // 変換
int iAuth = res->getInt("Authority"); // 権限列から取得
if (iAuth == 1)
bUserAuth = TRUE;
//ログイン情報保持
CSupplyRequestManagerApp* pApp = static_cast<CSupplyRequestManagerApp*>(AfxGetApp());
pApp->SetUserId(strId); // ユーザID設定
pApp->SetUserName(strUserName); // ユーザ名設定
pApp->SetUserAuth(bUserAuth); // 管理者権限設定
}
}
catch (sql::SQLException& e)
{
// 実行できなかった
ErrSQLException(e);
return FALSE;
}
return TRUE;
}簡単に解説
- 15~16行目:エディットボックスで取得したIDとパスワードを、
前回作成した関数で型変換。 - 18~23行目:SQL文作成&クエリ実行。
- 27~30行目:userテーブルにそのIDとパスワードの組み合わせは存在しないようです。
- 34~39行目:存在したので、名前とIDを該当行から取得します。
- 42~45行目:メンバ変数にセットしています。(※)
- 48~53行目:どうやらtry文(基本的に21か23行目)でエラーが生じたようで。
※について。
AfxGetAppは、アプリケーション全体にアクセスする手段を提供し、
アプリケーションのライフタイムに渡って状態を保持したい場合に使います。
ここら辺は、もっと詳しく解説しているところがあると思うので…。
テーブルからデータを取得する処理が終わりました。
いよいよ、ログイン画面でこれらを使います。
Login.cppを開きます。
まずはヘッダーインクルード。
#include "MySQLManager.h"続いてOKボタンが押されたときの関数OnBnClickedOk内に処理を追加します。
/**
* @fn
* @brief OKボタン押下時の処理
* @param なし
* @return なし
*/
void CLogin::OnBnClickedOk()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
UpdateData(TRUE);
CMySQLManager Login;
Login.GetConnection(); //接続確立
if (Login.bCheckLogin(m_strLoginID, m_strLoginPassword))
{
CDialog::OnOK();
}
else
{
//何もしない
}
}エディットボックスから文字列を取得し、
MySQLManagerでログインチェックを行います。
最後に、ちゃんと該当のデータが取れているか確認します。
SupplyRequestManagerDlg.cppのOnInitDialogに、以下を追加します。
BOOL CSupplyRequestManagerDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
//略
// TODO: 初期化をここに追加します。
CStatic* pStatic = (CStatic*)GetDlgItem(IDC_STATIC_MAIN_WELCOME); //Welcomeスタティック
CSupplyRequestManagerApp* pApp = static_cast<CSupplyRequestManagerApp*>(AfxGetApp());
CString strMes = _T("Welcome! ") + pApp->strGetUserName(); // Welcome!○○の形
pStatic->SetWindowText(strMes);
if (pApp->bGetUserAuth() == FALSE)
{
// 一般ユーザの場合
// 申請承認ボタンは非表示
CButton* pButton = (CButton*)GetDlgItem(IDC_BUTTON_MAIN_APPROVAL);
pButton->ShowWindow(SW_HIDE);
// ユーザ情報管理ボタンは非表示
pButton = (CButton*)GetDlgItem(IDC_BUTTON_MAIN_USERLIST);
pButton->ShowWindow(SW_HIDE);
// 項目情報管理ボタンは非表示
pButton = (CButton*)GetDlgItem(IDC_BUTTON_MAIN_ITEMLIST);
pButton->ShowWindow(SW_HIDE);
SetWindowText(_T("物品購入システム")); //タイトル
}
else
{
SetWindowText(_T("物品購入システム(管理者用)")); //タイトル
}
return TRUE; // フォーカスをコントロールに設定した場合を除き、TRUE を返します。
}メイン画面のWelcomeにユーザ名が出てきます。
また、管理者権限がある場合(Authority列が1)は全ボタンが表示されますが、
一般ユーザの場合は申請ボタンだけ表示させます。
動作確認
さて、ビルドします。
ちょっとドキドキしています。
まずは普通に、テーブルに用意したIDとパスワードで試します。

すると

名前も取得でき、管理者であることが分かります。
今度は一般ユーザの方で。

これもよさそう。
さて、テーブルにないIDとパスワードを入れると


動いてますね(´▽`*)。
良かった良かった。
問題点
ちょっと動かして問題点を見つけたので。
IDが5桁未満の場合
IDが00000、パスワードが12345では当然ログインできます。
ところがIDを0にしてもログインできたんですよね。
Id列がint型ですからね。
対応としては
- テーブルの列をvarcharに変更する
→文字列としてみてくれるので、0と00000は別物 - エディットボックスに制御をかける
5桁未満の場合はSQLの実行処理へ行かない、など。
2の方が実際の修正としては現実的なので、制御かけます。
Login.cpp内で。
void CLogin::OnBnClickedOk()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
UpdateData(TRUE);
if (m_strLoginID.GetLength() < 5)
{
AfxMessageBox(_T("ログインIDは5桁で入力してください。"));
return;
}
CMySQLManager Login;
Login.GetConnection(); //接続確立
if (Login.bCheckLogin(m_strLoginID, m_strLoginPassword))
{
CDialog::OnOK();
}
else
{
//何もしない
}
}ログインIDが5桁未満の場合は抜ける処理を追加です。
これで、IDが「0000」と入力されても6行目で引っかかって、
テーブルに見に行く処理が為されません。
終わりに
今回はユーザテーブルからログインを決定する処理を作りました。
ログイン機能の処理自体はほぼ終わりですが、
パスワードを生のままで保存するのはセキュリティ上よろしくないので、
次回以降ハッシュ化関数を作ります。
今回はここまで。

コメント