この記事はで読むことができます。
Contents
はじめに
GASで作成したWebサイトはデフォルトで「自分のみ」「Googleアカウントを持つ全員」「全員」という公開範囲を設定可能です。
さらにアクセスしているユーザの情報を取得することで細かなアクセス制御も可能ですが、Googleアカウントの情報を取得するため厳密に制限ができる反面、事前にアクセスを許可するメールアドレスをリストに追加し、閲覧ユーザにユーザ情報の取得を許可してもらう必要があります。
今回紹介する方法では事前のメールアドレス把握やユーザ情報の取得は不要です。
ただし通常のbasic認証同様、IDとPWがわかればアクセスできてしまう点にはご注意ください。
この記事では以下のステップでコードを解説しています。
1. 仕組み
ID/PWの認証にはGASのProperties Serviceクラスの「スクリプトプロパティ」と「ユーザプロパティ」を使用します。
スクリプトプロパティは全てのユーザがアクセスできるプロパティ、ユーザプロパティはスクリプトを動かすユーザのみがアクセスできるプロパティです。
スクリプトプロパティへ事前にID/PWを設定しておき、ユーザプロパティへユーザが入力したID/PWを保存をします。
GET時にID/PWの認証を行い、結果に応じて認証画面と認証後の画面を出し分けます。
認証が成功した場合にユーザプロパティにID/PWを保存して、次回以降はGET時に保存した認証データを参照します。
2. コード一覧
「ファイルを追加」から以下のファイルを作成し、各々コードを書き換えてください。
※ ID/PWをコードに直接記述すると、ライブラリとして公開されるURLを利用した際に外部のユーザが取得できてしまうため、{ID} {PW}から変更しないでください
- gas.gs
- auth.html
- index.html
gas.gs
サーバー側の処理部分になります
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
function setup() { PropertiesService.getScriptProperties().setProperty('auth', JSON.stringify({id:"{ID}", pw:"{PW}"})); } function doGet() { const authOwn = JSON.parse(PropertiesService.getUserProperties().getProperty('auth_users')); if (tryAuth(authOwn) == "success"){ var htmlOutput = HtmlService.createTemplateFromFile("index").evaluate(); } else { var htmlOutput = HtmlService.createTemplateFromFile("auth").evaluate(); } return htmlOutput; } function tryAuth(authOwn) { if (authOwn != null){ const auth = JSON.parse(PropertiesService.getScriptProperties().getProperty('auth')); if (auth.id == authOwn.id && auth.pw == authOwn.pw) { PropertiesService.getUserProperties().setProperty('auth_users', JSON.stringify(authOwn)); return "success"; } } return "fail"; } function deleteAuth(){ PropertiesService.getUserProperties().deleteAllProperties(); } |
auth.html
認証画面としてフロントに表示するものです
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<!DOCTYPE html> <html> <head> <base target="_top"> </head> <body> <form onsubmit="handleSubmit()"> <input name="id" type="text" placeholder="ID" required="required" autocomplete="off"> <input name="pw" type="password" placeholder="PW" required="required" autocomplete="off"> <input type="submit" value="認証"> </form> <script> window.addEventListener("load", function(){ document.querySelector("form").addEventListener("submit", function (event) { event.preventDefault(); }); }); function handleSubmit() { document.querySelector("input[type=submit]").disabled = true; const authOwn = document.querySelector("form"); google.script.run .withFailureHandler(onFailure) .withSuccessHandler(onSuccess) .tryAuth(authOwn); } function onSuccess(rslt){ if (rslt == "success"){ window.open("<?= ScriptApp.getService().getUrl() ?>", "_top"); } else { alert("認証情報が一致しません"); document.querySelector("input[type=submit]").disabled = false; } } function onFailure(){ alert("正常に完了しませんでした"); document.querySelector("input[type=submit]").disabled = false; } </script> </body> </html> |
index.html
認証済の場合にフロントで表示するものです
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<!DOCTYPE html> <html> <head> <base target="_top"> </head> <body> 認証成功 <button type="button" onclick="reset()">認証情報削除</button> <script> function reset(){ google.script.run .withFailureHandler(reload) .withSuccessHandler(reload) .deleteAuth(); } function reload(){ window.open("<?= ScriptApp.getService().getUrl() ?>", "_top"); } </script> </body> </html> |
3. セットアップ方法
setup()
を実行


※ 必ず「ウェブアプリケーションにアクセスしているユーザー」で実行するように設定してください

