サーバーサイドJavaScript CGJSフレームワーク
CGIの起動、I/Fと外部認証

Front部のJavaScriptからCGIへの接続I/F関数は2種類あります。
一つは通常のCGI起動のI/F関数で、これはLinux/Windowsで共通ですが、もう一つの認証CGIとのI/Fは、
shell、batの仕様の違いや、子プロセス起動のパーミッション等により、Linux/Windowsで異なります。
以下にI/Fの仕様、パラメータを説明しますが、具体的な例は「デモアプリ」のページを参照してください。
1. 通常CGIとのI/F    2. 認証CGIとのI/F    2.1  Linuxの認証    2.2  Windowsの認証
1.通常CGIとのI/F
  通常のI/Fの場合、Front部 cgjs.js で以下の CGJS.cgjs_if 関数を使用します。
■ CGJS.cgjs_if
形式 CGJS.cgjs_if(recv_obj, send_obj);
引数 recv_obj ■ 同期処理
 CGIの処理結果を受け取る連想配列(Hash)。
 最初の引数が連想配列の場合、cgjs_ifはCGIの処理が終わるの待つて、
 結果をrecv_objに設定する。
  recv_obj.CGI_CODE  :CGIの終了コード。正常終了は0。
  recv_obj.CGI_MESSAGE:CGIのエラーメッセージ。正常終了は空の文字列。
  recv_obj.CGI_OBJ    :CGIからの転送ObjectのHash
■ 非同期処理
 CGIの処理結果を処理するCallBack関数名を設定する。
 関数の定義・引数は以下の通りですが、引数の値は同期処理の場合と同じです。
  function recv_obj(CGI_CODE, CGI_MESSAGE, CGI_OBJ) { ... }
send_obj CGIに渡すGLOBAL変数のパラメータや、制御用のパラメータを定義した
連想配列(Hash)。以下の内部処理用のキーワードを参照
戻り値 CGIを起動した結果のエラーメッセージ。正常終了の場合空の文字列。
I/F関数 CGJS.cgjs_if の第2引数(send_obj)のキーで、以下の名称はCGJS内部処理用のキーワードです。
下記以外のその他のキー・値は、Back Endにキーを名称としたGlobal変数として値が設定されます。

■ CGJS内部処理用のキーワード
log_file ログファイル名を指定します。アプリ開発時に多数の開発者が同じログファイルを使用すると
不便なので、一時的にFront部で別のログファイルを指定します。
ログファイルのディレクトリはCGJS.configで定義されたログファイルと同じで、変更できません。
execute
※必須
実行するモジュールの中から、TOPで実行する関数、引数をJavaScript Statementの
文字列 "func_name(arg1, arg2, ...);" で指定する。
cgi 実行するCGI(CGJS.cgi、CGJS.exe、debugCGJS.cgi、debugCGJS.exe)を指定します。
指定がないとcgjs.jsファイルに設定されたCGIが実行されます。
一時的にデバッグ用のCGIを実行したい時に指定します。指定するのはファイル名だけで、
ディレクトリは/cgi-bin/配下で、変更できません。
include Back Endで実行するモジュールを指定します。カンマ区切りで複数指定可能(指定順にLOADされる)。
モジュールが拡張子なしで指定された場合、ソースファイル(.js)とコンパイルされたObjectファイル
(.jo)を比較し、TimeStampが新しいほうがLOADされます。
CGJS.configファイルで指定された共通モジュールは、include指定のモジュールより先にLOADされます。
timeout Ajaxのタイムアウト時間(秒)を指定します。アプリ開発中で、デバッガーでステップ実行する時に
タイムアウトしないよう長く設定します。
Apache2 等ブラウザーのTimeOutも長い時間に設定してください。
■ GLOBAL変数の設定順
Global変数はどこからでも参照・設定できるので、名称が重複した場合は後勝ちで上書きされます。
Global変数の設定順序は以下のようになりますので、名称が重複する場合は注意をしてください。

  ① CGJS.config ファイルにVARで定義したGlobal変数の設定
  ② Frontから CGJS.cgjs_if で渡されたGlobal変数の設定
  ③ CGJS.config ファイルにINCLUDEで指定したモジュール内のGlobal変数の設定(モジュール順)
  ④ Frontの CGJS.cgjs_if 引数の include で指定したモジュール内のGlobal変数の設定(モジュール順)
  ⑤ Back EndのJavaScript実行でのGlobal変数の設定

