0

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

这是 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 上找不到属性 'authenticated'”

  2. 如何从 xhtml 文件中将 Admin.authenticate 更新为 false (对不起,蹩脚的问题,我对 jsf 和 web 开发人员来说真的很陌生)

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

4

1 回答 1

1

根据我的说法,实现登录/注销的正确和更简洁的方法是创建一个过滤器并将其应用于应该保护的 url(例如 /admin/*)。

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

对于注销,您只需在会话上调用invalidate,所有会话范围的属性都将被销毁。

一个工作示例如下所示:

将保存登录信息的 SessionScoped bean:

用户Bean.java

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

  }

登录Bean.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(){}
}

登录.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标签来判断使用是否登录了。

希望这可以帮助。

于 2012-08-28T16:28:15.780 回答