web-dev-qa-db-ja.com

JSFの基本的なセキュリティ

this ほど単純ではないが、単純なログインアプリケーションを見たいのですが。

私が達成したいのは、JSFの仕組みを理解することです。コードビハインドがあり、ログイン時にセッションが作成されたかどうかを確認できる多くのASP.NETを開発しました。

JSFでの同様のソリューションは素晴らしいでしょう。

これは基本的に私が達成したいことです:

  • ログインページ
  • よろしければ
    • セッションを作成して「成功」を返す
  • 失敗した場合
    • 「失敗」を返す

(「成功」と失敗はfaces-config.xmlにマッピングされます)

成功ページで、ユーザーがログインしていることをCertainにしたいので、「success.jspx」にナビゲートできない場合正しいセッションがありません。

36
Filip Ekberg

コアJSFには、ロールベースのセキュリティを対象としたコンポーネントrendered属性などを使用できること以外に、固有の認証機能はありません。

デフォルトでは、JSFアプリケーションは、それを含むWebコンポーネントと同じコンテナ管理のセキュリティメカニズムに依存しています( JEE5チュートリアル )。 Seam のようなサードパーティのフレームワークは代替を提供できます。

独自のアプリケーションセキュリティを追加する場合、 servlet filter はより単純なメカニズムの1つです。

このフィルターは、web.xmlで定義されているrestrictedディレクトリーの下のリソースを保護します。

  <filter>
    <filter-name>AuthenticationFilter</filter-name>
    <filter-class>restricted.AuthenticationFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>AuthenticationFilter</filter-name>
    <url-pattern>/restricted/*</url-pattern>
  </filter-mapping>

フィルタークラスの実装:

public class AuthenticationFilter implements Filter {
  private FilterConfig config;

  public void doFilter(ServletRequest req, ServletResponse resp,
      FilterChain chain) throws IOException, ServletException {
    if (((HttpServletRequest) req).getSession().getAttribute(
        AuthenticationBean.AUTH_KEY) == null) {
      ((HttpServletResponse) resp).sendRedirect("../restricted_login.faces");
    } else {
      chain.doFilter(req, resp);
    }
  }

  public void init(FilterConfig config) throws ServletException {
    this.config = config;
  }

  public void destroy() {
    config = null;
  }
}

faces-config.xmlで定義されたログインBean:

public class AuthenticationBean {
  public static final String AUTH_KEY = "app.user.name";

  private String name;
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }

  public boolean isLoggedIn() {
    return FacesContext.getCurrentInstance().getExternalContext()
        .getSessionMap().get(AUTH_KEY) != null;
  }

  public String login() {
    FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(
        AUTH_KEY, name);
    return "secret";
  }

  public String logout() {
    FacesContext.getCurrentInstance().getExternalContext().getSessionMap()
        .remove(AUTH_KEY);
    return null;
  }
}

restricted_login.jspページのJSFログインフォーム:

  <f:view>
    <p><a href="restricted/secret.faces">try to go to secret
    page</a></p>
    <h:form>
    Username:
    <h:panelGroup rendered="#{not authenticationBean.loggedIn}">
        <h:inputText value="#{authenticationBean.name}" />
        <h:commandButton value="login"
          action="#{authenticationBean.login}" />
      </h:panelGroup>
      <h:commandButton value="logout"
        action="#{authenticationBean.logout}"
        rendered="#{authenticationBean.loggedIn}" />
    </h:form>
  </f:view>

(リダイレクトURL /メカニズムは、ベストプラクティスではなく簡潔さのために選択されました。その他のオプションについては Servlet API を参照してください。)

46
McDowell

もう少し高度なアプローチを試してみたい場合は、spring-security + JSFを検討することをお勧めします。それは魅力のように機能します。

セキュリティがかかっていないかのようにアプリケーションを作成し、アスペクトを使用して保護する必要がある領域を設定するだけです。

Springセキュリティ: http://static.springsource.org/spring-security/site/

チュートリアル: http://ocpsoft.com/Java/acegi-spring-security-jsf-login-page/

4
Tomas F

それを行う最良の方法は、コンテナ管理のセキュリティを使用することです。

チュートリアルはこちらglassfishjsfを使用してそれを達成する方法について。

3
gordan

テンプレートを使用する場合、フィルターは実際には必要ないことがわかりました。

index.jsp

<jsp:forward page="startup.faces"></jsp:forward>

startup.xhtml(.faces)は、実際には画面を表示しようとせず、ロード時にjavascript startupSubmit()を呼び出し、ボタンをクリックします。これにより、フローがStartupBean.Javaのメソッドstart()に直接送信されます。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0     Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
.
.
 <script type="text/javascript">
 function startupSubmit() {
  **document.getElementById('startupForm:startupBtn').click();**
 }
 </script>
 <h:body onload="startupSubmit()">
 <h:form id="startupForm">
 <p:commandButton id="startupBtn" value="" action="#{startupBean.start}" ajax="false" />  
 </h:form>
 </h:body>
</html>

StartupBean.Java(以下のtemplate.xhtmlの一部ではありません)。 StartupBeanのstart()メソッドは、authorizedという変数をtrue(デフォルトはfalse)に設定し、first.xhtmlにジャンプします。ログイン基準など、許可がtrueに設定されているかどうかを判断するための任意の基準を使用できます。

package gov.irs.eservices.managementBeans;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean(name="startupBean")
@SessionScoped
public class StartupBean {

private boolean authorized;

public StartupBean() {
}

public String start() {
    **setAuthorized(true);**
    return "first";
}

public boolean isAuthorized() {
    return authorized;
}

public void setAuthorized(boolean authorized) {
    this.authorized = authorized;
}
}

template.xhtml。 template.xhtmlでは、フォーム内にh:またはp:panelGridを配置し、startupBean.authorizedがtrueの場合にのみレンダリングします。ユーザーがテンプレートに含まれるページにアクセスできる唯一の方法は、最初にStartupBean.Javaを使用する場合です。

<f:view>
<div id="container">
<h:form id="templateForm">
**<p:panelGrid rendered="#{startupBean.authorized}">**
    <div id="header">
        <ui:include src="header.xhtml" />
    </div>

    <div id="wrapper">
        <div id="firstId">
            <ui:insert name="first"></ui:insert>
        </div>
.
.  <!-- MORE PAGES -->
.
.
    </div>

    <div id="footer">
        <ui:include src="footer.xhtml" />
    </div>
</p:panelGrid>
</h:form>
</div>      
</f:view>

だから、それが私の解決策です。私はそれをかなり徹底的にテストしましたが、うまくいくようです。

2
DougMH