jquery validation x asp.net mvc で遭遇した不具合 & 対抗ハック

37
jQuery Validation x ASP .NET MVC で遭遇した不具合 & 対抗ハック Community Open Day 2012 @jsakamoto

Upload: jun-ichi-sakamoto

Post on 31-May-2015

4.160 views

Category:

Technology


1 download

DESCRIPTION

Community Open Day 2012 北海道会場 セッション2

TRANSCRIPT

Page 1: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

jQuery Validation x ASP.NET MVC

で遭遇した不具合 & 対抗ハック

Community Open Day 2012

@jsakamoto

Page 2: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

Twitter Hashtag

• よろしければ、#clrh71 でお願いいたします。

– #cod2012jp だけだと、全国会場の Tweet と混信しそうなので...

– 本セッション中、MiniTwitter にて #clrh71 を含む Tweet をポップ

アップします。

Page 3: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

jQuery Validation についておさらい

• クライアント側スクリプトによる入力検証機能を提供する JavaScript

ライブラリ。

– jQuery のプラグイン

• ASP.NET MVC の、標準のクライアント側入力検証エンジンに採用

– MVC3以降

– Visual Studio にて ASP.NET MVC アプリを新規作成すると標準で使用。

• この資料を作成している時点での最新バージョン:

– jQuery = v.1.7.2

– jQuery Validation = v.1.9

Page 4: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

本セッションのテーマ

• jQuery Validation を使っている上で ”些細な” 不具合にいくつか遭遇

• それら不具合について紹介、どう対策して解決したのかを披露

• 対策はすべて、クライアント側 JavaScript コード上で施工

– 本セッションの本質的な部分では、C# とか ASP.NET とか出てきません。

– プラットフォーム問わず、Web アプリ共通の話題ではないでしょうか?

– っていうか、むしろ、Ruby on Rails などなど、他のプラットフォームでは

問題になってないのか? 気になります。

Page 5: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

デモ アプリ

• こんな ASP.NET MVC4 な

Webアプリを肴に、実演を

交えつつ、進めて参ります。

Page 6: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

文字数検証 - input type=“text”

Case 1.

Page 7: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

Demo

Page 8: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

何が起きてる?

• jQuery Validation は、行頭行末の空白を除いた文字数で

チェック

– ”期待” とは異なったクライアント側検証。

• サーバー側検証では、行頭行末の空白もそのままに文字

数チェックするのでセーフ。

– ”Post Back” な挙動。

– Webではクライアント側検証に頼らないという鉄則。

Page 9: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

対応

• jQuery Validation の検証メソッドを改変すればいい

maxlength: function(value, element, param) { return this.optional(element) || this.getLength($.trim(value), element) <= param; }

この trim 要らない!

Page 10: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

方法1 - jQuery Validation のソースを直接変更

• MIT License

• でも将来の jQuery Validation 本家のバージョンアップに

ついていける?

Page 11: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

方法2 – 開発元にフィードバック

• trim しているのは、それはそれで意味があるのでしょう。

• その上でなお、破壊的変更が受け入れられるのか?

• 仮に受け入れられるとして、リリースされるまで待てる?

– “今そこにある危機”

Page 12: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

方法3 – 実行時にOverride

• JavaScript なので、実行時に「書き換え」できます。

$.validator.methods.maxlength = function (value, element, param) { return this.optional(element) || this.getLength(value, element) >= param; };

Page 13: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

JavaScript コードの Hack

• いかにも “動的言語” らしく、Hack しやすい。

• しかし Closure が使える...!

– 関数型言語っぽい手法で作成されると手が出せない。

• jQuery Validation はそんな実装されてなく良かった...

これで学びました。

Page 14: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

文字数検証 - textarea

Case 2.

Page 15: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

Demo

Page 16: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

何が起きてる?

• jQuery Validation は、改行は1文字として文字数チェック。

• サーバー側検証では、改行は2文字として文字数チェック。

– POST データ中、改行が CR+LF になってる

– Windows7上で、IE9 でも Firefox12 でも Chrome19 でも同じ挙動

