コンテンツセキュリティポリシーへ対応する - ngCsp
最近のAjaxなどを使ってのHTMLの場合にはXSS(クロスサイトスクリプティング)などの脆弱性が入り込みやすいという問題があります。
このような問題に対応するために、ブラウザもセキュリティを高いモードで動作できるようにしたものが、「コンテンツセキュリティポリシー(以下CSP)」です。
簡単に言えば、JavaScript内でのeval()の実行を禁止したり、また、HTML内でscriptタグ内にJavaScriptを記述できる機能を無効にしたりと、これ以外にも細かくルールを規定することができます。
CSPを有効にするにはリスト8に示すようにHTTPヘッダに"Content-Security-Policy"というヘッダを追加します。
ただし、すべてのブラウザでサポートしているわけではなく比較的新しいブラウザのみとなっていて、Can I Useなどを参照すればどのブラウザで利用できるかを調べることができます。
Content-Security-Policy: default-src 'self' X-Content-Security-Policy: default-src 'self'
ここではCSPの詳細な設定方法を説明しませんが、詳しくはMDNなどを参照すると理解できます。
もともとAngularJSはCSPを意識した作りになっていますが、CSPを有効にしたときに以下の2つの処理に影響が発生します。
- $scope内の変数をHTMLテンプレートから取得する場合などで実行速度を優先するため「new Function(string)」を行う部分
- インラインCSSをHTML内に追加する部分(ng-cloak等)
new Function(string)を使わないようにする為には、ng-cspディレクティブをHTML要素に記述します。そして、インラインCSSの対応は代わりにangular-csp.cssを読みこむようにします。
リスト10はこれらの対応を行った後のサンプルコードです。
<html ng-csp> <head> : // 省略 <link rel="stylesheet" href="../css/angular-csp.css"> </head> <body ng-app="app"> : // 省略 </body> </html>
ng-cspを設定しても図5のようなエラーが発生する場合には、指定する場所が間違っているので、HTML要素に正しく記述してあるか確認してください。
なお、ng-cspディレクティブを明示しても、eval等の実行ができるようになるわけではないので、自分で記述するコードはCSPの制限にそった実装をする必要があります。
CSPは、開発者が指定するというよりは、サイトの管理者によって指定される場合が多いと思います。現在は必要なくても、必要になったときにそのまま動作することが望ましくあります。
このようにAngularJSはこのようなセキュリティに関しても十分考慮されたフレームワークだと言えます。
モデルの変更タイミングを指定する - ngModelOptions
このディレクティブは1.3で新たに導入されたディレクティブですので、1.2以前のバージョンを指定している場合には利用できませんが、入力フォームなどで指定したモデルの変更タイミングを指定することができる便利なディレクティブです。
例えば、郵便番号を入力すると自動的に住所が反映される用途の場合、入力カーソルがはずれた時にAjaxなどでサーバ機能と連携がしたくなります。その場合にngModelOptionsは大変有効な機能です。
リスト11は、blurイベントをモデルの変更タイミングに指定し、イベントの発生を500ミリ秒後に発生するように指定します。
これで、500ミリ秒以内に複数回blurイベントが発生しても最後のblurイベントのみが有効になります。
<div ng-init="name = '';"></div> <input type="text" ng-model="name" ng-model-options="{ updateOn : 'blur', debounce : 500 }" > <br /> あなたが入力した値は「<b>{{name}}</b>」です
変更が発生したタイミングで処理をするには、リスト11のように$scope.$watchメソッドを使えば目的となる処理が行えます。
app.controller('changeController',['$scope',function($scope){ $scope.name = ''; $scope.$watch('name',function(newValue,oldValue){ if(newValue){ console.log(newValue); // 何か処理をする } }) }]);
表2は指定できるオプションの一覧です。ここで指定したオプション以外もありますので、詳しく知りたい場合には、リファレンスを参照してください。
指定できるオプション | 説明 |
---|---|
updateOn | 変更を行うタイミングのイベント |
debounce | 変更イベントを指定した時間(ミリ秒)だけ遅らせる |
allowInvalid | 無効なデータでのモデル値を許容するか |
getterSetter | getter/setterを利用したアクセスを行うようにする |
timezone | inputでtime='date'もしくは'time'を指定した時のタイムゾーンの指定 |
最後に
これまで紹介してきたように、AngularJSのビルトインディレクティブだけでも十分な機能を持っています。
しかし、AngularJSではこのディレクティブ機能を利用して、比較的簡単に独自タグや独自属性を作ることができます。その機能を利用したサードパーティ製のディレクティブなども多々あります。
例えば、今回説明したDOMイベントでビルトインで用意されていないイベントを扱う際には、Event Binderを利用して拡張が可能です。
近日中に、いよいよAngularJS 1.4がリリースとなりそうです。少々大きな変更になり影響が出てくる開発者の方も出てくると思いますので、次回は少々予定を変更してAngularJSの1.4での新機能や注意すべき機能などを紹介したいと思います。