Glassfish v2 WebアプリケーションでのJAASアプリケーション

今回は、WebアプリケーションでのJAAS(Java Authentification and Authorization Service)の使用について書きたいと思います。 開始するには、Webリソースと承認への簡単なアクセス制御を検討してください。 主なアイデアを明らかにするとともに、展開方法のヒントを示します(テキストの後で問題の内容が明らかになります)。







練習に移る前に、いくつかの基本概念とWebリソースへのアクセス制御の一般的なスキームを強調する必要があります。



Webコンテナが接続されているすべてのマシンのセッションを「スニッフィング」すると、 ロールユーザープリンシパルをそのような各セッションに関連付けることができます。 各役割は、特定のアクション( 特権アクション )の実装だけでなく、特定のWebリソースセットにアクセスする能力または能力に関連付けられています。



最初は、ユーザーセッションはユーザープリンシパルやロールに関連付けられていません。 つまり、Webリソースの特定のセットへのアクセスに制約が課せられている場合、これらのリソースへのアクセス権はありません。



ユーザーセッションが役割の何らかのセットに関連するようになるために、ユーザーは認可されなければなりません。



許可はJAASを使用して実行されます。 承認中に、ユーザーは自分の資格情報資格情報 、単純な場合はログイン:パスワードまたはユーザー証明書)を送信します 。 サーバーでは、2つのエンティティ、つまりRealmLogin Moduleが制御プロセスに接続されています。 ログインモジュールは、ユーザーグループの特定のセットとのユーザーの接続を確認します( ロールと混同しないでください)。 さらに、認証は成功する可能性がありますが、ユーザーはどのグループにも関連付けられていない可能性があります。



Webアプリケーションは、 グループロール間の関係を決定できます 。 アプリケーションは、sun-web.xmlを使用してこの対応を設定します。



ログインモジュールレルムはWebアプリケーションの一部ではありませんが、アプリケーションサーバーの共有リソースであるため、サーバークラスパスにあり、サーバー(login.confおよびdomain.xml)に正しく登録されている必要があります。 アプリケーションはweb.xmlを介して名前でレルムを選択します。



アプリケーションは、web.xmlを介したリソースへのアクセスに関する一連の制限を定義し、次のことを示します。どのWebリソース(URLパターン)がどのタイプのリクエスト(get、post、headなど)およびroleで利用できるか。 さらに、アプリケーションは認証方法を決定します。 たとえば、ログインページを指定したり、標準のHTTP認証の使用を指定したりできます(ブラウザに認証ウィンドウが表示されます)。



Webコンテナは制限の実行の背後にあるため、アプリケーションは追加のチェックを実行する必要がありません。 URLパターンには制限が課せられているため、このパターンに該当するものは、サーブレット、JSP、または何でも(404)に関係ありません。 何も(404)でなく、ユーザーが何らかの役割を持っていることを制限が要求している場合でも、ユーザーはそこに何も存在しないことを確認するために承認を受ける必要があります。



レルムは、 ログインモジュールに関連付けることができます。 これを行うには、特別なペア「jaas-context」->「login-module-name」がプロパティでそれを示します。 レルムログインモジュールがペアでしか機能しない場合があります。 たとえば、 Login ModuleRealmを記述したい場合、 RealmLogin Moduleのみで動作させ、他では動作させないようにすることは非常に可能です。



たとえば、パスワード認証用の単純なペアを作成します。

Realmを書くことから始めましょう:

パブリッククラスTestRealmはAppservRealmを拡張します{

     @Override
     public String getAuthType(){
         return "magic";
     }

     @Override
     public Enumeration getGroupNames(String string)throws InvalidOperationException、NoSuchUserException {
         Collections.enumeration(Arrays.asList( "users"、 "guests"))を返します。
     }

     @Override
     protected void init(プロパティプロパティ)がBadRealmException、NoSuchRealmExceptionをスローします{
         super.init(小道具);

         System.err.println( "Realm :: Hello !!");

         if(props.containsKey(JAAS_CONTEXT_PARAM))
             setProperty(JAAS_CONTEXT_PARAM、props.getProperty(JAAS_CONTEXT_PARAM));
     }

     @Override
     public AuthenticationHandler getAuthenticationHandler(){
         nullを返します。
     }

 }





