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理的安全性。
这里是一个关于如何用glassfish
和jsf
实现的教程 。
如果你使用模板,我发现你并不需要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它非常彻底,它似乎工作正常。