- PR -

認証処理でUnsupportedCallbackException

1
投稿者投稿内容
arare
会議室デビュー日: 2008/06/13
投稿数: 3
投稿日時: 2008-06-13 20:13
こんにちは。

ログイン画面を作成しています。
一通り実装し終え、認証処理を行えるようになりました。
しかし、画面にユーザID、パスワード以外の追加フィールドを持たせ
値を取得するところでつまずいています。(具体的にはreferrerを取ろうとしています。)
TextInputCallbackを認識できず、UnsupportedCallbackExceptionが発生しますが
原因が分からず困っています。

TextInputCallbackのインスタンス生成時に画面のフィールド名をあたえるだけでよいと考えているのですが、
そもそも実装方法が間違っているのでしょうか?

LoginModule.java
public boolean login() throws LoginException {




Callback[] callbacks = new Callback[] {
new NameCallback("Username: "),
new PasswordCallback("Password: ", false),
new TextInputCallback("ref") //リファラ
};

try {
_callbackHandler.handle(callbacks);
}catch(UnsupportedCallbackException e){
System.out.println(e.getCallback());
} catch (Exception e) {
_succeeded = false;
System.out.println(e.getMessage());
throw new LoginException(e.getMessage());
}



}

login.jsp
<form name="Login" method="post"
action="j_security_check" onSubmit="Javascript:act()">


<input type="hidden" name="j_username">
<input type="password" name="j_password">
<input type="button" value="ログイン" align="middle" onclick="Javascript:act()">
<input type="hidden" name="ref">


</form>

どなたか、ご教示いただけないでしょうか?
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2008-06-13 22:23
まともな方法では無理です。

Webコンテナの種類が書いていませんが、
私はフィールドを追加できるコンテナは知りません。

Tomcatを例にするとJAASCallbackHandlerがCallbackHandlerの実装ですが、
ユーザー名とパスワード以外の情報を扱える構造になっていません。

実現しようと思ったら、認証周りの多くを差し替えることになります。
arai
会議室デビュー日: 2008/06/13
投稿数: 2
投稿日時: 2008-06-14 00:01
>そもそも実装方法が間違っているのでしょうか
 これだけの情報では判断できかねますが、たぶん実装方法の間違えでしょう。

「javax.security.auth.callback.CallbackHandler」を一般的に使うには、自分で実装する必要があります。CallbackHandlerに何を渡すかによって、CallbackHandler#handleの処理は変わってきます。文章の内容を見るとソースに

Callback[] callbacks = new Callback[] {
new NameCallback("Username: "),
new PasswordCallback("Password: ", false),
new TextInputCallback("ref") //リファラ
};

と記述されていますが、「new TextInputCallback("ref")」を追加するまでは、正常に動作しているようなので、NameCallback、PasswordCallbackの処理はCallbackHandler#handleの実装元で処理されているようです。TextInputCallbackの処理に関しては、未実装だということが読み取れます。

「UnsupportedCallbackException」がスローされるとの事でしたが、

http://sdc.sun.co.jp/java/docs/j2se/1.4/ja/docs/ja/api/javax/security/auth/callback/CallbackHandler.html

のAPIによると

UnsupportedCallbackException - このメソッドの実装が callbacks パラメータで指定された 1 つ以上の Callback をサポートしない場合

と書かれており、CallbackHandler#handleにTextInputCallbackが実装されておらず「UnsupportedCallbackException」がスローされたと考えられます。

認証に関しては、

「JDK ドキュメント」→「セキュリティ」→「JAAS リファレンスガイド 」

に詳しく書かれていますので、読んでみるとわかると思います。URLは、javadocが置いてある場所から

「docs\ja\technotes\guides\security\jaas\JAASRefGuide.html」

で参照できます。

読むのが面倒だったり、分らなかったらもう少し情報を追加していただくと説明するほうも楽です。

_________________
MyWeb:http://www.ncad.co.jp/~arai/
プログラミング:http://www.ncad.co.jp/~arai/pro3seminar

[ メッセージ編集済み 編集者: arai 編集日時 2008-06-14 00:16 ]
arare
会議室デビュー日: 2008/06/13
投稿数: 3
投稿日時: 2008-06-16 10:41
あしゅ様、arai様
素人な質問にお付き合い頂き、感謝します。

すみません、webコンテナはoc4jです。