getGroupNamesメソッドは、可能なグループを含む enumを返します。 initメソッドは、初期化中(実際には、ドメインの開始時)に呼び出されます。 その中で、必要な初期化を実行できます(たとえば、小道具から必要なパレットを取得し、後で使用するためにどこかに保存します)。 JAAS_CONTEXT_PARAMプロパティ( "jaas-context")を渡すことを忘れないことが非常に重要です。そうしないと、レルムが機能しません。



次に、 ログインモジュールについて説明します。 パスワード認証を使用します。

パブリッククラスTestLoginModuleはAppservPasswordLoginModuleを拡張します{

     @Override
     protected void authenticateUser()throws LoginException {
         if(_username == null || _password == null)
            新しいLoginExceptionをスローします(「パスワードのユーザー名がnull」)。

         if( "user" .equals(_username)&& "user-pass" .equals(_password))
             commitUserAuthentication(新しい文字列[] {"ユーザー"});
         else if( "guest" .equals(_username)&& "guest" .equals(_password))
             commitUserAuthentication(新しい文字列[] {"guests"});
        他に
            新しいLoginException(「不正なログイン/パスワード」)をスローします。
     }

 }




この例では、パスワードオプションを「ハンマー」で押しました。 代わりに、データベースまたはLDAPサーバー、あるいはその両方を「尋ねる」ことができます。



ビルド後、2つのクラスを持つ単純なjarを取得します(クラスパスでビルドを成功させるには、javaee.jar、appserv-rt.jar、appserv-ext.jar、およびglassfish-v2 / libディレクトリが必要です)。



アセンブリの後、jarをドメインのlibディレクトリなどに配置できます。



次に、 レルムログインモジュールをドメインに登録する必要があります。

開始するには、.jarがサーバーのクラスパスにあることを確認する必要があります。 これを適切に行う方法はおそらくいくつかありますが、トピックに関するドキュメントでは特定の方法について説明しているので、それを使用します。



domain.xmlファイルには、とりわけ、jvmパラメーターが記述されています。 そこで、java-configタグを見つけることができます。 classpath-suffix属性があります。 通常は空です。 これは、「適合する」必要がある場所です。

例:

 ...
 <java-config classpath-suffix = "/ home / cy6ergn0m / .domains / domain1 / lib / MyTestRealm.jar" ...
 ....




その後、 Login Moduleを追加する必要があります。 これは、ドメインディレクトリ(domain_dir / conf / login.conf)のテキストファイルlogin.confで行われます。 たとえば、次のように最後に追加するだけです。

 testRealmLM {
         cy6ergn0m.auth.TestLoginModuleが必要です。
 };





ログイン方法が説明されたら、名前付きRealmを登録できます。 domain.xmlまたはWeb管理コンソールから追加できます。 これはdomain.xmlを使用して行います。



トップレベルのタグの中に、security-serviceタグがあります。 通常、すでにいくつかのauth-realmタグがあります。 そこに独自のものを追加します。 ただし、タグは既に存在するauth-realmsの後にあることが重要です。 domain.xmlスキーマでは、auth-realmsが先頭にある必要があります。

 <auth-realm classname = "cy6ergn0m.auth.TestRealm" name = "testRealm">
           <プロパティ名= "jaas-context"値= "testRealmLM" />
           <プロパティ名= "auth-type"値= "magic" />
 </ auth-realm>




パラメーター(プロパティ)の中では、他のものを渡すことができます。 これらのプロパティはRealmの initメソッドに分類されます。 ここで、たとえば、サーバーのアドレス\ポートまたはその他の設定を配置できます。



また、複数のレルムを作成できますが、パラメーターは異なることに注意してください。 次に、ログインモジュールは 、_currentRealm保護フィールドを使用して、どのレルムがそれを使用しているかを常に確認できます。 また、そのような方法で、彼はレルム(ホスト、ポートなど)から特定の設定を取得できます。



ここで、ドメインを再起動する必要があります。 ログでドメインが開始されると、「Realm :: Hello !!」というエントリが表示されます。 これが起こらなかった場合、おそらくあなたは何か間違ったことをしました。



これで、承認モジュールを使用する準備が整いました。 使ってみよう。



これを行うには、モジュールを使用する小さなWebアプリケーションを作成します。



いくつかのWebページを作成します。最初に、index.html、secret.html、for-guests.htmlの3つを実行します。

index.htmlから他の2つへのリンクを作成します。



その後、「極秘」ページへのアクセスを制限します。 これを行うには、web.xmlおよびsun-web.xmlファイルを編集します。



