2012-10-25 13 views
5

私はJAASを勉強しています。私はJaasRealmでTomcatを使ってWebアプリケーションで使う簡単な例を実装しています。Tomcat-Jaas - 件名の取得方法

私の問題は、Subject subject = Subject.getSubject(AccessController.getContext());のようなコードは常にnullを返すので、件名の取得方法がわかりません。

私はTomcat 7.0.27を使用しています。私が見逃したことはありますか? JAASを使用してJava EEで権限を管理するにはどうすればよいですか?たとえば、JAASの安全なコンテキスト内でアクションを実装するにはどうすればよいですか?

+0

、あなたが(サーブレットAPIの 'HttpServletRequest.getUserPrincipalを試すことができ、自分のレルムは、Webアプリケーションのために使用されていることを確認してください)' –

+0

は、私はそれを知っていたし、それが動作しますが、私はまた、 – sasaman85

答えて

8

が、私はそれを知っていたし、それが動作しますが、私も残念ながら

をroleprincipal取得の対象と取得する必要があり、それは、Java EEでそのように動作しません。 JAAS Subjectは単に「プリンシパルのバッグ」であり、ユーザー/発信者のプリンシパルおよび/またはロールプリンシパルを表すものはどれも単純に標準化されていません。他のすべてのコンテナは、ここでさまざまなことを行います。 Javadoc for Tomcat's JAASRealmは、このことを説明し、Tomcatの特定の大会(強調鉱山)説明:

JAAS仕様がゼロ以上 を含めることができ のjavax.security.auth.Subjectインスタンスとしてログインに成功し、その結果を説明しますjava.security.Principalオブジェクトは、 Subject.getPrincipals()メソッドの戻り値に含まれます。しかし、それは個々のユーザを記述する(かつ は、Webアプリケーションで request.getUserPrincipal()の値として返すすることが適切である)プリンシパル(S) からプリンシパルを区別する方法 にはガイダンスを提供しないことこのユーザーの許可された役割を記述します。 JAASで実行される基礎となるLoginMethod 実装からできるだけ多くの 独立性を維持するために、次のポリシーは、このレルムで が実装されます。それ以外にも[...]

、Java EEの環境からあなためったにでもベンダー固有の方法でさえもしばしばJAAS Subjectにアクセスすることはできません。 JAASは普遍的な標準からは離れていますが、特にJava EEに関係していると思われるようです。

ポータブルな方法でアクセスできるのは、呼び出し元プリンシパルとそれに関連付けられたロールだけですが、JAASログインモジュールが構築した呼び出し元プリンシパルである必要はありません。

たとえば、JBoss ASは、このプリンシパルを独自のクラスを使用して何度かコピーします。したがって、JAASモジュールがkaz.zak.FooPrincipalをユーザー/呼び出し元プリンシパルのSubjectに格納した場合、HttpServletRequest#getUserPrincipal()org.jboss.security.SimplePrincipalを返すことがあります。保証されるのは、そのインスタンスのgetName()が同じ文字列を返すということだけです。このトピックに関するいくつかのより多くの背景については

最後のソースは、基本的に異なる言い回しで、同じことを言います。

、認証 機構(JAASRealm)としてTomcat内でJAASを使用することも可能であるが、ユーザが認証されると、JAASフレームワークの柔軟性が が失われます。これは、プリンシパルが という概念が "user"と "role"の概念を表すために使用され、webappが実行されるセキュリティコンテキストで利用可能な でなくなったためです。 の認証結果は、 request.getRemoteUser()およびrequest.isUserInRole()を介してのみ使用できます。

これは、Javaセキュリティ ポリシーとの接続が失われた単純な ユーザ/ロールシステムへの許可目的で、JAASフレームワークを縮小します。

+0

感謝をroleprincipal取得する対象取得する必要がありますしかし、私はJaas認可をtomcat(doaの使用など)とどのように結びつけるのか分かりません。 – sasaman85

+0

通常は、JAASなどを利用してコンテナの契約を満たすコンテナ固有のログインモジュールを作成します。プログラムでログイン(HttpServletRequest#login)または保護されたリソースにアクセスすると、認証が行われ、コンテナはこれを認識します。 web.xml()の制約により、Webページなどのリソースが保護されます。認可は、要求された役割を、認証されたユーザーが持つ役割と比較することによって行われます。一致した場合、ユーザーは承認されます。 –

+0

p.s. TomcatのJAASRealmはJASPICのプロトタイプです。私はこの経験はありませんが、サーブレットプロファイルとブリッジプロファイルの間には何かのようなものがあります。 –

0

Subjectを取得するには、LoginModuleとValveの組み合わせを使用できます。認証が始まる前にバルブが呼び出されたという事実が私たちをここに助けてくれます。バルブが呼び出されると、セッションはThreadLocalに入れられます(JBOSSがThreadLocalに要求を保存する方法と同様)、LoginModule.commit()が呼び出されたときにサブジェクトをセッションに保存します。 jarファイルに以下のクラスのために、このアドオンコンパイルされたコードを設定して、$ CATALINA_BASE/confに/ server.xmlの

/$ CATALINA_BASE/libに
package my.test; 

import java.io.IOException; 
import java.util.Map; 

import javax.security.auth.Subject; 
import javax.security.auth.callback.CallbackHandler; 
import javax.security.auth.login.LoginException; 
import javax.security.auth.spi.LoginModule; 
import javax.servlet.ServletException; 

import org.apache.catalina.Session; 
import org.apache.catalina.connector.Request; 
import org.apache.catalina.connector.Response; 
import org.apache.catalina.valves.ValveBase; 

/** 
* Use following class to retrieve subject in your HTTPServlet when using Tomcat. 
*/ 
public class ContainerServices extends ValveBase implements LoginModule { 

    // Key to revtieve subject from session. 
    public static final String SUBJECT_KEY = 
     "javax.security.auth.Subject.container"; 

    /** 
    * Session for current thread. 
    */ 
    static InheritableThreadLocal<Session> sessionHolder = 
     new InheritableThreadLocal<Session>(); 

    // JAAS Subject being authenticated. 
    private Subject subject; 

    // Invoke the value. 
    public void invoke(Request request, Response response) throws IOException, 
      ServletException { 

     sessionHolder.set(request.getSessionInternal(true)); 

     try { 
      // Next in the invocation chain 
      getNext().invoke(request, response); 
     } finally { 
      sessionHolder.remove(); 
     } 
    } 

    // Initialize the login module 
    public void initialize(Subject subject, CallbackHandler callbackHandler, 
     Map<String, ?> sharedState, Map<String, ?> options) { 
     this.subject = subject; 
    } 

    // Store subject to session. 
    public boolean commit() throws LoginException { 

     Session session = sessionHolder.get(); 

     if (session != null) { 
      session.getSession().setAttribute(ContainerServices.SUBJECT_KEY, subject); 
     } 

     return true; 
    } 

    // not used 
    public boolean abort() throws LoginException { 
     return false; 
    } 

    // not used 
    public boolean login() throws LoginException { 
     return true; 
    } 

    // not used 
    public boolean logout() throws LoginException { 
     return true; 
    } 
} 

の下に配置する

は、要素の子としてバルブの設定を次のように追加します。 jaas.configファイルで

<Valve className="my.test.ContainerServices" /> 

のLoginModuleと同じクラスを追加します。今

DummyAppLogin { 
    my.test.ContainerServices required debug=true; 
    my.test.DummyAppLoginModule required debug=true; 
}; 

はログイン後、認証されたSubjectは以下のものを使用して取得することができます。

session.getAttribute(ContainerServices.SUBJECT_KEY); 
関連する問題