webページに埋め込んだGeoGebraアプレットにおける内部構造の閲覧制限について
1 はじめに
アプレットの埋め込みとダウンロード
GeoGebraでは、ユーザーページから、作成したアプレットをブログ等に埋め込むためのhtmlを生成することができる。
本ブログは、このhtmlを使ってアプレットを埋め込むことで、作成したアプレットを紹介している。アプレットが埋め込まれたページのソースを見ると、上記htmlを見ることができる。
たとえば、「light_2018版 - うしブログ」のページのソースには、以下のhtmlが含まれている。
このhtmlには、アプレットのID情報が含まれている。上のソースでは、下線部分のうち「tC8Z3WpZ」がID情報である。
ID情報が分かると、そのアプレットが保管されているGeoGebraのwebページにアクセスすることができ、そのページから、アプレットをダウンロードできる。URLは以下のとおりである。
https://www.geogebra.org/m/(ID文字列)
上の例では、
が、アプレットの保管ページである。
保管ページの右上から、アプレットをダウンロードしたり、webブラウザ版GeoGebraで開いたりすることができる。
アプレットの内部構造の閲覧
ブログ等のページに埋め込まれた状態では、そのアプレットがどのような仕組みで作られているか(内部構造)を見ることはできない*1。
これに対して、アプレットをダウンロードしたり、webブラウザ版GeoGebraで開いたりすれば、「数式ビュー」からオブジェクトの定義を確認したり、「プロパティ」ダイアログからオブジェクトのスタイル・表示条件・スクリプト等を確認することができる。つまり、アプレットの内部構造を確認できるのである(換言すれば、リバースエンジニアリングが可能である)。
GeoGebraのwebページに投稿されたアプレットは、非商用ライセンスの下で、誰でも自由に利用可能である*2。投稿されたアプレットは教育活動に役立つ資源として広く共有していこう、という、GeoGebraの精神が窺い知れる。そして、GeoGebraでは、投稿されたアプレットの内部構造の閲覧を制限する機能は、実装されておらず、そのような制限をすることは不可能であるとされてきた*3。
本記事の目的
もっとも、アプレットを教材として公表したいけれども、公表したいのはあくまでアプレットの外形的機能だけで、それを実現している内部構造は非公開にしておきたい、という場合があるかもしれない。
例えば、計算問題に関するアプレットにおいて、答えを記載したテキストオブジェクトを用意しておき、これを生徒が解答を入力するまでは非表示にしておき、解答入力後に表示させたい、という場合を考えてみよう。オブジェクトの表示/非表示は、「オブジェクト表示の条件」を指定することで切り替えることが可能である*4。ところが、非表示にしていたとしても、数式ビューから当該テキストオブジェクトのプロパティを参照すれば、テキストの内容(すなわち計算問題の答え)を、問題解答前に閲覧することができてしまう。そこで、生徒には、教師のwebページ等に埋め込まれたアプレットを教材として使用してもらい*5、生徒が当該webページのソース等から、アプレットが保管されているGeoGebraのwebページにアクセスして、ファイルをダウンロードして開こうとしても、パスワードを入力しなければ開けない仕掛けにしておけば、生徒が解答前にテキストオブジェクトの内容を閲覧することを防止できるのである。
本記事は、GeoGebraのアプレットに対して、こうした仕掛け(以下「内部構造の閲覧制限」という)を施すことの可否の検討を目的とする。なお、本記事では、内部構造の閲覧制限を行うことが、GeoGebraの精神に照らして妥当であるか否かには立ち入らない。あくまで、当該制限が技術的に可能なのか否かを、純粋な探究心から検討することが目的だからである。
バージョン情報
本記事は、バージョン 6.0.454.0-w (17 April 2018)のGeoGebraを対象とする。
2 モデルの紹介
以下では、内部構造の閲覧制限をかけたいアプレットのモデルとして、以下のアプレットを用いる。
3つの計算問題について、すべての解答を入力すると「採点」ボタンが現れ、ボタンを押すと採点結果と答えが表示される、というアプレットである。
このアプレットの、本記事への埋め込みのためのhtmlは、以下の通りである。
<iframe scrolling="no" title="計算問題" src="https://www.geogebra.org/material/iframe/id/pWpuwaNH/width/452/height/480/border/888888/smb/false/stb/false/stbh/false/ai/false/asb/false/sri/false/rc/false/ld/false/sdz/false/ctl/false" width="452px" height="480px" style="border:0px;"> </iframe>
また、アプレットの保管ページは
である。
上記の埋め込み画面上では、どんな操作をしたとしても、解答入力前に正答を知ることはできない。
ところが、上記保管ページからアプレットをダウンロードしてPC版GeoGebraで開いたり、web版GeoGebraで開いたりすると、「数式ビュー」から、いとも簡単に正答が閲覧できてしまう。
3 基本的発想
ユーザーにパスワードを入力させる方法
まずは、ユーザーにパスワードの文字列を入力してもらい、その文字列を何らかの形で記録・保持する仕組みが必要になる。
このためには、JavaScriptで入力ダイヤログを表示させるメソッドである、promptを使用すれば良い。
パスワードが正しくない場合の処理
パスワードが正しくない場合には、ユーザーに内部構造を閲覧させたくないわけだが、その方法としては、パスワードが正しくないことが判明したのち、①内部構造自体は存続させるが、その閲覧を遮断する機能を発動させる方法、②同じく内部構造自体は存続させつつ、ユーザーが入力した文字列に応じて、別のアプレットにユーザーを飛ばす方法*6、③内部構造自体を改変・破壊・消去して、根本的に閲覧不能にする方法が考えられる。
ところで、GeoGebraにおいて利用可能なJavaScriptのメソッドとして、
ggbApplet.newConstruction();
というメソッドがある。これは、すべてのオブジェクトを削除したうえで、その作成順序のデータも削除する。したがって、実行後に「元に戻す」ことによってオブジェクトを復元することはできない。
そこで、パスワードが正しくない場合にこのメソッドを実行すれば、ユーザーにオブジェクトの内容を閲覧される前に、全オブジェクトを不可逆的に消去できるため、上記③の発想が実現できる。
また、
ggbApplet.reset();
というメソッドもある。これは、アプレットを最初の状態に戻すメソッドであり、ggbOnInit 関数も実行される。したがって、パスワードが正しくない場合にこのメソッドを実行すれば、再びパスワード入力画面が現れ、正しいパスワードを入力しない限りパスワードを要求し続けるという、無限ループに入る。これによっても、ユーザーにオブジェクトの内容を閲覧されることを防げるだろう。
newConstruction メソッドは、PC(インストーラ)版GeoGebraにて実行した場合に、パスワードが間違っていても、その後表示される(場合のある)、「ファイルを閉じる」ダイヤログにおいて「取り消し」を選択することによって、データ削除を回避できるという抜け道がある。
また、resetメソッドも、ユーザーを無限ループに陥らせることは、ユーザーにアプリの強制終了を強いることになるため、望ましい方法とはいえない。
しかし、両者を組み合わせれば、お互いのデメリットは解消できる。
すなわち、第一にnewConstruction メソッドを実行し、第二にreset メソッドを実行するように組んでおけば良いのである。こうすれば、「ファイルを閉じる」ダイヤログにおいて「取り消し」を選択することによって、newConstruction メソッドを抜けたとしても、第二のメソッドであるreset メソッドによって、2回目のパスワード要求が行われる。そこでパスワードをミスした場合、newConstruction メソッドの2回目の実行がなされるのであるが、GeoGebra (Ver. 5.0.321.0-3D)の仕様上、ここでは「ファイルを閉じる」ダイヤログが表示されることなく、直ちに全オブジェクトの不可逆的消去が行われる。
パスワードの照合
上記③の発想をとる場合には、②と違って、正しいパスワードをどこかに記述しておく必要がある。③では、パスワードが正しくない場合に、アプレット内のオブジェクトがすべて不可逆的に消去されるため、アプレット内のオブジェクトに依存する形で、正しいパスワードの情報を記述するのが望ましい*7。
例えば、正しいパスワードが「usidesu」であるとして、点オブジェクトのOn Click スクリプトに、JavaScriptで
if(pass != "usidesu"){
ggbApplet.newConstruction();
}
と記述しておいて、アプレット起動時に、これをRunClickScriptコマンドで実行させれば良い。
埋め込まれている場合にはパスワードを要求しない
パスワードを要求して、間違っていたらオブジェクトを不可逆的に消去する、という処理を実行すべきなのは、ユーザーが、保管ページからアプレットをダウンロードする等によって、webサイトに埋め込まれていない状態でアプレットを起動しようとした場合に限る。webサイトに埋め込まれている状態でアプレットを起動した場合には、上記処理は必要ない。埋め込み画面上で内部構造を閲覧することは、できないからである。
そのため、アプレットの起動時に、アプレットがwebサイトに埋め込まれている状態なのか否かを区別する方法を考えなければならない。
モデルの計算問題アプレットの埋め込みは、
というURLのページを、<iframe>(インラインフレーム)によって埋め込むという方法で行われている(上述「モデルの紹介」にて掲げたhtmlを参照)。アプレットがこの方法で埋め込まれている場合に限って、JavaScriptで
var url = location.href ;
とすることで、変数「url」に、上記URLを記載したテキスト情報を代入することができる。
これに対して、web版GeoGebraやPC版GeoGebraなど、上記方法による埋め込み以外の方法でアプレットを起動した場合には、変数「url」に、上記URLは代入されない。
この違いを利用すれば、アプレットがwebサイトに埋め込まれている状態なのか否かを区別することができる。
4 内部構造の閲覧制限の実現方法
上記の基本的発想に従って、モデルのアプレットに内部構造の閲覧制限をかけてみよう。正しいパスワードは「usidesu」とする。
パスワード照合用オブジェクトの作成
まず、パスワードの照合用として、モデルのアプレット上に、点オブジェクトを1つ作成し、名前を「Terminator」とする*8。点Terminatorは、ユーザーにとって見えている必要はなく、また表示しておくと誤クリックのおそれもあるので、非表示にしておく。
そして、点TerminatorのOn Click ハンドラに、以下を記述する。
if(pass != "usidesu"){
ggbApplet.newConstruction();ggbApplet.reset();
}
上記スクリプトでは、newConstructionとresetを併用している。
このとき、「OK」ボタンの左にあるプルダウンメニューで「JavaScript」を選択するのを忘れないよう、注意されたい。
グローバルJavaScriptの記述
グローバルJavaScriptに、以下を記述する。
var url = location.href;
function ggbOnInit() {
if(url != "https://www.geogebra.org/material/iframe/id/pWpuwaNH/width/452/height/480/border/888888/smb/false/stb/false/stbh/false/ai/false/asb/false/sri/false/rc/false/ld/false/sdz/false/ctl/false") {
pass = prompt("パスワードを入力してください", "");
ggbApplet.evalCommand("RunClickScript[Terminator]");
}
}
4行目のURLは、そのアプレットを埋め込むためのhtmlから、過不足なく抜き出してくる。
設定は以上である。アプレットに対して、上記のような変更を反映させるためには、web版GeoGebra上で上記の作業を行うか、PC版GeoGebraでファイルを変更したのち、アプレット保管ページ中「ワークシートを変更」からファイルをアップロードすれば良い。その際、数回にわたってパスワードの入力を求められる場合があるが、仕様上のものであり、異常ではない。
5 結果
本記事に埋め込まれているアプレットについては、起動時にパスワードの入力は求められない。
これに対して、保管ページである
にアクセスすると、アプレット読み込み完了直前に、パスワードの入力を求められる。
正しいパスワード「usidesu」を入力すると、計算問題が表示されるが、パスワードを間違うと、真っ白な画面しか表示されない。
web版GeoGebraで開こうとしても、同様である。
ggbファイルをPCにダウンロードして、PC版GeoGebraで開こうとしても、同様である。
6 留意すべき点
以上の結果のとおり、アプレットに内部構造の閲覧制限をかけることに成功した。
もっとも、アプレット自体にパスワードの情報が含まれている以上、制限は絶対的なものではありえない。ファイル自体を解析する等、方法によっては内部構造を閲覧できる余地があるだろう。
したがって、本記事の方法は完全な閲覧制限を保障するものではないという旨、および、本記事に書かれている方法を用いたことによって生じたトラブルに関して、筆者は一切の責任を負いかねる旨、ご留意いただきたい。
*1:ただし、埋め込みの設定で「右クリック、キーボードによる編集を有効にする」チェックボックスや、「メニュー」チェックボックスをオンにする等により、数式ビューやプロパティが閲覧可能な設定にしている場合には、閲覧可能である。
*2:非商用ライセンス(https://www.geogebra.org/license)2条参照。
*3:GeoGebraのフォーラムにおいて、そのような制限は100パーセント不可能であると断定する回答として、mathmagic〔回答〕Γιώργος Τσιρικος〔質問〕「Encryption」
https://help.geogebra.org/topic/encryption
参照。
*4:SetVisibleInViewコマンドを用いる方法もある。
https://wiki.geogebra.org/en/SetVisibleInView_Commandを参照。
*5:埋め込みの際の設定のうち、「表示」および「アプレットの設定」に含まれる全てのチェックボックスをオフにしておく。これによって、埋め込み画面から数式ビューやプロパティを閲覧することを防止できる。
*6:この方法によるメリットは、正しいパスワードが何であるかをアプレット内に記述する必要がないことである。例えば、ユーザーが入力した文字列が、パスワードとして正しくても間違っていても、その入力した文字列を名前に持つアプレットを開くとしておけば、正しいパスワード(例えば「usidesu」とする)を入力した場合には本命のアプレットである「usidesu.ggb」が開き、それ以外の文字列を入力した場合には、アプレットが存在しないとしてエラーが返ってくるか、何も返されずに処理が停止するだろう。つまり、正しいパスワードが何であるか、という情報を、どこにも記述する必要がないのである。
*7:そうすることで、入力されたパスワードが間違っていた場合に、アプレット内のオブジェクトとともに、正しいパスワードの情報も、不可逆的に消去することができるからである。