承認モジュールは、「ユーザー」と「ゲスト」という2つのグループのユーザーを承認できます。 これらのグループに対応する2つのロールを作成しましょう。



sun-web.xmlファイルを開き、これらの比率を追加します。 これを行うには、2つの<security-role-mapping>セクションを追加します。



 <?xml version = "1.0" encoding = "UTF-8"?>
 <!DOCTYPE sun-web-app PUBLIC "-// Sun Microsystems、Inc.//DTD Application Server 9.0 Servlet 2.5 // EN" "http://www.sun.com/software/appserver/dtds/sun-web -app_2_5-0.dtd ">
 <sun-web-app error-url = "">
   <context-root> / TestRealmClient </ context-root>
   <security-role-mapping>
     <ロール名>ユーザー</ロール名>
     <グループ名>ユーザー</グループ名>
   </ security-role-mapping>
   <security-role-mapping>
     <ロール名>ゲスト</ロール名>
     <グループ名>ゲスト</グループ名>
   </ security-role-mapping>
   <class-loader delegate = "true" />
   <jsp-config>
     <プロパティ名= "keepgenerated"値= "true">
       <description>生成されたサーブレットクラスのJavaコードのコピーを保持します。</ description>
     </プロパティ>
   </ jsp-config>
 </ sun-web-app>




ここで、web.xmlで使用するロールについて説明します。

     <セキュリティロール>
         <説明/>
         <ロール名>ユーザー</ロール名>
     </ security-role>
     <セキュリティロール>
         <説明/>
         <ロール名>ゲスト</ロール名>
     </ security-role>




これで、 制約を作成できます。 これを行うには、web.xmlを修正し、それに制限を追加します。

     <セキュリティ制約>
         <display-name> Constraint1 </ display-name>
         <web-resource-collection>
             <web-resource-name>シークレット</ web-resource-name>
             <説明/>
             <url-pattern> / secret * </ url-pattern>
         </ web-resource-collection>
         <auth-constraint>
             <説明/>
             <ロール名>ユーザー</ロール名>
         </ auth-constraint>
     </ security-constraint>
     <セキュリティ制約>
         <display-name> Constraint2 </ display-name>
         <web-resource-collection>
             <web-resource-name>ゲスト</ web-resource-name>
             <説明/>
             <url-pattern> / for-guests * </ url-pattern>
         </ web-resource-collection>
         <auth-constraint>
             <説明/>
             <ロール名>ゲスト</ロール名>
             <ロール名>ユーザー</ロール名>
         </ auth-constraint>
     </ security-constraint>




したがって、/ secret *ページへのアクセスはuser roleを持つユーザーのみに、アドレス/ for-guests *はuserおよびguestのロールを持つユーザーに対してのみ行うことを決定しました。 つまり、ユーザーロールを持つユーザーはすべてのページにアクセスでき、ゲストロールを持つユーザーはindex.htmlとfor-guests.htmlのみ、「nobody」のみはindex.htmlにアクセスできます。



次に、 レルムと認証方法を指定する必要があります。 まず、簡単な方法(HTTP認証)-BASICを選択します。 これを行うには、web.xmlで次を指定します。

     <login-config>
         <auth-method> BASIC </ auth-method>
         <realm-name> testRealm </ realm-name>
     </ login-config>




したがって、最後に次のweb.xmlを取得します。

 <?xml version = "1.0" encoding = "UTF-8"?>
 <web-appバージョン= "2.5" xmlns = "http://java.sun.com/xml/ns/javaee" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi :schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
     <session-config>
         <セッションタイムアウト>
             30
         </ session-timeout>
     </ session-config>
     <welcome-file-list>
         <welcome-file> index.html </ welcome-file>
     </ welcome-file-list>
     <セキュリティ制約>
         <display-name> Constraint1 </ display-name>
         <web-resource-collection>
             <web-resource-name>シークレット</ web-resource-name>
             <説明/>
             <url-pattern> / secret * </ url-pattern>
         </ web-resource-collection>
         <auth-constraint>
             <説明/>
             <ロール名>ユーザー</ロール名>
         </ auth-constraint>
     </ security-constraint>
     <セキュリティ制約>
         <display-name> Constraint2 </ display-name>
         <web-resource-collection>
             <web-resource-name>ゲスト</ web-resource-name>
             <説明/>
             <url-pattern> / for-guests * </ url-pattern>
         </ web-resource-collection>
         <auth-constraint>
             <説明/>
             <ロール名>ゲスト</ロール名>
             <ロール名>ユーザー</ロール名>
         </ auth-constraint>
     </ security-constraint>
     <login-config>
         <auth-method> BASIC </ auth-method>
         <realm-name> testRealm </ realm-name>
     </ login-config>
     <セキュリティロール>
         <説明/>
         <ロール名>ユーザー</ロール名>
     </ security-role>
     <セキュリティロール>
         <説明/>
         <ロール名>ゲスト</ロール名>
     </ security-role>
 </ web-app>




