谷本 心 in せろ部屋 このページをアンテナに追加 RSSフィード

2007-08-20

[]serializeConverterとか作ったら幸せになれね?

<input type="hidden" m:value="#{xxxDto.yyyList}" m:converter="#{serializeConverter}" />

みたいな書き方ができるConverter作れば、

Listをsessionに入れなくても、入力をListで受けるようにできないかなー?


超ジャストアイデアなので、何の検証もしてないけど。

2007-08-13

[]間違ってバリデータ消しちゃった・・・。

あ”〜、しまった!!


http://d.hatena.ne.jp/cero-t/20070726/1185468870

で書いたバリデータをこないだローカル環境で完成させたんだけど

別の問題対応している間に、間違ってプロジェクトごと削除しちゃったーー!!


俺あほやーーー(TT


ちゃんとローカル構成管理しとけ!>俺

2007-08-09

[]outjectionって分かりづらくね?

何って、Actionに作るgetterメソッドのことですよ。

Actionにgetterを作っておくと、S2Containerに管理されたり

管理対象じゃなければRequestスコープに入るわけですが。


S2JSFで最初に躓くのって、このoutjectionじゃないでしょうか。

outjectionにせず、requestにsetAttributeしてしまった方が

普通の開発者には分かりやすいのではないでしょうか。


つまり、public Hoge getHoge() って書くよりも、

request.setAttribute("hoge", hoge); って

書く方が分かりやすいのでは、ということです。


少なくともActionを書いている時には

オブジェクトのライフサイクルは「考える」でしょうから

FW側でライフサイクルを変更できる」というメリットは、

実質、享受されないでしょう。


HttpServletRequestを渡すのが嫌なら、みんな大好き俺様Requestで。

RequestScope.set("hoge", hoge); と書けばOK、みたいな。


ついでに、injectionとかもやめちゃって、requestパラメータは引数渡し。

引数名はARGSアノテーションで指定すれば良いのではないでしょうか。


つまり、こんな風にしちゃえばいいと思うんですよ。

@ARGS({"userId", "dto"})
public String doHoge(String userId, XxxDto dto)
{
	List groupList = xxxService.find(userId, dto);
	RequestScope.set("groupList", groupList);

	return "hoge2";
}

xxxServiceだけはテストしやすいようinjectionされます。

別に、publicでも構わないでしょう。


あと、DiiguとかIrenkaとか使えば

引数名も取れるようになるのかな?

public String doHoge(String userId, XxxDto dto)
{
	List groupList = xxxService.find(userId, dto);
	RequestScope.set(groupList);

	return "hoge2";
}

こんな風になると、分かりやすいのではないでしょうか。


Pageクラス(≒HTMLJava化)という概念ならまだしも

通常のStrutsライクなアーキテクチャなら

このように、引数の明確化、スコープの明確化を

行なった方が分かりやすいかな、と思いました。


では、Pageクラスが主流となった現在は、

どんな風に書けば分かりやすいのでしょうか。


それについてはATDK

2007-08-01

[][]もうちょっとVerificationについて考えてみた。

S2JSFだったら、HTMLにValidationを書いて

Dtoにアノテーションを書いてVerificationにすればOK。


でも、結局、両方に似たような事を書くことになるだろうから、

そのうち面倒くさくなってくるよね。(むら)


基本的にはVerificationの一部を切り出したものがValidationになるだろうから

(Validationの方がVerificationより厳しい事は、ないだろうから)

Validationもアノテーションに反応して行なえるようにしたい。


では、どのようなアノテーションにすれば、そんな事ができるのでしょうか。


■基本方針

Dtoプロパティに@Requiredとか@MaxLengthみたいなアノテーションをつけて、

Validator/Verifierがそれを見て反応。

アノテーションへの引数の渡し方なんかは、Teedaと同じノリで。


Verifier専用のメソッドは、public booleanなメソッドに

@Verifierというアノテーションを書く。


もしくは、StrutsのActionFormみたいに、Verifyメソッドを実装できる。


あるいは、クラスにアノテーションを付けて、

@VerifierMethod("verifyHoge") みたいに書いておくと

verifyHogeメソッドが呼び出されても良い。


■ウィザード画面で、全バリデータが作動すると@Requiredで軒並みエラーが出るんですが

バリデーションをするのは、Dtoのフィールドに画面からの値を設定しようとした時。

だから画面から値が設定されないフィールドではバリデーションが起こらない。

もちろん、@Requiredなフィールドにnullとか空とか入れようとしたらエラー。


■複数フィールドバリデータは?

悩ましいけど、画面で一番下になる項目(年月日で言えば、日)に

アノテーションをつけるしかないかな。


■ボタンによってValidatorを分けたい時は?

えーっと、これは困る。

Dtoで画面のボタンまでは意識したくない、というのが本音。

だからアノテーションにボタンIDを書くというは、できれば避けたい。


いっそ、Actionのメソッドに引数を持たせるというアイデアでどうか。

もうS2JSFじゃ実現し得ないアイデアになっちゃうけど。

例えばHTML

<input id="param1" type="text" m:value="param1" />
<input type="button" m:action="doHoge" />
<input type="button" m:action="doFuga" />

って書いておいて、Actionに

publict String doHoge(FooDto fooDto);
publict String doFuga(BarDto barDto);

って書いておく。


doHogeのボタンを押したら、FooDto#setParam1にparam1を渡してdoHogeを呼び出す。

doFugaの方も同様。

それで、FooDto/BarDtoそれぞれのバリデーションを掛ける。

FooDtoもBarDtoも実装はほぼ全く同じになるだろうけど仕方ない。


■更新画面の場合、initialize()でどうやってparam1に値を入れるの?

えっと、、、ペ、、、ページクラス?

なんてやると、PageクラスとDtoでまた同じ値が被りますね。


まぁちょっとこの辺りで行き詰ったんですが、

もうちょっと考えれば答えは出せそうです。

2007-07-31

[][]ValidationとVerification

こないだのドン引き最終回でもチラっと出た、これ。


ValidationとVerification。

言葉的には「妥当性の確認」と「検証」なんだけど、

ここでは「画面入力のチェック」と「サービスの引数チェック」って事にしておく。


図にするとこんな感じ。

f:id:cero-t:20070731232453g:image


Webアプリケーションのセキュリティでウダウダ言ってる問題って

実は、この2種類に分ければ、随分と上手く整理できそうなんですよね。


ときに、

フレームワーク使って開発してると、バリデーションの責務が増えがち。

だって、バリデータとロジックの双方でチェックなんてしたくないから。

だから複数フィールドバリデータとか、無理してキモい事やったり

バリデータからDBにアクセスしたり、おいおい、それ何てLogic? みたいな状況になる。


逆に、バリデータはソコソコに、ロジックできっちりチェックすると

決めてるプロジェクトも多いと思うんだけど、

そんな場合も、もし、hidden書き換え対策だー、とか言って

sessionにDtoを持たせてたりすると、

ロジックに到達した時点でDtoには値が反映されてるわけだから、これヤバい。

詳しくは書かないけど、ヤバい。チェックの意味があんまりない。


セッションは極力使わず、入力はhiddenを使って保持して、

値はロジックでもチェックする、多分これが一番安全。


さて、

ここで最初に書いた「Validation」と「Verification」に話を戻しましょう。


「入力値のチェック」っていうのを、何のために行なうかを考えると、

やはり「ユーザビリティ」のためでしょう。

最後のコミットする段階になって「ふつうにだめー」とかってDBに怒られると、

もう腹が立って仕方ないから入力段階でバリデーションを行なう。


ここで勘違いしちゃいけないのは、

このバリデーションはセキュリティのためじゃないってこと。


いくらバリデーションタグを使っても、hiddenタグは書きかえられちゃうし、

sessionの値も、結局、安全とは言えない。


セキュリティのために行なうのは、Verification。

つまり、サービスを呼び出し時の引数のチェック。


Dtoがリクエストスコープだったら、そのままサービスに渡して良いけど

Dtoをセッションスコープで保持した場合は、ディープコピーを作ってから渡す。

それをService層でチェックする。


ほら、みんなWebサービスだったら同じことするでしょ?

それをWebアプリケーションでもやるだけ。


この原則を守ってさえいれば、

別に複数ウィンドウ対策とか、画面フローの制御とか行なわなくて良い。

そんな「変な」操作をして困るのは、操作した人だから。

システムには影響を与えないから。


ここで、サービスの引数となるDtoにはアノテーションを入れておいて、

Interceptorでチェックしてあげるのが、一番楽なのかな。


というのを形にすると、最初に見せた図の通りになる。

f:id:cero-t:20070731232453g:image

Validationは、HTMLに記述したValidatorで行なって

Verificationは、Formに記述したアノテーションに反応して行なう。

もちろんVerificationは複数フィールドの相関チェックにも対応するし、

Daoアクセスなんかも可能、という位置づけで。


ただ、これでも、二重サブミットと、CSRFは防げないから、

ワンタイムトークンの発行だけは必須。

確認画面の表示時にでもワンタイムトークンを渡してあげて、

それでコミットを行なえば良い。


これでどう?

[]新バリデータ、いちおう、動作しました。

なんて事を言いながら、

S2JSFの新バリデータ、"s:validator2"の実装を行なっちゃいました。


いきなりリリースするわけにもいかないので、

S2JSF 1.0.26のリリース後にSVNにコミットして、

しっかりテストも通してからリリースしようと思います。


さすがに、そろそろドキュメントも書かないと!>俺