以下に、Front部からGlobal変数の渡し方、Back Endでの参照方法の例を示します。
■ Front部で変数をまとめて渡す例
// Front部のJavaScript
function show_list() {
 let send_obj = {
  arg: {
   "Prefecture": $('#Prefecture').val(),
   "sel_sex": $('#sel_sex').val(),
   "sel_age": $('#sel_age').val(),
  },

  include:"get_pref_list",
  execute:"get_pref_list(arg);",
  timeout: 1000000,
 }
 let obj = { };
 let ret = CGJS.cgjs_if(obj, send_obj);
 ・・・・・・・・・・
}

// --------------------------------------------------------------
// Back EndのTOP関数
function get_pref_list(arg) {
 ・・・・・・・・・・
 // 都道府県の条件を作成
 let pref_code = arg.Prefecture;
 ・・・・・・・・・・
 // 年齢別の条件を作成
 let age_code = arg.sel_age;
 ・・・・・・・・・・
 // 男女別の条件を作成
 let sex_code = arg.sel_sex;
 ・・・・・・・・・・
}
■ Front部で変数をバラバラ渡す例
// Front部のJavaScript
function show_list() {
 let send_obj = {
  "Prefecture": $('#Prefecture').val(),
  "sel_sex": $('#sel_sex').val(),
  "sel_age": $('#sel_age').val(),

  include:"get_pref_list",
  execute:"get_pref_list();",
  timeout: 1000000,
 }
 let obj = { };
 let ret = CGJS.cgjs_if(obj, send_obj);
 ・・・・・・・・・・
}
// --------------------------------------------------------------
// Back EndのTOP関数
function get_pref_list() {
 ・・・・・・・・・・
 // 都道府県の条件を作成
 let pref_code = Prefecture;
 ・・・・・・・・・・
 // 年齢別の条件を作成
 let age_code = sel_age;
 ・・・・・・・・・・
 // 男女別の条件を作成
 let sex_code = sel_sex;
 ・・・・・・・・・・
}
Back EndのTOP関数に引数を渡さずに直接FrontからのGlobal変数を参照することもできますが、
処理をわかりやすくするためにも引数をHashで渡して参照してください。
2.認証CGIとのI/F
  データベースを使用してID、PASSWORDの認証チェックはBack EndのJavaScriptでもできますが、
LDAP認証等はできません。
また、トークン認証用のトークンをFrontに返す事もBack EndのJavaScriptではできません。
LDAP認証やトークン認証を可能にするため、他のCGIで認証実行後、CGJSのCGIを実行して
トークンをFrontに返します。
  CGJS.configファイルに認証キー名称、タイムアウト時間の定義をすれば、外部CGIでの認証後、
AjaxでCGJS CGIを起動すれば、トークンの認証、リフレッシュ、タイムアウトチェックはCGJS内の
IFで自動的に行われます。
  CGJSではFront部でトークンの保存にSession変数を使用するだけで、Session変数そのものを
Back Endと送受信はしません。また、CGJSではクッキーは使用しません。
アプリでクッキー、Sessionの情報をBack Endと送受信したい場合は、
FrontのJavaScriptでCGIとの送受信データとして記述してください。

  認証の場合、Front部 cgjs.js で以下の CGJS.cgjs_login I/F関数を使用します。
■ CGJS.cgjs_login
形式 CGJS.cgjs_login(recv_obj, send_obj, os_type);
引数 recv_obj CGIの処理結果を受け取る連想配列(Hash)。
最初の引数が連想配列の場合、cgjs_ifはCGIの処理が終わるの待つて、結果をrecv_objに設定する。
 recv_obj.CGI_CODE  :CGIの終了コード。正常終了は0。
 recv_obj.CGI_MESSAGE:CGIのエラーメッセージ。正常終了は空の文字列。
 recv_obj.CGI_OBJ    :CGIからの転送ObjectのHash
