見出し画像

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を導入すれば、安価にサービス構築もできます。

いいなと思ったら応援しよう!