2009-04-05 16 views
13

Webサービスを介してログインを実行する必要のあるJava Webアプリケーションを作成しています。もちろん、私が使用しているアプリケーションサーバー(glassfish v2)で提供されている領域のいずれも、このトリックを行うことはできません。私は自分自身を書く必要があった。しかし、私が書いたレルムの実装は、グラスフィッシュと完全に結びついているため、他のアプリケーションサーバーと同じように使用することはできません。Java Webアプリケーション:カスタム領域の使用

カスタムレルムを実装する標準または広くサポートされている方法はありますか?それはどのようにして.warからそのレルムを展開することが可能か、それとも常にサーバのクラスパスからロードする必要がありますか?

+0

あなたのレルムコードの例を投稿できますか? –

答えて

9

注:以下の回答は、Java EE 5にのみ有効です。その他の回答の1つに注目したように、Java EE 6はこれをサポートしています。したがって、Java EE 6を使用している場合は、この回答を読まずに、他の関連する回答をお読みください。

JAASは標準インターフェースですが、JAAS Realm + LoginModuleをさまざまなアプリケーションサーバーに記述、配置、統合する統一された方法はありません。

Glassfish v2では、LoginModuleまたはRealm自体を実装する独自の内部クラスの一部を拡張する必要があります。ただし、LoginModuleインターフェイスの多くのメソッドがGlassfishのスーパークラスでfinalとマークされているため、ログインプロセス全体をカスタマイズすることはできません。カスタムLoginModuleクラスとRealmクラスはASクラスパスに配置する必要があり(アプリケーションのものではない)、レルムを手動で登録する必要があります(可能であれば.warからのデプロイメントなし)。

Tomcatでは、独自のRealmとLoginModuleを完全にコーディングできるようになり、独自のJAASRealmを使用してアプリケーションサーバーに構成できるようになります(実際の作業を実装に委譲します)。レルムとLoginModule)。しかし、Tomcatでも、.warからカスタムレルムを展開することはできません。

結果が表示されたアプリケーションサーバーは、すべてのJAASコールバックを最大限に活用できないようです。それらのすべては、基本的なユーザ名+パスワード方式だけをサポートしているようです。それより複雑なものが必要な場合は、Java EEコンテナによって管理されていないソリューションを見つける必要があります。

参考のために、私の質問にコメントで尋ねられたので、ここにGlassFish V2のために書いたコードがあります。

まず第一に、ここでのレルムの実装です:

public class WebserviceRealm extends AppservRealm { 

private static final Logger log = Logger.getLogger(WebserviceRealm.class.getName()); 

private String jaasCtxName; 
private String hostName; 
private int port; 
private String uri; 

@Override 
protected void init(Properties props) throws BadRealmException, NoSuchRealmException { 
    _logger.info("My Webservice Realm : init()"); 

    // read the configuration properties from the user-supplied properties, 
    // use reasonable default values if not present 
    this.jaasCtxName = props.getProperty("jaas-context", "myWebserviceRealm"); 
    this.hostName = props.getProperty("hostName", "localhost"); 
    this.uri = props.getProperty("uri", "/myws/EPS"); 

    this.port = 8181; 
    String configPort = props.getProperty("port"); 
    if(configPort != null){ 
     try{ 
      this.port = Integer.parseInt(configPort); 
     }catch(NumberFormatException nfe){ 
      log.warning("Illegal port number: " + configPort + ", using default port (8181) instead"); 
     } 
    } 
} 

@Override 
public String getJAASContext() { 
    return jaasCtxName; 
} 

public Enumeration getGroupNames(String string) throws InvalidOperationException, NoSuchUserException { 
    List groupNames = new LinkedList(); 
    return (Enumeration) groupNames; 
} 

public String getAuthType() { 
    return "My Webservice Realm"; 
} 

public String getHostName() { 
    return hostName; 
} 

public int getPort() { 
    return port; 
} 

public String getUri() { 
    return uri; 
} 
} 

そしてLoginModule実装:

public class WebserviceLoginModule extends AppservPasswordLoginModule { 

// all variables starting with _ are supplied by the superclass, and must be filled 
// in appropriately 

@Override 
protected void authenticateUser() throws LoginException { 
    if (_username == null || _password == null) { 
     throw new LoginException("username and password cannot be null"); 
    } 

    String[] groups = this.getWebserviceClient().login(_username, _password); 

    // must be called as last operation of the login method 
    this.commitUserAuthentication(groups); 
} 

@Override 
public boolean commit() throws LoginException { 
    if (!_succeeded) { 
     return false; 
    } 

    // fetch some more information through the webservice... 

    return super.commit(); 
} 

private WebserviceClient getWebserviceClient(){ 
    return theWebserviceClient; 
} 
} 

は最終的に、レルムにログインモジュールに接続する必要があります。これはJAAS設定ファイルレベルで行われます。このレベルは、glassfish v2ではyourDomain/config/login.confにあります。そのファイルの末尾に次の行を追加します。

myWebserviceRealm { // use whatever String is returned from you realm's getJAASContext() method 
    my.auth.login.WebserviceLoginModule required; 
}; 

