Jsf 使用Servlet 3.0以编程方式控制登录

Jsf 使用Servlet 3.0以编程方式控制登录,jsf,servlets,servlet-filters,Jsf,Servlets,Servlet Filters,我已经在Glassfish 3.0.1中测试了默认的安全容器,并得出结论,我不会在这方面花费更多的时间。相反,我想自己控制验证。但我需要一些指导让我走上正轨 目前,我有一个UserBean,它具有登录/注销功能(见下文)。我不想使用内置的*j_security_check*容器,而是使用核心JSF2.0 我的问题是, 如果用户未登录(如果访问某些文件夹),是否需要ServletFilter重定向流量 用户成功登录后,如何存储用户原则 感谢任何帮助或链接到示例,克里斯 请原谅我把两个问题集中在一起

我已经在Glassfish 3.0.1中测试了默认的安全容器,并得出结论,我不会在这方面花费更多的时间。相反,我想自己控制验证。但我需要一些指导让我走上正轨

目前,我有一个UserBean,它具有登录/注销功能(见下文)。我不想使用内置的*j_security_check*容器,而是使用核心JSF2.0

我的问题是,

  • 如果用户未登录(如果访问某些文件夹),是否需要ServletFilter重定向流量
  • 用户成功登录后,如何存储用户原则
  • 感谢任何帮助或链接到示例,克里斯

    请原谅我把两个问题集中在一起

    @ManagedBean
    @SessionScoped
    public class UserBean {
    
    private AuthenticateUser authenticateUser;
    ...
    
    public String login() {
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
    
        JsfUtil.log("Username : " +authenticateUser.getUserName());
        JsfUtil.log("Password : " +authenticateUser.getPassword());
        AuthenticateUser authRequest = authenticationFacade.find(authenticateUser);
        try {
            if(!authRequest.equals(authenticateUser))
                return "/loginError";
    
            request.login(authenticateUser.getUserName(), authenticateUser.getPassword());
            return "";
        } catch(ServletException e){
           JsfUtil.addErrorMessage(e, "Incorrect username or password, please try again.");
           return "/loginError";
        }
    
    ...
    public String logOut() {
        String result = "/index?faces-redirect=true";
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
    
        try {
            request.logout();
        } catch (ServletException e) {
            JsfUtil.log("Failed to logout user!" +e.getRootCause().toString());
            result = "/loginError?faces-redirect=true";
        }
        return result;
        }
    

    当您想利用
    request.login()
    时,您真的应该在容器中配置一个表示用户数据库的域。但是您似乎已经用一些
    AuthenticationFacade
    取代了这个领域。在这种情况下,
    request.login()
    对您没有用处

    您只需将用户放在会话范围内,并在该范围内进行拦截。以下是一个启动示例:

    @ManagedBean
    @SessionScoped
    public class UserManager {
    
        @EJB
        private UserService userService;
        private String username;
        private String password;
        private User current;
    
        public String login() {
            current = userService.find(username, password);
    
            if (current == null) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Unknown login, try again"));
                return null;
            } else {
                return "userhome?faces-redirect=true";
            }
        }
    
        public String logout() {
            FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
            return "index?faces-redirect=true";
        }
    
        public boolean isLoggedIn() {
            return current != null;
        }
    
        // Getters/setters (but do NOT provide a setter for current!)
    }
    
    当像这样进行身份验证时,您肯定需要一个限制访问的方法。使用容器管理的安全性时,您通常会为此将其指定为
    。但是如果没有它,你就必须把它掌握在手中。很高兴知道JSF托管bean在任何范围内都是由其托管bean名称设置密钥的

    UserManager userManager = ((HttpServletRequest) request).getSession().getAttribute("userManager");
    
    if (userManager == null || !userManager.isLoggedIn()) {
        ((HttpServletResponse) response).sendRedirect("login.xhtml");
    } else {
        chain.doFilter(request, response);
    }
    
    将上述过滤器映射到所需的URL模式


    当您仍要重新考虑使用容器管理的身份验证时,以下相关答案可能会很有用:

    • (及)

    如果您使用的是JDBC领域安全性,请注意。在Glassfish管理控制台中配置领域的字段中有一些固定/预期的单词

    JAAS上下文:字段中,必须键入:jdbcream。该关键字使安全容器使用预期的JDBC领域。如果您键入其他内容,它将不起作用


    这是一个很好的例子,由Gordan Jugo完成

    谢谢你的快速回答。也许不使用应用程序容器中的域是不明智的。但当我试图使用我的桌子结构/设计时,我在巡逻中遇到了麻烦。它在很大程度上是一个容器领域的黑盒子。但是使用ServletFilter,我仍然可以限制对根目录和其他文件夹的所有访问。所以我明天就试试看。再次感谢。