今回は、GAS (Google Apps Script) を使って、認証機能を付けた簡単なログイン画面を作ってみます。ログイン画面(login.html)から入力したemailアドレスとパスワードが、スプレッドシートの「社員ログイン情報」ファイルに記載されたemail(ログインID)とパスワードに一致すれば、「こんにちは!」(index.html)を表示して、不一致であれば「アクセス権がありません。」(error.html)と表示して、ログイン画面に戻ります。
注意:
ログイン画面のレイアウトはCSSは使用せず、bootstrapで作成しています。ここでは、Bootstrapの使い方については説明していませんので、必要な場合はネット等で検索して下さい。
「社員ログイン情報」ファイルのスプレッドシートの作り方は、以下のブログを参照下さい。
GAS(Google Apps Script)については、以下のブログを参照下さい。
gas ログイン認証の仕様
ログイン画面
アプリを起動してログイン画面から、emailアドレスとパスワードを入力します。
emailとパスワードが一致した場合
入力されたemailアドレスとパスワードで、スプレッドシート:社員ログイン情報に記載されているemailアドレスとパスワードと比較して一致した場合は、以下の様に表示します。
emailとパスワードが不一致の場合
emailアドレスとパスワードが一致しなかった場合は、以下のように表示して、「ログイン画面に戻る」をクリックすると、「ログイン画面」に戻ります。
スクリプトの作成に必要なもの
スプレッドシート(社員ログイン情報)
予め、以下のスプレッドシートを用意します。ログインの為のホワイトリストとなります。
作成するGASスクリプトとHTML
コード.gs
doGet関数、doPost関数、ninsyou関数を作成します。
login.html
emailアドレスとパスワードを入力するログイン画面を作成します。
index.html
emailとパスワードが一致した場合に表示する画面を作成します。
error.html
emailとパスワードが不一致の場合に表示する画面を作成します。
gas ログイン認証のスクリプトの作成
doGet関数の実装
まずはスプレッドシートを操作する為に、スプレッドシートのオブジェクトを取得します。
ここでは次の5つの処理を行います。
htmlファイルを生成
Webブラウザで表示するにはhtmlファイルが必要で、生成処理もdoGetで行います。
const htmlOutput = HtmlService.createTemplateFromFile(“login”);
htmlのファイル名は「login.html」とすることにします。この場合は文字列”login”を、HtmlServiceのcreateTemplateFromFileというメソッドに指定します。
最新のデプロイURLの反映
login.htmlのform actionにURLを貼り付けるとデプロイの度に、その時点でのデプロイURLに変化してしまいます。そこでこれを解決するために、デプロイURLを変数化してformタグに反映する必要があります。次の1行を追加します。
htmlOutput.deployURL = ScriptApp.getService().getUrl();
そして、login.htmlのactionは、以下のようにします。
HtmlOutputオブジェクトへの変換
HtmlServiceオブジェクトのメソッドであるcreateTemplateFromFileは、指定のhtmlファイルからHtmlTemplateオブジェクトを生成するメソッドです。そこでhtmlOutput.evaluate()で、HtmlTemplateオブジェクトをevaluate(評価)することでHtmlOutputという形式のオブジェクトに変換しています。変換されたHtmlOutputオブジェクトはブラウザで表示ができる状態となります。
留意:
evaluate()とはHtmlTemplateオブジェクトをHtmlOutputオブジェクトに変換するメソッドです。HtmlOutputオブジェクトに変換することでWebページを表示できるようになります。
タイトルの設定
通常ブラウザで開いたWebページのタブには、そのページのアイコン(ファビコン)と、タイトルが表示されますが、GASで作ったページの場合は、Apps ScriptのアイコンとURLがそのまま表示されます。そこでhtmlOutput.setTitle(“ログイン画面”)でタイトルを設定します。
スマホ対応
Webページをスマホ対応する為に、headタグ内にviewportの設定をmetaタグで指定します。
HtmlOutputオブジェクト.addMetaTag(name属性の値, content属性の値)
htmlOutput.addMetaTag(‘viewport’, ‘width=device-width, initial-scale=1’);
width=device-width:表示領域の幅を端末画面の幅に合わせる
initial-scale=1:初期のズームの倍率を1、つまり拡縮なしに設定しておく
doPost関数の実装
入力されたemailアドレスと、パスワードの取得
const email = e.parameters.email.toString();
const password = e.parameters.password.toString();
doGetはデプロイしたURLにアクセスしたときに(GETリクエストした時に)実行され、doPostはフォームの送信ボタンが押されたときに(POSTリクエストした時に)実行されます。
ninsyou関数の呼び出しと、チェック結果の取得
const check = ninsyou(email,password);
ninsyou関数を呼び出し、チェック結果を変数checkに格納します。
チェック結果による画面の切り替え
formの送信ボタンが押下されて、チェック結果によりindex.htmlかerror.htmlを表示します。
if ( check === true ) {
emailをindex.html(スクリプトレット)へ送り、最初の画面(index.html)を表示します。
} else {
エラー画面(error.html)を表示します。
}
ninsyou関数の実装
doPost関数から呼び出されるninsyou関数を実装します。
スプレッドシート:社員ログイン情報と、emailとパスワードが一致するかをチェックして、一致していれば、trueを返し、不一致であればfalseを返します。
「社員ログイン情報」のシートの取得
スプレッドシートの「社員ログイン情報」ファイルの該当シート(シート1)を取得します。
const sheets = SpreadsheetApp.openByID(“ID”);
const sheet = sheets.getSheetByName(“シート1”);
シート内のセルの取得
取得する範囲の開始セルを指定して、そこから何行分、何列分取り出すかを指定します。
const ninsyou_email = sheet.getRange(2,3,3,1).getValues();
const ninsyou_pass = sheet.getRange(2,4,3,1).getValues();
例えば、emailの場合は、開始セルが2行目の3列で、そこから3行分、1列分を取り出しています。つまり、info@gungii.com、hello@kaithuburi.net、info@gungii.siteの3つのemailアドレスを取得しています。
[ 最終行を自動で判別して取得する。]
最終行を自動で取得して、次のように書き換えることもできます。
const ninsyou_email = sheet.getRange(2,3,sheet.getLastRow(),1).getValues();
const ninsyou_pass = sheet.getRange(2,4,sheet.getLastRow(),1).getValues();
email、パスワードのチェック
ninsyou_emailの要素数(ここでは3つ)だけ繰り返します。つまり、emailアドレスが3つありますので3回繰り返し、変数iを0、1、2と更新します。for inではiのところに配列のindexが返ってきます。例えば、入力されたemailアドレスがinfo@gungii.siteで、パスワードがpas54321の場合、変数iが2の時に、ninsyou_email[2]とemail(入力されたemailアドレス)且つ、ninsyou_pass[2]とpassword(入力されたパスワード) が一致しますので、hanteiにtrueを代入してreturnで戻ります。
留意:
for in文はオブジェクト(連想配列)のデータからキー要素を順不同で取得して、繰り返し処理を実行します。定義された順番にオブジェクトのキーが取り出されるかは保証されていませんので、配列のデータ処理には適していません。このケースの場合配列は関係なくtrueかfalseかのみですので、問題ありませんが配列が必要な場合は、for ofを使うことが必要です。
ninsyou_email = sheet.getRange(2,3,3,1).getValues();には、次のような二次元配列となっています。
gas ログイン認証のHTMLの作成
login.htmlの作成
CSSとJavascripのCDNを挿入
Bootstrapより、CSSとJavascripのCDN(コンテンツデリバリーネットワーク)を挿入します。CSSは、headの適当な場所に挿入してよいですが、Javascriptは、bodyの最後に挿入して下さい。
formの編集
Bootstrapから最も近いformを選択して、htmlを編集しています。
index.htmlの作成
Bootstrapより、CSSとJavascripのCDN(コンテンツデリバリーネットワーク)を挿入します。CSSは、headの適当な場所に挿入してよいですが、Javascriptは、bodyの最後に挿入して下さい。
注意:login.htmlと同様、index.htmlにもCSSとJavascriptのCDNを挿入します。
error.htmlの作成
CSSとJavascripのCDNを挿入
Bootstrapより、CSSとJavascripのCDN(コンテンツデリバリーネットワーク)を挿入します。CSSは、headの適当な場所に挿入してよいですが、Javascriptは、bodyの最後に挿入して下さい。
「ログイン画面」に戻る
「ログイン画面に戻る」をクリックすると、ログイン画面(初期画面)に戻るようにします。
error.htmlの修正
次の1行を追加します。
コード.gsの修正
次の1行を追加します。
index.htmlの方も追加していますが、次の画面(例えば、社員情報の表示や雇用契約書の表示etc)が決まっていませんので、現状は使っていません。
スクリプトレットの解説
スクリプトレットとは
GASでは「スクリプトレットタグ」を使うことで”gsコードからHTMLに変数を渡したり、”HTML内にgsコードを埋め込んだ”りすることができます。HTML内で、(スクリプトレットタグ)で囲まれた部分はgsコードとして実行することができます。GASにおけるスクリプトレットは3種類あり、やりたいことによって使い分けます。
スクリプトレットは、doPost関数内のevaluateメソッドによって実行されます。つまり、サーバーからHTTPレスポンスが送出される直前のタイミングで実行され、結果のHTML(今回の例ではoption要素)が送信されます。GASのスクリプトが実行されるのはあくまでサーバー側となります。
スクリプトレットの使い方
上記の例では、doGet関数内でHtmlService.createTemplateFromFileメソッドを使用してHTMLファイルを読み込んでいます。このHTMLファイル内にスクリプトレットを使用することができます。template変数にyoukenプロパティを追加して、”GASを学ぼう”を代入しています。そしてreturn文でtemplate.evaluateメソッドを呼び出して、評価結果を返しています。この評価結果がクライアントに送信されるHTMLページとなります。
function doGet() {
let template = HtmlService.createTemplateFromFile(“index”);
template.youken = “GASを学ぼう”;
return template.evaluate().setTitle(template.youken);
}
HTMLファイル内では、次のようにスクリプトレットを使用することができます。
template.(HTML側で定義されている変数名) = (gsコード側で代入したい変数名)
実際の使い方
function doPost(e) {
・
template = HtmlService.createTemplateFromFile(“index”);
template.namae = email;
return template.evaluate();
・
}
上記の例では、doPost関数内でHtmlService.createTemplateFromFileメソッドを使用してHTMLファイルを読み込んでいます。このHTMLファイル内にスクリプトレットを使用することができます。template変数にnamaeプロパティを追加して、emailを代入しています。そしてreturn文でtemplate.evaluateメソッドを呼び出して、評価結果を返しています。この評価結果がクライアントに送信されるHTMLページとなります。