※以上を Fiddler v.2.3.9.3 で確認。MacOSではどうなんでしょう?

• クライアント側とサーバー側とで検証動作が異なる。

– ちなみに、XHR要求だと改行が LF で送信されたり。

Page 17: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

対応

• サーバー側で CR+LF を LF に置換することで対応可能。

• でも、漏れなく実装するのは大変では?

• それでは jQuery Validation の実装を変更しましょう。

– オリジナルの $.validator.prototype.getLength(value, element ) が

呼び出される前に、value に含まれる改行文字(LF)を2文字に置換し

てオリジナル実装に渡すよう、カスタムコードを ”差し込む”。

Page 18: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

実行時に Override

var org = $.validator.prototype.getLength; $.validator.prototype.getLength = function (value, element) { value = value.replace(/¥n/g, "++"); return org.apply(this, [value, element]); };

元の実装をorgに確保

LFを適当な 2文字に置換

元の実装をapplyで実行

getLength メソッドを 独自実装に差し替え

Page 19: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

Cancel ボタン

Case 3.

Page 20: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

Demo

Page 21: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

何が起きてる?

• “cancel” CSSクラスを持つ input か button がクリックされると「入力検証しない」のフラグが立つ。

• そしてそのフラグは解除されない。

this .find("input,button") .filter(".cancel") .click(function() { validator.cancelSubmit = true; });

Page 22: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

正攻法 – input で Cancel ボタンを実装しない

• a 要素で。

• Twitter Bootstrap など昨今の CSS ライブラリを使えば、a も

input も、同じ外観に作れる。

Page 23: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

どうしても、という場合...

• 「検証しない」フラグをワンショット遅延でオフに復元。

$(".cancel").click(function () { var validator = $(this).closest("form").validate(); setTimeout(function () { validator.cancelSubmit = false; }, 0); });

Page 24: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

IE8

Case 4.

Page 25: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

Demo

Page 26: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

何が起きてる?

• $.validator.elements メソッドの内部に原因

• IE8 だとなぜか、$($(“form”)[0].elements).filter(“:input”)

の結果が、要素数 = 0個になっている

– IE9 でも、ドキュメントモードが IE8 かそれ以前だと再現

Page 27: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

対応 – jQuery Validation を最新に

• この問題を抱えているのは、実は ver.1.8.0.1 まで。

• jQuery Validation を ver.1.8.1 以降に Upgrade で解決。

– ver.1.8.1 のパッケージは 2011年6月10日頃から出現している模様。

– それ以前に作成されたASP.NET MVC3 アプリは注意?

Page 28: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

jQuery Validation を最新にできない場合は...

• $.validator.elements の実装を実行時に Override。

• .filter(“:input”) ではなく、.find(“input, select, textarea”)

で要素を絞り込む。

$.validator.prototype.elements = function () { ... return $([]) .add(this.currentForm.elements) .find("input, select, textarea") ...; };

Page 29: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

CSS Class 名が検証ルール名にかぶった

Case 5.

Page 30: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

Demo

Page 31: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

何が起きてる?

• ASP.NET としての入力検証機構とは無関係に、jQuery

Validation による入力検証機構は活きている

• そのひとつ、CSSクラス名による入力検証の発動

– email

– required

– date

– number

– ...

Page 32: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

jQuery Validation 標準の検証ルールは潰せる

• $.validator.classRuleSettings からCSSクラス名ルールを削除

delete $.validator.classRuleSettings.email;

Page 33: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

徒然に

Page 34: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

些細なことにこだわってばかりで、

自分が器の小さい人間に思えてきました...

だって、結局は、サーバー側検証が機能するんだし...

Page 35: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

結局、フィードバックは、Microsoft を含め、

どこにもしていません。

他の仕事とか優先してしまい...

どなたか Microsoft Connect とかに投稿いただません?

Page 36: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

Web Forms や、MVC2 までの

クライアント側入力検証では、些細とはいえ、

こんな問題はなかったよな... と思ったり。

さすが Microsoft 純正品クォリティ?

今振り返るに、jQuery Validation の採用はどうだったんだろう...

Page 37: jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック

Thank you...