JSF中的基本安全

我希望看到一个简单的login应用程序,但不是这样简单。

我想实现的是对JSF如何工作的理解,我已经开发了大量的ASP.NET代码,你可以在这里检查是否在login时创build了一个会话。

JSF中的类似解决scheme将会很好。

这基本上是我想要实现的:

  • login页面
  • 如果确定
    • 创build会话并返回“成功”
  • 如果失败
    • 返回“失败”

(“成功”和失败映射到faces-config.xml)

在成功页面上,我想确保用户已经login,所以如果您没有正确的会话,就不能导航到“success.jspx”。

除了能够使用像基于angular色的安全性的组件rendered属性之类的东西,核心JSF中没有内在的身份validationfunction。

默认情况下,JSF应用程序依赖于容器pipe理的安全机制和包含它的Web组件( JEE5教程 )。 像Seam这样的第三方框架可以提供替代scheme。

如果你想添加自己的应用程序安全性, servletfilter是更简单的机制之一。

该filter保护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> 

filter类的实现:

 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定义的loginbean:

 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; } } 

JSFlogin表单在restricted_login.jsp页面中:

  <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> 

(redirectURL /机制的select是为了简洁,而不是任何最佳实践;请参阅Servlet API以获取更多选项。)

如果你愿意尝试更高级的方法,那么我build议你考虑一下spring-security + JSF。 它像一个魅力。

你可以编写你的应用程序,就好像它不在安全之下,然后configuration哪些区域应该使用方面来保护。

Spring安全性: http : //static.springsource.org/spring-security/site/

教程: http : //ocpsoft.com/java/acegi-spring-security-jsf-login-page/

最好的办法是使用容器pipe理的安全性。

这里是一个关于如何用glassfishjsf实现的教程 。

如果你使用模板,我发现你并不需要filter。

的index.jsp

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

startup.xhtml(.faces),实际上并不尝试显示一个屏幕,它调用加载的JavaScript的startupSubmit(),并点击button。 这将直接发送到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的variables设置为true(默认为false),然后跳转到first.xhtml。 您可以使用您想要的任何标准来确定授权是否被设置为true(例如login标准)。

 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中,只需在窗体内部放置ah:或者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> 

所以,这是我的解决scheme。 我已经testing它非常彻底,它似乎工作正常。