Performing user authentication in Java EE / JSF using j_security_check

前端 未结 4 1394
北荒
北荒 2020-11-21 23:43

I\'m wondering what the current approach is regarding user authentication for a web application making use of JSF 2.0 (and if any components do exist) and Java EE 6 core mec

4条回答
  •  名媛妹妹
    2020-11-22 00:32

    I suppose you want form based authentication using deployment descriptors and j_security_check.

    You can also do this in JSF by just using the same predefinied field names j_username and j_password as demonstrated in the tutorial.

    E.g.



    You could do lazy loading in the User getter to check if the User is already logged in and if not, then check if the Principal is present in the request and if so, then get the User associated with j_username.

    package com.stackoverflow.q2206911;
    
    import java.io.IOException;
    import java.security.Principal;
    
    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.SessionScoped;
    import javax.faces.context.FacesContext;
    
    @ManagedBean
    @SessionScoped
    public class Auth {
    
        private User user; // The JPA entity.
    
        @EJB
        private UserService userService;
    
        public User getUser() {
            if (user == null) {
                Principal principal = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
                if (principal != null) {
                    user = userService.find(principal.getName()); // Find User by j_username.
                }
            }
            return user;
        }
    
    }
    

    The User is obviously accessible in JSF EL by #{auth.user}.

    To logout do a HttpServletRequest#logout() (and set User to null!). You can get a handle of the HttpServletRequest in JSF by ExternalContext#getRequest(). You can also just invalidate the session altogether.

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

    For the remnant (defining users, roles and constraints in deployment descriptor and realm), just follow the Java EE 6 tutorial and the servletcontainer documentation the usual way.


    Update: you can also use the new Servlet 3.0 HttpServletRequest#login() to do a programmatic login instead of using j_security_check which may not per-se be reachable by a dispatcher in some servletcontainers. In this case you can use a fullworthy JSF form and a bean with username and password properties and a login method which look like this:

    
        
        
        
        

    And this view scoped managed bean which also remembers the initially requested page:

    @ManagedBean
    @ViewScoped
    public class Auth {
    
        private String username;
        private String password;
        private String originalURL;
    
        @PostConstruct
        public void init() {
            ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
            originalURL = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI);
    
            if (originalURL == null) {
                originalURL = externalContext.getRequestContextPath() + "/home.xhtml";
            } else {
                String originalQuery = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_QUERY_STRING);
    
                if (originalQuery != null) {
                    originalURL += "?" + originalQuery;
                }
            }
        }
    
        @EJB
        private UserService userService;
    
        public void login() throws IOException {
            FacesContext context = FacesContext.getCurrentInstance();
            ExternalContext externalContext = context.getExternalContext();
            HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
    
            try {
                request.login(username, password);
                User user = userService.find(username, password);
                externalContext.getSessionMap().put("user", user);
                externalContext.redirect(originalURL);
            } catch (ServletException e) {
                // Handle unknown username/password in request.login().
                context.addMessage(null, new FacesMessage("Unknown login"));
            }
        }
    
        public void logout() throws IOException {
            ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
            externalContext.invalidateSession();
            externalContext.redirect(externalContext.getRequestContextPath() + "/login.xhtml");
        }
    
        // Getters/setters for username and password.
    }
    

    This way the User is accessible in JSF EL by #{user}.

提交回复
热议问题