JSF HTTP会话登录

时间:2010-10-01 16:56:35

标签: jsf

我尝试在Web应用程序中创建登录表单。 在JSP页面我可以使用

<%
   String name = request.getParameter( "username" );
   session.setAttribute( "theName", name );
%>

但现在我正在使用JSF / Facelets进行Web应用程序 我不知道如何在客户端的JSF Backing bean中创建会话,并检查用户是否登录,因此它将重定向到登录页面。 谁能帮我提一下这些问题的链接教程? 谢谢你

现在我在映射到web.xml时几乎没有问题 代码剪辑了类Filter

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

@Override
public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;
    LoginController controller = (LoginController) req.getSession()
            .getAttribute("loginController");
    if (controller == null || !controller.isLoggedIn()) {
        res.sendRedirect("../admin/login.xhtml");
    } else {
        chain.doFilter(request, response);
    }
}

并在web.xml我使用<fitler>代码

进行映射
<filter>
    <filter-name>userLoginFilter</filter-name>
    <filter-class>com.mcgraw.controller.UserLoginFilter</filter-class>
    <init-param>
        <param-name>loginPage</param-name>
        <param-value>/login.xhtml</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>userLoginFilter</filter-name>
    <url-pattern>/admin/*</url-pattern>
</filter-mapping>

我在web项目中有一个文件夹管理员,我检查用户是否没有使用管理员权限登录不访问页面(我可以进行权限检查)但是当我使用过滤器时浏览器不理解URL? ? 浏览器不理解URL时没有显示StackTrace

Firefox上显示错误

The page isn't redirecting properly

在IE上加载...加载。 ..不停的

现在我改变条件,检查是否req.getPathInfo.startsWith(“/ login.xhtml”)它会做链

我有2个想法,但它响应500 HTTP STATUS

 if (controller == null || !controller.isLoggedIn()) {
     res.sendRedirect("../admin/login.xhtml");
     if(req.getPathInfo().startsWith("/login.xhtml")){
     chain.doFilter(request, response);
}

} else {
     chain.doFilter(request, response);
}

===============

if (controller == null || !controller.isLoggedIn()) {
    if (!req.getPathInfo().startsWith("/login.xhtml")) {
        res.sendRedirect("../admin/login.xhtml");
    } else {
        chain.doFilter(request, response);
    }
} else {
    chain.doFilter(request, response);
}

====================== update class loginController

package com.mcgraw.controller;

import com.DAO.UserBean;
import com.entity.IUser;
import java.io.Serializable;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

/**
 * @author Kency
 */
@ManagedBean
@SessionScoped
public class LoginController implements Serializable {

    @EJB
    private UserBean userBean;
    private IUser user;
    private boolean admin;
    private boolean mod;
    private PasswordService md5;

    /** Creates a new instance of LoginController */
    public LoginController() {
        user = new IUser();
        md5 = new PasswordService();
    }

    // getter / setter
    public boolean isMod() {
        return mod;
    }

    public void setMod(boolean mod) {
        this.mod = mod;
    }

    public IUser getUser() {
        return user;
    }

    public void setUser(IUser user) {
        this.user = user;
    }

    public boolean isAdmin() {
        return admin;
    }

    public void setAdmin(boolean admin) {
        this.admin = admin;
    }

    public String cplogin() {
        String md5Password = md5.md5Password(user.getPassword());
        if (userBean.userLogin(user.getUsername(), md5Password) != null) {
            if (user.getUsername() != null || md5Password != null) {
                user = userBean.userLogin(user.getUsername(), md5Password);
                if (user.getGroups().getAdmin() != null) {
                    setAdmin(user.getGroups().getAdmin());
                }
                if (user.getGroups().getMods() != null) {
                    setMod(user.getGroups().getMods());
                }
                if (isAdmin() == true || isMod() == true) {
                    return "home";
                } else {
                    return "login";
                }
            } else {
                return "login";
            }
        } else {
            return "login";
        }
    }

    public String logout() {
        user = null;
        return "login";
    }

    public boolean isLoggedIn() {
        return user != null;
    }
}

我有新问题如果使用方法loggedIn渲染JSF taglib,在索引页面(不在admin文件夹中)用户不登录可以看到我渲染的例子,&lt; ==这就好像如果用户没有登录用户可以不知道为什么他能看到它?

2 个答案:

答案 0 :(得分:47)

您可以在JSF中通过ExternalContext#getSessionMap()获取/设置HTTP会话属性,这基本上是HttpSession#get/setAttribute()的包装器。

@Named
@RequestScoped
public class LoginController {

    private String username;
    private String password;

    @EJB
    private UserService userService;

    public String login() {
        User user = userService.find(username, password);
        FacesContext context = FacesContext.getCurrentInstance();

        if (user == null) {
            context.addMessage(null, new FacesMessage("Unknown login, try again"));
            username = null;
            password = null;
            return null;
        } else {
            context.getExternalContext().getSessionMap().put("user", user);
            return "userhome?faces-redirect=true";
        }
    }

    public String logout() {
        FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
        return "index?faces-redirect=true";
    }

    // ...
}

在Facelets页面中,只需将usernamepassword输入字段绑定到此bean并相应地调用login()操作。

<h:form>
    <h:inputText value="#{loginController.username}" />
    <h:inputSecret value="#{loginController.password}" />
    <h:commandButton value="login" action="#{loginController.login}" />
</h:form>

会话属性可在EL中直接访问。名为user的会话属性在EL中可用#{user}。在测试用户是否登录了某个rendered属性时,只需检查它是否为empty

<h:panelGroup rendered="#{not empty user}">
    <p>Welcome, #{user.fullName}</p>
    <h:form>
        <h:commandButton value="logout" action="#{loginController.logout}" />
    </h:form>
</h:panelGroup>

注销操作基本上只会破坏会话。


如果用户是否登录时检查传入的请求,只需创建一个Filter,其doFilter()方法大致执行以下操作:

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {    
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;
    HttpSession session = request.getSession(false);
    String loginURI = request.getContextPath() + "/login.xhtml";

    boolean loggedIn = session != null && session.getAttribute("user") != null;
    boolean loginRequest = request.getRequestURI().equals(loginURI);
    boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER);

    if (loggedIn || loginRequest || resourceRequest) {
        chain.doFilter(request, response);
    } else {
        response.sendRedirect(loginURI);
    }
}

将其映射到涵盖受限页面的url-pattern,例如/secured/*/app/*

另见:

答案 1 :(得分:1)

在收到请求时(例如在操作方法中)在您的支持bean中尝试此操作:

HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
HttpSession session = request.getSession();

然后,您可以使用请求和会话对象,就像您以前使用JSP,设置属性等一样。

您可能还想查看我的related question about checking the client session in a servlet Filter。你可以写一个类似的过滤器来检查他们的HttpSession中的用户登录,然后根据需要进行重定向(或像我最终做的那样RequestDispatch)到你的登录页面。