5

私はJAASを研究しており、TomcatとJaasRealmを使用してWebアプリで使用する簡単な例を実装しています。

Subject subject = Subject.getSubject(AccessController.getContext());今私の問題は、のようなコードが常にnullを返すため、件名を取得する方法がわからないことです。

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

4

2 に答える 2

9

私はそれを知っていました、そしてそれはうまくいきます、しかし私はまたroleprincipalを得るために主題を検索する必要があります

残念ながら、JavaEEではそのようには機能しません。JAASサブジェクトは単なる「プリンシパルのバッグ」であり、ユーザー/呼び出し元のプリンシパルおよび/またはロールプリンシパルを表すものはどれも標準化されていません。他のすべてのコンテナは、ここで異なる動作をします。TomcatのJAASRealmのJavadocはこれを説明し、Tomcat固有の規則を説明しています(私の強調):

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

その上、Java EE環境から、JAASサブジェクトにアクセスすることはめったになく、ベンダー固有の方法を介してさえもアクセスできないことがよくあります。JAASは、特にJava EEに関係する場合、あなたが思っているような普遍的な標準からはほど遠いものです。

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

たとえば、JBoss ASは、独自のクラスを使用してこのプリンシパルを数回コピーします。したがって、JAASモジュールkaz.zak.FooPrincipalがユーザー/呼び出し元プリンシパルのサブジェクトにを格納した場合、はをHttpServletRequest#getUserPrincipal()返す可能性がありorg.jboss.security.SimplePrincipalます。保証される唯一のことは、getName()そのインスタンスで同じ文字列を返すことです。

このトピックに関するその他の背景については、以下をご覧ください。

最後の情報源は基本的に同じことを別の言い回しで言っています。

Tomcat内で認証メカニズム(JAASRealm)としてJAASを使用することは可能ですが、ユーザーが認証されると、JAASフレームワークの柔軟性は失われます。これは、プリンシパルが「ユーザー」と「ロール」の概念を示すために使用され、Webアプリケーションが実行されるセキュリティコンテキストでは使用できなくなったためです。認証の結果は、request.getRemoteUser()およびrequest.isUserInRole()を介してのみ利用できます。

これにより、承認を目的としたJAASフレームワークが、Javaセキュリティポリシーとの接続を失う単純なユーザー/ロールシステムになります。

于 2012-11-11T12:32:14.997 に答える
0

サブジェクトを取得するには、LoginModuleとValveの組み合わせを使用できます。認証が開始される前にバルブが呼び出されるという事実は、ここで私たちを助けています。バルブが呼び出されると、セッションがThreadLocalに配置され(JBOSSが要求をThreadLocalに保存する方法と同様)、後でLoginModule.commit()が呼び出されると、サブジェクトがセッションに保存されます。

これを構成するには、以下のクラスのコンパイル済みコードをjarに追加し、$ 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;
    }
}

$ CATALINA_BASE / conf / server.xmlで、次のValve構成を要素の子として追加します。

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

jaas.configファイルで、LoginModuleと同じクラスを追加します。

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

ログイン後、以下を使用して認証済みサブジェクトを取得できます。

session.getAttribute( ContainerServices.SUBJECT_KEY );
于 2015-09-24T03:51:50.367 に答える