send_obj CGIに渡すGLOBAL変数のパラメータや、制御用のパラメータを定義した連想配列(Hash)
os_type OSがWindowsかLinuxかを指定する文字
OSがWindowsの場合'W'を、Linuxの場合'L'を指定する。
戻り値 CGIを起動した結果のエラーメッセージ。正常終了の場合空の文字列。
連想配列 send_obj のキーは以下の3つだけです。
認証プログラムに渡すパラメータは、コマンドラインに文字列として渡します。
execute
※必須
実行するモジュールの中から、TOPで実行する関数、引数を指定する。
include Back Endで実行するモジュールを指定します。カンマ区切りで複数指定可能(指定順にLOADされる)。
モジュールが拡張子なしで指定された場合、ソースファイル(.js)とコンパイルされたObjectファイル
(.jo)を比較し、TimeStampが新しいほうがLOADされます。
CGJS.configファイルで指定された共通モジュールは、include指定のモジュールより先にLOADされます。
command
※必須
認証プログラムのコマンドライン文字列を指定する。プログラムのディレクトリはCGJS CGIと同じで、
/cgi-bin/から変更できません。
(例 Linux:"auth_check.sh ID_str PASS_str" Windows:"check_login.bat ID_str PASS_str")
  以下に外部のCGIで認証を行い、認証で取得したLogin Userの会社、本部、部室、氏名をFrontに返すデモの例を
Linux、Windowsに分けて説明します。
2.1  Linuxの認証
  Linuxの認証処理の例として、デモアプリの認証画面でID、PASSWORDを入力後、ログインボタンの押下イベントを
処理するJavaScriptを以下に示します。
Front部の認証I/F関数 CGJS.cgjs_login で Back Endに渡すパラメータは以下の3つです。
  ① 認証プログラムのコマンドライン(4行目)。ID、PASSWORDはFORMから取得して文字列にします。
  ② Back Endのモジュール(5行目)
  ③ 実行するTOP関数(6行目)
認証プログラム(auth_check.sh)は、CGJS CGIのディレクトリ(cgi-bin)に配置してください。また、CGJSで実行可能な
プログラムとして、CGJS.config ファイルに以下のように登録してください。(複数ある場合はCSV形式)
  CGI_PROGRAMS=user_login.exe,check_login.bat,auth_check.sh
処理の順番は、まず最初にI/Fのシェル authorize.sh 経由で auth_check.sh が実行されて認証が行われます。
認証プログラムは結果と付随するパラメータを標準出力(stdout)に出力してください。
それを入力にしてCGJS CGIで指定のモジュールのTOP関数が実行されます。
■ Front部のJavaScript
// ログインのボタン押下イベント
function check_data() {
let send_obj = {
  command:'auth_check.sh ' + $('#id').val() + ' ' + $('#pass').val(),     // 認証のコマンドライン
  include:"demo_module/check_login.js",     // 実行するモジュール
  execute:"check_login()",                // 実行するTOP関数
}
let obj = { };
let ret = CGJS.cgjs_login(obj, send_obj, 'L');    // 'L'はLinux
if (ret != "") {
  alert(ret);               // Ajaxで認証CGI起動エラー
  return;
}
if (obj.CGI_CODE != 0) {
  alert(obj.CGI_MESSAGE);   // 認証CGIの後に起動されたCGJS CGIのエラー
  return;
}
if (obj.CGI_OBJ.RESULT != 1) {
  alert("認証エラー");      // 認証でのエラー
  return;
}
sessionStorage.removeItem("company");         // 認証結果のsession変数を一旦クリア
sessionStorage.removeItem("division");
sessionStorage.removeItem("department");
sessionStorage.removeItem("user_mame");
let tmp = obj.CGI_OBJ.COMPANY;
if (tmp)
  sessionStorage.setItem("company", tmp);     // 会社名を設定
tmp = obj.CGI_OBJ.DIVISION;
if (tmp)
  sessionStorage.setItem("division", tmp);    // 本部名を設定
tmp = obj.CGI_OBJ.DEPARTMENT;
if (tmp)
  sessionStorage.setItem("department", tmp);  // 部室名を設定
tmp = obj.CGI_OBJ.NAME;
if (tmp)
  sessionStorage.setItem("user_mame", tmp);   // ログインユーザの氏名
location.href = "population.html";            // 認証後のページに遷移
return;
}
  ユーザーが作成する認証プログラムの例として、シェルで作成したものを以下に示します。