netbeansのweb.xmlエディターでは、これは次のようになります。



netbeansのweb.xml



できた これで、アプリケーションを起動して確認できます。 リンクの1つをクリックしようとすると、認証ウィンドウが表示されます。



タスクを複雑にしましょう。 自分でログインページを作りたいとしましょう。



これは2つの方法で実現できます。 両方を検討しましょう。



まず、web.xmlの認証方法を変更する必要があります。 以前は、BASIC認証方法を指定していました。 次に、ログインフォームを選択します。

     <login-config>
         <auth-method> FORM </ auth-method>
         <realm-name> testRealm </ realm-name>
         <form-login-config>
             <form-login-page> /login.jsp </ form-login-page>
             <form-error-page> /login.jsp?fail </ form-error-page>
         </ form-login-config>
     </ login-config>




次に、最初の方法に従ってlogin.jspログインフォームを作成します。

 <%@ page contentType = "text / html" pageEncoding = "windows-1251"%>
 <!DOCTYPE HTML PUBLIC "-// W3C // DTD HTML 4.01 Transitional // EN"
    "http://www.w3.org/TR/html4/loose.dtd">

 <html>
     <head>
         <meta http-equiv = "Content-Type" content = "text / html; charset = windows-1251">
         <title> JSPページ</ title>
     </ head>
     <本体>
         <h1> Hello World!</ h1>

         <h2> Webコンテナーのログインメソッド</ h2>
         <form action = "j_security_check" method = "post">
             <input type = "text" name = "j_username" />
             <input type = "password" name = "j_password" />
             <入力タイプ= "送信" />
         </ form>
     </ body>
 </ html>




できた これで、権限のないユーザーが「安全な」ページにアクセスしようとすると、Webコンテナはログインフォームに「リダイレクト」します。 承認後、ユーザーは必要な役割を受け取り、「保護された」ページにアクセスできます。



場合によっては、承認プロセスをさらに制御する必要があり、制御しないj_security_checkが適切でない場合があります。 この場合、常に2番目の方法を使用できます。 手動でログインできます。 Glassfishは非標準のログインモジュールを使用しているため(偶然、標準のJAASインターフェースの代わりにAppservPasswordLoginModuleを実装していません)、LoginContextを介して通常の認証方法を使用することはできませんが、非標準のサーバーAPIを使用する必要があります(より正確には可能ですが、より複雑で移植性はありません)。



Glassfish API [7]のProgrammaticLoginを使用するLoginServletを作成します。 クラスを表示するには、アセンブリ中にクラスパスにjavaee.jar、appserv-rt.jarおよびappserv-ext.jarファイルを追加する必要があることに注意してください(IDEでも同じことが可能です)。



パブリッククラスLoginServletはHttpServletを拡張します{


     @Override
     protected void doGet(HttpServletRequestリクエスト、HttpServletResponseレスポンス)
             ServletException、IOException {
         response.sendError(HttpServletResponse.SC_FORBIDDEN);
     }

     @Override
     protected void doPost(HttpServletRequestリクエスト、HttpServletResponseレスポンス)
             ServletException、IOException {
         ProgrammaticLogin pl =新しいProgrammaticLogin();
         {
            ブール値rc = pl.login(request.getParameter( "name")、request.getParameter( "pass")、 "testRealm"、request、response、true);
             if(rc!= null && rc.booleanValue()){
                 response.sendRedirect( "index.jsp");
                帰る
             }
         } catch(例外ex){
             Logger.getLogger(LoginServlet.class.getName()).log(Level.SEVERE、null、ex);
         }

         response.sendRedirect( "login.jsp?fail");
     }

     @Override
     public String getServletInfo(){
         return "ログインサーブレット";
     }

 }




