2016-03-23 14 views
3

私は、さまざまな場所からWebアプリケーションのリスト(リストは展開によって異なります)を反復処理する埋め込みJettyサーバーを持っています。私は基本認証からフォーム認証に移行しようとしています。これは、必要に応じて、一つだけのWebアプリケーションがWebアプリケーションであるかどう動作しますが、複数が存在する場合、あなたはあなたが続くたびにサインインするように求められますWebAppContextの複数のインスタンスを持つシングルサインオンの吹き出し

// create constraint 
Constraint usersOnly = new Constraint(Constraint.__FORM_AUTH, "user"); 
usersOnly.setAuthenticate(true); 
ConstraintMapping requireAuthentication = new ConstraintMapping(); 
requireAuthentication.setConstraint(usersOnly); 
requireAuthentication.setPathSpec("/*"); 

// create login service 
LoginService loginService = new HashLoginService("realm"); 
loginService.setConfig("users.txt"); 

// create form authentication 
FormAuthenticator formAuthenticator = new FormAuthenticator("/login", "/login", true); 

// create /login route 
ServletHolder loginServlet = new ServletHolder(new DefaultServlet() { 
@Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    response.getWriter().append("<html>\n<head>\n<title>Login</title>\n</head>\n<body>\n" 
    + "<form method='POST' action='/j_security_check'>\n" 
    + "<input type='text' name='j_username'/>\n" 
    + "<input type='password' name='j_password'/>\n" 
    + "<input type='submit' value='Login'/>\n</form>\n</body>\n</html>\n"); 
    } 
}); 

ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler(); 
securityHandler.addMapping(requireAuthentication); 
securityHandler.setLoginService(loginService); 
securityHandler.setAuthenticator(formAuthenticator); 

// assign security to each webapp 
for (WebAppContext webapp : webapps) { 
    webapp.setSecurityHandler(securityHandler); 
    webapp.addServlet(loginServlet, "/login"); 
} 

:私がやりたいのは何

のようなものですあるWebアプリケーションから別のWebアプリケーションへのリンク、および再認証するたびにルート "/"のベースWebアプリケーションにリダイレクトされ、そのWebアプリケーションに対してのみ認証されます。

セッションを共有するために自分のコンテキストを取得したいと考えています。

this questionによれば、WebAppContextインスタンスごとに共通のSessionManagerを持つ必要がありますが、質問者は1つのWebAppContextインスタンスしか持っていません。同じWebManagerContextに同じSessionManagerインスタンスを割り当てると、NPEが取得されます。

また、各コンテキストのSessionCookieConfigのパスを共通のコンテキストパスに設定し、useApplicationのSessionManagerごとにuseRequestedIdをtrueに設定することを指摘しましたが、この解決策はorg.mortbay.jetty用であり、古くなっています。

複数のWebAppContextを持つ埋め込みJettyサーバのSSOを設定している経験がある場合や、1つの共通サーバで複数の異なるWebアプリケーションを提供するより良い方法が考えられる場合は、 。

1つのフォームを入力して、1つのサーバーで処理されるすべてのWebアプリケーションにユーザーが認証できるようにするにはどうすればよいですか。

私が明確ではないか、ご質問がある場合はお知らせください。

+0

Jettyサーバー内で実行されている複数のアプリケーションに対して、Jettyコンテナベースのセキュリティ(ポスト品種のJAAS)を拡張する方法を尋ねていますか? – Richard

+0

はい、特にシングルサインオンを使用しています。 –

+0

オクラホマ..私はそこに経験がありません。しかし、他のすべてが失敗した場合、あなたは「コンテナ」ではなく「アプリ」であなたのセキュリティを行うことができます。フィルターなどのようなものを使用する これを行う多くの利用可能なセキュリティフィルター、春のセキュリティなどがあります。 具体的には、コンテナがユーザーをフォームサーブレットに送信し、その後にユーザーが元の要求されたURLに転送されていないということですか? – Richard

答えて

0

私の解決策は、新しいセッションを作成する前にSessionIdManagerを照会するようにHashSessionManagerクラスを拡張することでした。その結果、同じSessionIdManagerの下にあるCrossContextSessionManagerインスタンスはすべて、セッションIDだけでなくセッション内容を共有します。したがって、1つのWebアプリケーションにサインインするということは、それらすべてにサインインすることを意味します。

import java.util.Collection; 

import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpSession; 

import org.eclipse.jetty.server.session.AbstractSession; 
import org.eclipse.jetty.server.session.HashSessionIdManager; 
import org.eclipse.jetty.server.session.HashSessionManager; 

/** 
* Allows the WebAppContext to check the server's SessionIdManager before creating a new session 
* so that WebAppContext can share session contents for each client rather than just session ids. 
*/ 
public class CrossContextSessionManager extends HashSessionManager { 

    // Number of seconds before the user is automatically logged out of an idle webapp session 
    private int defaultSessionTimeout = 1800; 

    /** 
    * Check for an existing session in the session id manager by the requested id. 
    * If no session has that id, create a new HttpSession for the request. 
    */ 
    @Override 
    public HttpSession newHttpSession(HttpServletRequest request) { 
    AbstractSession session = null; 

    String requestedId = request.getRequestedSessionId(); 
    if (requestedId != null) { 
     String clusterId = getSessionIdManager().getClusterId(requestedId); 
     Collection<HttpSession> sessions = ((HashSessionIdManager) getSessionIdManager()).getSession(clusterId); 
     for (HttpSession httpSession : sessions) { 
     session = (AbstractSession) httpSession; 
     break; 
     } 
    } 

    if (session == null) { 
     session = newSession(request); 
     session.setMaxInactiveInterval(defaultSessionTimeout); 
     addSession(session,true); 
    } 

    return session; 
    } 
} 

リクエストにすでにIDが設定されている場合、newSessionIdはそのIDをそのまま取り出します。それ以外の場合は、既存のすべてのIDからユニークな新しいIDを作成します。

+0

このCrossContextSessionManagerはどのように初期化されますか?組み込みのJettyスタートアップを実行するEquinox OSGIコンテナを使用しています。だから私は、このCrossContextSessionManagerを渡すために、スタートアッププロセスにどこに引っ掛けることができるのだろうかと思います。これを初期化する方法を示すコードスニペットをいくつか共有できますか? – Christoph

+0

for(WebAppContext webapp:webapps){ CrossContextSessionManager sessionManager = new CrossContextSessionManager(); SessionHandler sessionHandler =新しいSessionHandler(セッションマネージャ); webapp.setSessionHandler(sessionHandler); } –

関連する問題