実際にはLDAPの認証プログラム等が使用されます。入力のID、PASSWORDを判定して、結果をRESULTの変数に設定し、
付随する所属の情報と共に標準出力に出力します。
認証結果の変数 RESULT には以下の値を設定してください。認証失敗の場合は設定しないでください。
■Ajax<--->CGJS CGI間にトークン認証を使用する場合
  成功:RESULT=[CGJS.configに定義してるTOKEN_KEYの文字列];
■Ajax<--->CGJS CGI間にトークン認証を使用しない場合
  成功:RESULT=1;
RESULTはCGJS CGIで認証後の処理を行うかどうかの判定で使用します。
その他の会社名、本部名、部室名、氏名は、NAME=VALUEの形式でセミコロン(;)で区切ってください。
上記のパラメータ群は、改行なしの文字列として標準出力(stdout)に出力してください。
■認証プログラムのサンプル
 #!/bin/sh
# 引数のID、PASSWORDをチェックする
if [ "$1" = "CGJS" -a "$2" = "TEST" ]; then
# 認証成功の文字列を出力
STR="RESULT=CGJS;MESSAGE=認証に成功しました"
STR="${STR};COMPANY=テスト株式会社;DIVISION=テスト本部;DEPARTMENT=テスト第三部"
echo "${STR};NAME=試験 太郎"
else
# 認証失敗の文字列を出力
echo "RESULT=0;MESSAGE=認証に失敗しました"
fi
exit 0
  Back Endの関数check_loginが実行されるのは、CGJS CGIに渡された認証結果が成功の場合だけで、
失敗の場合はメッセージをFrontにかえして、処理を終了します。
check_loginの処理は、認証結果と付属情報をFront部に返す事と、トークンをリフレッシュする事です。
下記の例は会社名、本部名、部室名、氏名をFrontに転送しています。
Frontに転送するデータがない場合でも、トークンをリフレッシュするためにダミーのモジュール、TOP関数は必要です。
■認証後のBack End JavaScript
 // 認証後の処理(check_login.js)
function check_login() {
// フロントに結果を転送する
sendToFront('RESULT', 1);
sendToFront(COMPANY);
sendToFront(DIVISION);
sendToFront(DEPARTMENT);
sendToFront(NAME);
}
2.2  Windowsの認証
Windowsの認証処理の例として、デモアプリの認証画面でID、PASSWORDを入力後、ログインボタンの押下イベントを
処理するJavaScriptを以下に示します。
Front部の認証I/F関数 CGJS.cgjs_login で Back Endに渡すパラメータは以下の3つです。
  ① 認証プログラムのコマンドライン(4行目)。ID、PASSWORDはFORMから取得して文字列にします。
  ② Back Endのモジュール(5行目)
  ③ 実行するTOP関数(6行目)
認証プログラム(check_login.bat)は、CGJS CGIのディレクトリ(cgi-bin)に配置します。
また認証プログラムは、CGJS.config ファイルに以下のCSV形式で実行可能なプログラムとして設定しなければなりません。
  CGI_PROGRAMS=user_login.exe,check_login.bat,test_login.bat
処理の順番は、まず最初に認証プログラムのコマンドラインを実行し、その標準出力を入力にして
CGJS CGI(②指定のモジュール、③指定のTOP関数)が実行されます。
TOP関数は、CGJS.configファイルにTOKEN_KEYが設定されていれば、トークン認証・リフレッシュを開始し、
認証結果をFront部に転送します。
■ Front部のJavaScript
 // ログインのボタン押下イベント