>TextInputCallbackの処理に関しては、未実装だということが読み取れます。
おっしゃる通りです。ログイン処理に関して実装したのはloginmoduleと関連するDBアクセス処理だけです。
安易に考えていて、何をどう実装すればよいのか整理できないままでした。


>まともな方法では無理です。
>「javax.security.auth.callback.CallbackHandler」を一般的に使うには、自分で実装する必要があります。

コールバックハンドラをカスタマイズですが、、私の知識ではなかなか大変そうです。
要件はログイン画面の遷移元の取得だけなんですが。

フィールドを追加して取得するということ自体、一般的な方法ではないのでしょうか?
arai
会議室デビュー日: 2008/06/13
投稿数: 2
投稿日時: 2008-06-18 23:51
>すみません、webコンテナはoc4jです。
oc4jは使ったことはありませんが、Strutsは使ったことがあります。サーブレット・JSPやStrutsでは、web上から値を取得するのに、「HttpServletRequest#getParameter」や「DynaForm#get」のように取得します。doGetやdoPostからの取得です。

認証処理で使われている実装は関係ないと思います。
oc4jで<input type="hidden" name="ref"> からの取得は、どのように取得するか分かりませんが、必ずどこかで指定しているはずです。その処理を
CallbackHandler#handleに記述する必要があります。

サンプルとして、コンソール処理ですが

http://ncad.co.jp/~arai/pro3seminar/temp/JAAS.zip

から取得できます。追加する部分を「TODO」コメントしましたので、参考にしてください。また、開発はEclipseで試しましたので、Eclipseでそのまま使用できるのでインポートなどで試してみてください。

メインが「sample.SampleAcn」で実行するには、VM引数に

-Djava.security.auth.login.config==sample_jaas.config sample.SampleAcn

を指定する必要があります。

実行すると、

user name: testUser
password: testPassword
refー>

が表示されて、ソースをみると分かりますが、「user name: 」に「testUser」を「password: 」に「testPassword」を入力すると正常に処理が終了します。間違った値を入力すると再度入力が求められ、3回失敗で処理が終了します。

具体的な処理は、
「// TODO ここに行いたい処理を追加」
のTODOコメントに記述することになります。
_________________
MyWeb:http://www.ncad.co.jp/~arai/
プログラミング:http://www.ncad.co.jp/~arai/pro3seminar
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2008-06-19 22:35
引用:

araiさんの書き込み (2008-06-18 23:51) より:
認証処理で使われている実装は関係ないと思います。
oc4jで<input type="hidden" name="ref"> からの取得は、どのように取得するか分かりませんが、必ずどこかで指定しているはずです。その処理を
CallbackHandler#handleに記述する必要があります。



無駄だと思いますよ。

OC4Jは独自実装のServletコンテナなので違うかもしれませんが、
LoginModuleからHttpServletRequestにアクセスする手段がないです。

#OC4J固有のAPIからアクセスできる可能性もあるので不可能とは言いません。

================================================================

否定してばっかじゃしょうがないので提案もしておきます。

<input type="hidden">なフィールドを追加したいだけですので、
区切れるようにエスケープしつつj_usernameとrefのデータを繋げて
j_usernameとして送信し、LoginModule側で分解すればよいのでは?
arare
会議室デビュー日: 2008/06/13
投稿数: 3
投稿日時: 2008-06-20 09:17
arai様、あしゅ様

度々、ありがとうございます。


>LoginModuleからHttpServletRequestにアクセスする手段がないです。
確かに、そうですね。


分からないなりに調べて、何とかやってみようとしたのですが、無理ですね。
oc4jが暗黙的にLoginContextのインスタンスを生成するのだと思うのですが
CallbackHandlerを実装して、インスタンス生成時のパラメータとして
指定してやることができるのか。
そんなことできるわけなく、、。

あしゅ様が提案された方法も当初考えていたのですが、ユーザIDに連結するというのが何となく嫌で他の方法を探していました。
ユーザIDとパスワード以外の情報をログイン時に取得したい場合は、どんな手段があるのかというのにも興味がありましたし。

ですが、今回調べてみて難しいということが分かったので、結局、usernameでの連結・分解で実装しました。


arai様
サンプルまで提示して頂いて、ありがとうございます。
すみません、まだ拝見してません。
知識不足なので理解できるかは謎ですが、一度確認していみたいと思います。


1

スキルアップ/キャリアアップ(JOB@IT)