4. コード解説
※ JavaScriptの挙動については詳細は割愛しています
gas.gs
gas.gsに記述するコードについて解説します。
PropertiesServiceクラスのgetScriptProperties()
メソッドでスクリプトプロパティを取得
取得したプロパティに対してPropertiesクラスのsetProperty(key, value)
メソッドでキーauthに対してidとpwを保存
このとき、Object型ではプロパティの値として扱えないため、JSON形式に変換を行う
1 |
PropertiesService.getScriptProperties().setProperty('auth', JSON.stringify({id:"{ID}", pw:"{PW}"})); |
webサイト読み込み時(GET時)に動作
PropertiesServiceクラスのgetUserProperties()
メソッドでユーザプロパティを取得
取得したプロパティに対してPropertiesクラスのgetProperty(key)
メソッドでキーauth_usersに紐づく値を取得
JSON形式で保存されているため、Object型に戻して変数authOwnへ格納
1 |
const authOwn = JSON.parse(PropertiesService.getUserProperties().getProperty('auth_users')); |
関数tryAuthへ変数authOwnで認証をリクエスト
戻り値に応じたhtmlファイルを変数htmlOutputにHtmlOutputオブジェクトとして格納
HtmlOutputオブジェクトはHtmlServiceクラスのcreateTemplateFromFile(filename)
メソッドでhtmlファイルをHtmlTemplateオブジェクトに変換し、HtmlTemplateクラスのevaluate()
メソッドで変換して生成
※ 今回はhtml内にGASコードが含まれるためcreateTemplateFromFile(filename)
を使用
1 2 3 4 5 |
if (tryAuth(authOwn) == "success"){ var htmlOutput = HtmlService.createTemplateFromFile("index").evaluate(); } else { var htmlOutput = HtmlService.createTemplateFromFile("auth").evaluate(); } |
フロントで出力する内容として変数htmlOutputを返す
1 |
return htmlOutput; |
変数authOwnが空でない場合、
PropertiesServiceクラスのgetScriptProperties()
メソッドでスクリプトプロパティを取得
取得したプロパティに対してPropertiesクラスのgetProperty(key)
メソッドでキーauthに紐づく値を取得
JSON形式で保存されているため、Object型に戻して変数authへ格納
さらに変数authOwnと変数authのid/pwがどちらも一致した場合、
PropertiesServiceクラスのgetUserProperties()
メソッドでユーザープロパティを取得
取得したプロパティに対してPropertiesクラスのsetProperty(key, value)
メソッドでキーauth_usersに対してidとpwを保存
このとき、Object型ではプロパティの値として扱えないため、JSON形式に変換を行う
認証結果としてsuccessを返す
1 2 3 4 5 6 7 |
if (authOwn != null){ const auth = JSON.parse(PropertiesService.getScriptProperties().getProperty('auth')); if (auth.id == authOwn.id && auth.pw == authOwn.pw) { PropertiesService.getUserProperties().setProperty('auth_users', JSON.stringify(authOwn)); return "success"; } } |
変数authOwnが空の場合もしくは変数authOwnと変数authのidとpwが一致しなかった場合、認証結果としてfailを返す
1 |
return "fail"; |
PropertiesServiceクラスのgetUserProperties()
メソッドでユーザープロパティを取得
取得したプロパティに対してPropertiesクラスのdeleteAllProperties()
メソッドで全てのキーとそれに紐づく値を削除
1 |
PropertiesService.getUserProperties().deleteAllProperties(); |
auth.html
auth.htmlに記述するJavascriptについて解説します。
画面読み込み完了後に自動実行
form要素のsubmit時にsubmitのデフォルトイベントをキャンセルするイベントを追加
1 2 3 |
document.querySelector("form").addEventListener("submit", function (event) { event.preventDefault(); }); |
重複送信防止の為、submitボタンを非活性化
1 |
document.querySelector("input[type=submit]").disabled = true; |
変数authOwnにform要素を格納
1 |
const authOwn = document.querySelector("form"); |
GAS側の関数tryAuthへ変数authOwnで認証をリクエスト
認証結果を問わず関数実行が失敗した場合、関数onFailureを動作させる
認証結果を問わず関数実行が成功した場合、関数onSuccessを動作させる
1 2 3 4 |
google.script.run .withFailureHandler(onFailure) .withSuccessHandler(onSuccess) .tryAuth(authOwn); |
認証が成功した場合、現在のURLに再アクセスを行いGAS側の関数doGetを動作させる
現在のURLはGASのScriptAppクラスのgetService()
メソッドでウェブアプリのServiceオブジェクトを取得し、getUrl()
メソッドで取得
※ GASのwebサイトはiframe構造のためJSのlocation.href
では取得できません
失敗した場合、認証が失敗した旨をアラートで通知し、submitボタンを活性化
1 2 3 4 5 6 |
if (rslt == "success"){ window.open("<?= ScriptApp.getService().getUrl() ?>", "_top"); } else { alert("認証情報が一致しません"); document.querySelector("input[type=submit]").disabled = false; } |
関数実行が失敗した旨をアラートで通知
1 |
alert("正常に完了しませんでした"); |
submitボタンを活性化
1 |
document.querySelector("input[type=submit]").disabled = false; |
index.html
index.htmlに記述するJavascriptについて解説します。
GAS側の関数deleteAuthへ認証情報削除をリクエスト
関数実行結果を問わず、関数reloadを動作させる
1 2 3 4 |
google.script.run .withFailureHandler(reload) .withSuccessHandler(reload) .deleteAuth(); |
現在のURLに再アクセスを行いGAS側の関数doGetを動作させる
現在のURLはGASのScriptAppクラスのgetService()
メソッドでウェブアプリのServiceオブジェクトを取得し、getUrl()
メソッドで取得
※ GASのwebサイトはiframe構造のためJSのlocation.href
では取得できません
1 |
window.open("<?= ScriptApp.getService().getUrl() ?>", "_top"); |
まとめ
GASでBasic認証もどきを実装する方法を解説しました。
コピペだけで実装できますので、社内や仲間内での共有などにぜひ活用してみてください。
この記事は役に立ちましたか?
もし参考になりましたら、下記のボタンで教えてください。
コメント