そして、login.jspページはそれに応じて変更され、フォームパラメータがLoginSerlvetに送信されます。



 <%@ page contentType = "text / html" pageEncoding = "windows-1251"%>
 <!DOCTYPE HTML PUBLIC "-// W3C // DTD HTML 4.01 Transitional // EN"
    "http://www.w3.org/TR/html4/loose.dtd">

 <html>
     <head>
         <meta http-equiv = "Content-Type" content = "text / html; charset = windows-1251">
         <title> JSPページ</ title>
     </ head>
     <本体>
         <h1> Hello World!</ h1>

         <h2> Webコンテナーのログインメソッド</ h2>
         <form action = "login" method = "post">
             <input type = "text" name = "name" />
             <input type = "password" name = "pass" />
             <入力タイプ= "送信" />
         </ form>
     </ body>
 </ html>




したがって、私たちにとって都合の良い方法で使用できるログインサーブレットを取得します。たとえば、キャプチャを実行したり、ajaxなどでログインを確認したりできます。



結論として、もう1つのポイントを強調したいと思います。 実際のところ、 レルムログインモジュールの登録はそれほど単純でないので、任意のドメインに自動的に登録できるようにしたいと思います。



このアイデアを実装するために、Ant用の独自のカスタムタスクを作成できます。 Javaで記述し、必要なすべてのアクションを実行できます。



公式の義務のために、私は同様のことを書かなければなりませんでしたが、明らかな理由で、私はこのコードをここで与えることができません。 ただし、その内容についていくつかのヒントを示します。 append = trueパラメーターで作成されたFileWriterを使用して、login.confファイルに数行を簡単に追加できます。 domain.xmlの操作はより複雑ですが、XMLです。目に見えるサイズに加えて...したがって、DocumentBuilderを使用してすべてのXMLをDOMツリーに読み込み、ツリーに必要な変更を加え、classpath-suffixとauthを追加できます。 -realm、次にdomain.xmlでDOMツリーをシリアル化します。 入力パラメーターのチェックと一緒に200行以内に抑えることができました。 このタスクは、ドメイン全体を作成するためのant-scriptに含めることができます(ドメインがantによって作成されている場合)。



しかし、glassfish v2ですべてをテストしたという事実にもかかわらず、さまざまな情報源から判断すると、v3にもこれが関連していることが期待できますが、調整が必要になる場合があります。



この難しい記事で終わりました。 もちろん、多くは舞台裏(特権アクション、ユーザープリンシパル)に残っていましたが、このWeb開発の困難なニッチに光を当てることができたことを願っています。



成功。



Cg。



リファレンス別名リンク:



1. Sun Java System Application Serverのカスタムレルムを使用した認証

developers.sun.com/appserver/reference/techart/as8_authentication



2. TomcatでJAASを使用する

www.kopz.org/public/documents/tomcat/jaasintomcat.html



3. JAAS Tomcatログインモジュール

www.owasp.org/index.php/JAAS_Tomcat_Login_Module



4. JavaTM認証および承認サービス(JAAS)。 LoginModule開発者ガイド。

java.sun.com/javase/6/docs/technotes/guides/security/jaas/JAASLMDevGuide.html



5. Sun GlassFish Enterprise Server v3アプリケーション開発ガイド

第5章アプリケーションの保護

docs.sun.com/app/docs/doc/820-7695/beabg?l=en&q=glassfish+JAAS&a=view



6. j_security_checkを介したWebログインに関するフォーラムスレッド

www.sql.ru/Forum/actualthread.aspx?tid=624508



7. JavadocクラスProgrammaticLogin

glassfish.dev.java.net/nonav/docs/v3/api



8. Sun GlassFish Enterprise Server v3アプリケーション開発ガイド

プログラムによるログイン

docs.sun.com/app/docs/doc/820-7695/beacm?l=en&a=view



9. OC4J 10.1.3でのADF FacesアプリケーションのJAASベースの認証および認可の実装

technology.amis.nl/blog/1426/implement-jaas-based-authentication-and-authorization-for-adf-faces-applications-on-oc4j-1013



10. JAASを使用したGlassfishでのWebアプリケーションの保護-パート1および2

www.developinjava.com/features/47-enterprise-java/105-securing-a-web-application-on-glassfish-using-jaas.html

www.developinjava.com/features/47-enterprise-java/106-securing-a-web-application-on-glassfish-using-jaas-pt-2.html



11. Glassfish javadoc:クラスAppservRealm

glassfish.java.net/nonav/javaee5/api/com/sun/appserv/security/AppservRealm.html



All Articles