Domanda

Mi chiedo che cosa l'attuale approccio è per quanto riguarda l'autenticazione utente per un'applicazione web facendo uso di JSF 2.0 (e se esistono eventuali componenti) e Java EE 6 meccanismi di base (i permessi di accesso / controllo / logout) con le informazioni dell'utente tengono in un'entità JPA. Il tutorial Oracle Java EE è un po 'scarne su questo (gestisce solo servlet).

Questa è senza facendo uso di tutto un altro quadro, come Primavera-Security (Acegi), o Seam, ma cercando di attaccare si spera con il nuovo Java EE 6 piattaforma (profilo web) se possibile .

È stato utile?

Soluzione

Dopo la ricerca sul Web e provare molti modi diversi, ecco cosa io suggerirei per Java EE 6 di autenticazione:

Impostare il regno di sicurezza:

Nel mio caso, ho avuto gli utenti nel database. Così ho seguito questo post del blog per creare un Reame JDBC che potrebbe autenticare gli utenti in base alla username e le password MD5 hash nella mia tabella di database:

http: //blog.gamatam. com / 2009/11 / JDBC-regno-setup-con-GlassFish-v3.html

Nota: il post parla di un utente e un tavolo di gruppo nel database. Ho avuto una classe User con un attributo UserType enum mappato tramite annotazioni javax.persistence al database. Ho configurato il regno con la stessa tabella per utenti e gruppi, utilizzando la colonna UserType come colonna gruppo e ha funzionato bene.

autenticazione Utilizza il modulo:

Sempre seguendo il post sul blog di cui sopra, configurare il web.xml e del sole-web.xml, ma invece di utilizzare l'autenticazione di base, utilizzare il modulo (in realtà, non importa quale si utilizza, ma ho finito per usare FORM ). Utilizzare il codice HTML standard, non il JSF.

Quindi utilizzare punta di BalusC sopra sul pigro l'inizializzazione delle informazioni utente dal database. Ha suggerito di farlo in un bean gestito ricevendo il preside dal contesto volti. Ho usato, invece, un bean di sessione stateful per memorizzare le informazioni di sessione per ciascun utente, così ho iniettato il contesto di sessione:

 @Resource
 private SessionContext sessionContext;

Con il preside, posso controllare il nome utente e, utilizzando la Gestione EJB Entity, ottenere le informazioni utente dal database e conservare nel mio SessionInformation EJB.

Esci:

ho anche guardato intorno per il modo migliore per il logout. Il migliore che ho trovato è usare una servlet:

 @WebServlet(name = "LogoutServlet", urlPatterns = {"/logout"})
 public class LogoutServlet extends HttpServlet {
  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   HttpSession session = request.getSession(false);

   // Destroys the session for this user.
   if (session != null)
        session.invalidate();

   // Redirects back to the initial page.
   response.sendRedirect(request.getContextPath());
  }
 }

Anche se la mia risposta è davvero tardi considerando la data della domanda, spero che questo aiuta altre persone che finiscono qui da Google, proprio come ho fatto io.

Ciao,

Vítor Souza

Altri suggerimenti

Credo che si desidera l'autenticazione basata utilizzando descrittori di deployment e j_security_check.

È anche possibile fare questo in JSF da solo utilizzando gli stessi nomi dei campi predefinied j_username e j_password come dimostrato nel tutorial.

per es.

<form action="j_security_check" method="post">
    <h:outputLabel for="j_username" value="Username" />
    <h:inputText id="j_username" />
    <br />
    <h:outputLabel for="j_password" value="Password" />
    <h:inputSecret id="j_password" />
    <br />
    <h:commandButton value="Login" />
</form>

Si potrebbe fare lazy loading in getter User per verificare se la User è già connesso e se non, quindi verificare se il Principal è presente nella richiesta e, in caso affermativo, quindi ottenere il User associato con 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;
    }

}

Il User è ovviamente accessibile in JSF EL da #{auth.user}.

Per disconnettersi fare una HttpServletRequest#logout() (e impostare User a null!). È possibile ottenere una maniglia della HttpServletRequest in JSF da ExternalContext#getRequest() . È anche possibile invalidare la sessione del tutto.

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

Per il resto (la definizione degli utenti, ruoli e vincoli nel descrittore di deployment e regno), basta seguire il Java EE 6 tutorial e la documentazione servletcontainer solito modo.


Aggiorna : è possibile anche utilizzare il nuovo Servlet 3.0 HttpServletRequest#login() per fare un account di accesso programmatico invece di usare j_security_check che non può per-sé essere raggiungibile da un dispatcher in alcuni servletcontainers. In questo caso è possibile utilizzare un modulo fullworthy JSF e un fagiolo con username e password proprietà e un metodo login che simile a questa:

<h:form>
    <h:outputLabel for="username" value="Username" />
    <h:inputText id="username" value="#{auth.username}" required="true" />
    <h:message for="username" />
    <br />
    <h:outputLabel for="password" value="Password" />
    <h:inputSecret id="password" value="#{auth.password}" required="true" />
    <h:message for="password" />
    <br />
    <h:commandButton value="Login" action="#{auth.login}" />
    <h:messages globalOnly="true" />
</h:form>

E questo punto di vista con scope bean gestito, che ricorda anche la pagina inizialmente richiesta:

@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.
}

In questo modo il User è accessibile in JSF EL da #{user}.

Va ricordato che si tratta di un'opzione di lasciare completamente problemi di autenticazione per il front controller, ad esempio, un Apache Webserver e valutare l'HttpServletRequest.getRemoteUser () invece, che è la rappresentazione JAVA per la variabile di ambiente REMOTE_USER. Ciò consente anche sofisticato registro nei disegni come l'autenticazione Shibboleth. Filtraggio richieste a un servlet container attraverso un server web è un buon design per ambienti di produzione, spesso mod_jk viene utilizzato per farlo.

Il problema HttpServletRequest.login non imposta lo stato di autenticazione in sessione è stato risolto a 3.0.1. Aggiorna GlassFish alla versione più recente e il gioco è fatto.

L'aggiornamento è molto semplice:

glassfishv3/bin/pkg set-authority -P dev.glassfish.org
glassfishv3/bin/pkg image-update
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top