function check_data() {
let send_obj = {
  command:'check_login.bat ' + $('#id').val() + ' ' + $('#pass').val(),  // 認証コマンドライン
  include:"demo_module/check_login.js",     // 実行するモジュール
  execute:"check_login()",                // 実行するTOP関数
}
let obj = { };
let ret = CGJS.cgjs_login(obj, send_obj, 'W');    // 'W'はWindows
if (ret != "") {
  alert(ret);                 // Ajaxで認証CGI起動エラー
  return;
}
if (obj.CGI_CODE != 0) {
  alert(obj.CGI_MESSAGE);     // 認証CGIの後に起動されたCGJS CGIのエラー
  return;
}
if (obj.CGI_OBJ.RESULT != 1) {
  alert("認証エラー");        // 認証でのエラー
  return;
}
// 認証結果のsession変数を一旦クリア
sessionStorage.removeItem("company");
sessionStorage.removeItem("division");
sessionStorage.removeItem("department");
sessionStorage.removeItem("user_mame");
let tmp = obj.CGI_OBJ.COMPANY;
if (tmp)
  sessionStorage.setItem("company", tmp);     // 会社名を設定
tmp = obj.CGI_OBJ.DIVISION;
if (tmp)
  sessionStorage.setItem("division", tmp);    // 本部名を設定
tmp = obj.CGI_OBJ.DEPARTMENT;
if (tmp)
  sessionStorage.setItem("department", tmp);  // 部室名を設定
tmp = obj.CGI_OBJ.NAME;
if (tmp)
  sessionStorage.setItem("user_mame", tmp);   // ログインユーザの氏名
location.href = "population.html";            // 認証後の人口検索ページに遷移
return;
}
  ユーザーが作成する認証プログラムの例としてBATで作成したものを以下に示します。
実際にはLDAPの認証プログラム等が使用されます。入力のID、PASSWORDを判定して、結果をRESULTの変数に設定し、
付随する所属の情報と共に標準出力に出力します。
認証結果の変数 RESULT には以下の値を設定してください。失敗の場合は設定しなくてもよい。
■Ajax・CGJS CGI間にトークン認証を使用する場合
  成功:RESULT=[CGJS.configに定義してるTOKEN_KEYの文字列];
  失敗:RESULT=0;
■Ajax・CGJS CGI間にトークン認証を使用しない場合
  成功:RESULT=1;
  失敗:RESULT=0;
RESULTはCGJS CGIで認証後の処理を行うかどうかの判定で使用します。
その他の会社名、本部名、部室名、氏名は、NAME=VALUEの形式でセミコロン(;)で区切ってください。
上記のパラメータ群は、改行なしの文字列として標準出力(stdout)に出力してください。
■認証プログラムのサンプル
  @echo off
setlocal enabledelayedexpansion
cd %~dp0

set VAL=FALSE
if "%1"=="CGJS" if "%2"=="TEST" set VAL=TRUE
if %VAL%==TRUE (
set STR=RESULT=CGJS;MESSAGE=Login-Success
set STR=!STR!;COMPANY=TEST-LTC;DIVISION=DEVELOP-DIV;DEPARTMENT=Devlop-3
echo !STR!;NAME=TEST-TARO
) else (
echo MESSAGE=Login-Failed
)
exit /b 0
■認証後のBack End JavaScript
 // 認証後の処理(check_login.js)
function check_login() {
// フロントに結果を転送する
sendToFront('RESULT', 1);
sendToFront(COMPANY);
sendToFront('DIVISION', DIVISION);
sendToFront(DEPARTMENT);
sendToFront(NAME);
}
  Back Endの関数check_loginが実行されるのは、CGJS CGIに渡された認証結果が成功の場合だけで、
失敗の場合はメッセージをFrontにかえして、処理を終了します。
check_loginの処理は、認証結果と付属情報をFront部に返す事と、トークンをリフレッシュする事です。
下記の例は会社名、本部名、部室名、氏名をFrontに転送しています。
Frontに転送するデータがない場合でも、トークンをリフレッシュするためにダミーのモジュール、TOP関数は必要です。