Webアプリで電子カードを使った認証処理-2(No.061)
前回に引き続き、電子カード(非接触)を使った認証処理を実装する続きです。前回は、Webサーバからの要求で、C#アプリがカードリーダを読み、結果をWebサーバに返す機能を紹介しましたが、今回は、Webサーバ(PHP言語)側の処理です。画面(Webixを使ったJavascript画面)は、次回にします。
PHPからは、curlコマンドでC#アプリが動作しているWindowsOSのPCに8082ポートを使用してhttpリクエストを出します。
C#のアプリは、カード情報が読めると、その情報と改行コード
読めない(タイムアウト含む)場合は、改行コードだけを返すので、PHP側で応答をチェックし、UIには、JSON形式の応答を返します。
今回、画面をまだ実装していないので、Postmanで画面からのリクエスト出して、結果を確認します。
正常応答時には、以下のようにJSONデータを返します。
infoに値が入ります。(一部、情報をカットしていますが)
カードを置かない(読めない)場合は、以下のようになります。
infoが空欄です。
実際の画面では、カード情報をJavascriptからPHPにリクエストを出して読出し、その情報でDBを検索して一致する場合、認証OKを返すような動作となります。次回には、そのあたり実装を紹介します。
PHPのソースコードです。NF0010_cared_read.php
<?php
//======================================================================
//File Name : NF0010_cared_read.php
//Encoding : UTF-8
//Creation Date : 2024-08-28
//
//Copyright © 2024 sunsunfarm. All rights reserved.
//
//This source code or any portion thereof must not be
//reproduced or used in any manner whatsoever.
//======================================================================
header("Content-Type: text/javascript; charset=utf-8");
$myfilename = basename(__FILE__); //自分自身のファイル名取得
$userid = '';
$logheader = 'userid='.$userid.', '.$myfilename.':';//ログ出力時のヘッダー情報(自ファイル名,ログインIDを付与)
if($_SERVER["REQUEST_METHOD"] != "GET"){
error_log($logheader.' not GET method');
header("HTTP/1.0 404 Not Found");
return;
}
//指定パラメータでUPDATEする
//GET情報からパラメータ取得
$accesskey = 0;
//if(isset($_GET['accesskey'])){
// if(is_numeric($_GET['accesskey'])){
// $accesskey = $_GET['accesskey'];
// $error_flag = 1;
// }
//}
//else{
// $error_flag = -1;
// error_log($logheader.' accesskey not found');
// header("HTTP/1.0 404 Not Found");
// exit;
//}
if(isset($_GET['userid'])){
$userid = $_GET['userid'];
$error_flag = 1;
}
else{
$error_flag = -1;
error_log($logheader.' userid not found');
header("HTTP/1.0 404 Not Found");
exit;
}
$job_info = "NF0010";
if(isset($_GET['job_info'])){
$job_info = $_GET['job_info'];
}
$logheader = 'userid='.$userid.', '.$myfilename.':';//ログ出力時のヘッダー情報(自ファイル名,ログインIDを付与)
include('../../commonlib/svr_common_lib_v2.php'); //
$config_obj = get_config_obj();
$NFC_serve_ip = $config_obj::get('app01.NFC_server'); //NFCカードリーダPCのIPアドレス
$NFC_serve_port= $config_obj::get('app01.NFC_serve_port'); //NFCカードリーダURLのポート番号(8082)
//アクセスキーチェック
//if(Chk_AccessKey($accesskey)){
//}
//else{
// error_log($logheader.' accesskey check error');
// header("HTTP/1.0 404 Not Found");
// exit;
//}
/**
* curl でGET通信を行う
*
* @param [string] $url - 'http://example.com/'
* @return [string|boolean] - 成功: 取得結果, 失敗: false
*/
function sendGetRequest($logheader,$url){
$option = [
CURLOPT_RETURNTRANSFER => true, // 文字列として返す
CURLOPT_TIMEOUT => 12000, // タイムアウト時間
CURLOPT_SSL_VERIFYPEER => false, // サーバ証明書の検証をしない
];
// curl初期化
$ch = curl_init($url);
curl_setopt_array($ch, $option);
$body = str_replace(PHP_EOL, '', curl_exec($ch)); //改行カット
$info = curl_getinfo($ch);
$errorNo = curl_errno($ch);
$errorMsg = curl_error($ch);
$resp = array();
// 「CURLE_OK」以外はエラーなのでエラー情報を返す
if ($errorNo !== CURLE_OK) {
// 詳しくエラーハンドリングしたい場合はerrorNoで確認
// タイムアウトの場合はCURLE_OPERATION_TIMEDOUT
$resp["resp"] = "ng";
error_log($logheader.' $errorNo='.$errorNo.' Msg='.$errorMsg);
$resp["error_code"] = $errorNo;
$resp["error_mess"] = $errorMsg;
return $resp;
}
// 200以外のステータスコードは失敗なのでそのステータスコードを返す
if ($info['http_code'] !== 200) {
$resp["resp"] = "ng";
error_log($logheader.' http_code='.$info['http_code']);
$resp["error_code"] = $info['http_code'];
$resp["error_mess"] = "http error";
return $resp;
}
else{
$resp["resp"] = "ok";
$resp["error_code"] = 0;
$resp["error_mess"] = "";
error_log($logheader.' body='.$body);
$resp["info"] = $body;
return $resp;
}
}
//
//メインルーチン
//
try{
$url = 'http://'.$NFC_serve_ip.':'.$NFC_serve_port.'/';
error_log($logheader.' url=:'.$url);
//NFCカード読出し
$rs = sendGetRequest($logheader,$url);
if($rs["resp"] != "ok"){
error_log($logheader.' sendGetRequest error rs='.$rs["error_code"]);
$resp = "ng";
$error_code = $rs["error_code"];
$json_data = json_encode(compact("resp","error_code"),JSON_UNESCAPED_UNICODE);
echo $json_data;
exit;
}
else{
$resp = "ok";
$error_code = 0;
$info = $rs["info"];
$json_data = json_encode(compact("resp","error_code","info"),JSON_UNESCAPED_UNICODE);
echo $json_data;
exit;
}
} catch(PDOException $e){
error_log($logheader.' 捕捉した例外: '.$e->getMessage()); //例外発生時の処理(エラー情報をログに格納してエラー応答)
$resp = "ng";
$error_code = -1;
}
$json_data = json_encode(compact("resp","error_code"),JSON_UNESCAPED_UNICODE);
echo $json_data;
?>
前回のC#アプリの実装と今回のPHPソースで、UIからの要求でカード情報を読み出すことが可能となります。動作環境がすこし、大変ですが、割と簡単に機能を構築できます。
尚、C#アプリが実装されるPCでは、ポート8082を通すファイヤウォールの設定とC#アプリを管理者権限で動かす必要があります。
ログイン認証や、タイムカード(出勤、退勤などの時刻記録)も可能ですし、カードリーダを接続したPC上でブラウザでUIを動かせば、カードリーダを連携したいろいろな機能も構築できます。(タイムカードや、出勤時に昼食ランチの予約なども)
タッチが可能なタブレットPCを導入すれば、安価にサービス構築もできます。