これは、グラスフィッシュで私のために働いているものです。ここでも、このソリューションはアプリケーションサーバー間で移植できませんが、私が知る限り、既存のポータブルソリューションはありません。

-2

チェックアウトSun's article on this subject

私は決して実際にこれを自分ではしませんでしたが、各ASは新しい領域(セキュリティドメイン)を登録するオプションをあなたに提供しています。

これはおそらく100%移植性がなく、各ASには異なる設定XMLが必要かもしれませんが、基本的にはコードが異なる可能性はありません。

1

Apps固有のクラスを拡張するカスタムLoginModuleを記述する必要があるように、Sunsのマニュアルを簡単に見ています。これは私にとって少し後退し、グラスフィッシュの限界と思われます。

これを移植性の高いものにしたい場合は、標準のJavaEEインターフェイスに対して開発されたカスタムLoginModuleに大量の実装を置き、Glassfish固有のシン・インプリメンテーション・レイヤーを持つことをお勧めします。標準の移植可能な実装です。

+0

ええ、それはすでに私がやったことです。これはかなり馬鹿だと感じたので、私は他の方法があるかどうか疑問に思っていました。しかし、それ以外の方法はないようです(少なくともグラスフィッシュではありません) – LordOfThePigs

+0

ええ、私はJBoss用にこのハッキーを書いたときに何かをしなければならないことを覚えていません。私はこれを助けることができませんでした – BenM

2

レルムはアプリケーションアーティファクトではなく、コンテナアーティファクト(したがってコンテナベースのセキュリティというフレーズ)であるため、WARからレルムを展開することはできません。コンテナが提供する特定の領域を使用するようにアプリケーションを設定することはできますが、アプリケーションはそれを提供できません。

しかし、すべてのコンテナは異なっていますが、これらの領域はポータブルではありません。ポータブル性を求めている場合は、コンテナとの統合に必要な少しのグルーコードとの違いを軽減します。

+1

私はこれが非常に古い答えだと知っていますが、2009年にも、 'realm'(または名前自体が標準化されていないため、戦争や耳の中にいること。少なくともJBoss ASはこれをバージョン5から、おそらく以前から許可しました。 –

6

カスタムを実装する標準または広くサポートされている方法はありますか レルムですか? .warからその領域を展開することは可能ですか? サーバのクラスパスから常にロードする必要がありますか?

カスタムレルムを実装する標準的な方法、またはより一般的な用語としてカスタム認証モジュールが絶対にあります。これはJASPIC/JASPI/JSR 196 SPI/APIで行うことができます。 JASPICは、完全なJava EE 6実装の標準的な部分ですが、残念ながらJava EE 6 Webプロファイルの一部ではありません。

しかし、JASPICがJava EE 6の一部であるにもかかわらず、それはベンダーによって最適にサポートされていません。 GlassFishとWebLogicは非常に優れた実装を行っているようですが、JBoss ASとGeronimoはもう少し問題があります。 JBossの主任エンジニア(Anil Saldhana)は、このトピックについては、refuses to activate JASPIC by defaultとしています。 Jboss AS 7.1の最も深刻なバグのいくつかはrecently fixedでしたが、JBoss 7.1.xの公開リリースはもうなくなり、JBoss AS 7.2はまだまだ離れているため、少なくともJBossではJASPICは面倒です。

もう一つの不幸な問題は、実際の認証モジュールが標準化されている可能性がありますが、標準化するための宣言的な方法(XMLファイルを読む)がないことです。

どのようにしても、そのレルムを.warから展開することは可能ですか、それとも は常にサーバーのクラスパスからロードする必要がありますか?

JASPICでは、認証モジュール( 'realm')を実際に.warから読み込むことができます。私はこれが仕様で保証されているかどうかは100%確信していませんが、私がテストした4台のサーバー(GlassFish、WebLogic、Geronimo、およびJBoss AS)ではすべてサポートされています。 Geronimoは残念なことに、プログラム登録に何らかの競合状態を抱えているので、2度のホットデプロイメントを行うことで醜い回避策が必要ですが、最終的には.warからモジュールをロードすると最終的に回避されます。

独自のメカニズムとして、少なくともJBoss ASは、.warまたは.earからモジュール(たとえばorg.jboss.security.auth.spi.AbstractServerLoginModuleのサブクラス)をロードすることを常にサポートしています。

I wrote a blog postこのトピックについてもう少し詳しく説明します。

+0

クール!これはJ2EE 6の新機能ですか? J2EE 5では不可能だと確信していたので、 – LordOfThePigs

+0

@LordOfThePigsが最初に踏み台になっていましたが、J2EE 5でも6でも決してありませんでした。それはJava EEになりました;しかし、実際JASPICはJava EE 6仕様自体は長い歴史を持ち、Java EE 6より前にリリースされました。スタンドアロンの仕様として、ベンダーは自主的に実装することができました。これは、認証モジュールの移植性をすべてのベンダーにもたらすことを目的とした仕様ではあまり意味がありません。 –

関連する問題