使用静态变量保存登录状态 - JSF2

时间:2012-08-28 15:57:10

标签: jsf-2

我想知道在jsf2环境中创建登录/注销机制的正确方法。 我创建了一个登录xhtml表单和一个存储静态布尔值(is_authenticated)的Admin bean。我想在每个xhtml页面检查该变量,如果是真的?继续,否则重定向到登录页面。

这是Admin.java bean:

@ManagedBean
@SessionScoped
public class Admin implements Serializable {
/**
 * 
 */
private static final long serialVersionUID = 1L;
static Boolean authenticated;
String username;
String password;

@PostConstruct
public void initialisation() {      // init bean on new instance
    Admin.authenticated = false;
}

public Boolean getAuthenticated(){
    return Admin.authenticated;
}

public String getUsername() {
    return username;
}
public void setUsername(String username) {
    this.username = username;
}
public String getPassword() {
    return password;
}
public void setPassword(String password) {
    this.password = password;
}

public String doLogout() {
    Admin.authenticated=false;  

    return "login?faces-redirect=true";
}

public String validity() {


    if(username.equals("admin") && password.equals("admin")) {
        Admin.authenticated=true;
        return "success";
    }   else   {
        Admin.authenticated=false;
        return "failure";
    }
}

}

这是main.xhtml:

<?xml version="1.0" encoding="UTF-8" ?>
<ui:composition template="template.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"      
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:define name="content">

<c:if test="#{admin.authenticated == false}">
// update Admin.authenticate to false
<meta http-equiv="refresh" content="0;URL=login.xhtml" />
</c:if>


<h1>Statistics</h1>
<div style="margin:10px">
<h:panelGrid columns="3">
Advertisers:
<h:outputText value="#{stats.advertisers}"/> 
<h:outputText value=""/>
Publishers:
<h:outputText value="#{stats.publishers}"/> 
<h:outputText value=""/>
Campaigns:
<h:outputText value="#{stats.campaigns}"/>
<h:outputText value="(#{stats.activeCampaigns} active)"/>
Banners:
<h:outputText value="#{stats.banners}"/>
<h:outputText value="(#{stats.activeBanners} active)"/>
Games:
<h:outputText value="#{stats.games}"/>
<h:outputText value="(#{stats.activeGames} active)"/>
</h:panelGrid>
</div>
</ui:define>
</ui:composition>

两个问题:

  1. 在jstl'if'中,我得到:“找不到属性'已验证' 输入com.pkg.name.Admin“

  2. 如何从xhtml文件中将Admin.authenticate更新为false(对于蹩脚的问题感到抱歉,我对jsf和web dev一般都是新手)

  3. 使用此静态变量是一种好习惯吗? (就像会话变量的一个实例)

1 个答案:

答案 0 :(得分:1)

据我所知,实现登录/注销的正确和清晰的方法是创建一个过滤器并将其应用于应受保护的URL(例如/ admin / *)。

如果用户成功登录会话bean中加载他的详细信息。当用户请求受保护的页面时,过滤器首先运行。在过滤器中从请求获取会话并调用其getAttribute方法来获取会话bean(jsf将会话范围的bean存储为会话属性)。如果你得到了bean对象,那么他就会登录,如果你得到null,他就没有被授权,你可以将他重定向到登录页面。

对于注销,您只需在会话中调用 invalidate ,即可销毁所有会话范围属性。

一个工作示例如下:

SessionScoped bean将保存登录信息:

UserBean.java

    @ManagedBean
    @SessionScoped
    class UserBean implements Serializable{
    private User user;
    //getter/setter for user

  }

LoginBean.java

    @ManagedBean
    class LoginBean
    {
    @ManagedProperty(value="#{userBean}")
    private UserBean userBean;
    public UserBean getUserBean(){
    return userBean;
    }
    public void setUserBean(UserBean userBean){
    this.userBean=userBean;
    }
    private String username,password;
    //getter and setter for username,password
    public String checkLogin(){
   //check database for user
   if(user!=null){
   userBean.setUser(user);
   }
   //...
   }
   }

LoginFilter.java-我们将此过滤器应用于url模式:/ admin / *

@WebFilter("/admin/*")
    class LoginFilter implements Filter{
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {    
       HttpSession session=((HttpServletRequest)request).getSession();
       userBean userBean=(userBean)session.getAttribute("userBean");
       if(userBean!=null){
       User user=userBean.getUser();
       if(user==null){
          ((HttpServletResponse)response).sendRedirect("login.jsf");
       }
       else
        chain.doFilter(request, response);
       }
       else
         ((HttpServletResponse)response).sendRedirect("login.jsf");
    }

    public void init(FilterConfig fc){}
    public void destroy(){}
}

login.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:f="http://java.sun.com/jsf/core">
    <h:head><title>Login To Admin Panel</title>
    </h:head>
    <h:body>
    <h:form>
    Username : <h:inputText value="#{loginBean.username}"/>
    Password : <h:inputSecret value="#{loginBean.password}"/>
    <h:commandButton value="Login" action="#{loginBean.checkLogin}" />
    </h:form>

    </h:body>
    </html>

对于注销,您只需调用session.invalidate(),它将破坏会话以及任何会话范围属性。

这样您就不必编写条件jstl标记来确定是否登录使用。

希望这有帮助。