Frage

Ich frage mich, was das derzeitige Konzept der Benutzerauthentifizierung für eine Web-Anwendung ist in Bezug auf die Verwendung von JSF 2.0 zu machen (und wenn alle Komponenten existieren) und Java EE 6-Kern-Mechanismen (Login / Check-Berechtigungen / Abmeldungen) mit Benutzerinformationen halten in einer JPA-Entität. Die Oracle Java EE Tutorial ist ein wenig spärlich auf diese (nur Griffe Servlets).

Dies ist ohne Verwendung von einem ganz anderen Rahmen zu machen, wie Spring-Security (Acegi) oder Naht, aber hoffentlich mit dem neuen Java EE 6-Plattform (Web-Profil) zu halten versuchen, wenn möglich, .

War es hilfreich?

Lösung

Nachdem die Suche im Internet und viele verschiedene Arten versucht, hier ist was ich für Java EE 6-Authentifizierung würde vorschlagen:

, um den Sicherheitsbereich ein:

In meinem Fall hatte ich die Benutzer in der Datenbank. Also folgte ich diesen Blog-Post einen JDBC-Realm zu erstellen, die Benutzer basierend auf Benutzernamen und MD5-Hash-Passwörter in der Datenbank-Tabelle authentifizieren können:

http: //blog.gamatam. com / 2009/11 / jdbc-Reich-setup-mit-Glassfish-v3.html

Hinweis: Die Post spricht von einem Benutzer und eine Gruppe Tabelle in der Datenbank. Ich hatte eine User-Klasse mit einem Usertype Enum-Attribute über javax.persistence Anmerkungen zu der Datenbank abgebildet. Ich baut den Bereich mit der gleichen Tabelle für Benutzer und Gruppen, die usertype Spalte als Gruppen Spalt und es hat gut funktioniert.

Mit Form-Authentifizierung:

folgenden noch die oben Blog-Post, konfigurieren Sie Ihre web.xml und sun-web.xml, sondern BASIC-Authentifizierung zu verwenden, Verwendung FORM (eigentlich ist es egal, welche Sie verwenden, aber ich landete Formular ). Verwenden Sie den Standard-HTML, nicht die JSF.

Verwenden Sie dann BalusC Tipp oben auf faul, um die Benutzerinformationen aus der Datenbank zu initialisieren. Er schlug vor, es in einer verwalteten Bean macht die Haupt vom Gesicht Kontext zu bekommen. Ich habe stattdessen einen Stateful-Session-Bean für jede Benutzersitzung um Informationen zu speichern, so dass ich injizierte, um den Sitzungskontext:

 @Resource
 private SessionContext sessionContext;

Mit dem Prinzip kann ich die Benutzername überprüfen und den EJB-Entity-Manager erhalten Sie die Benutzerinformationen aus der Datenbank und Speicher in meinem SessionInformation EJB.

Abmelden:

Ich sah mich um auch für den besten Weg, um die Abmeldung. Die beste, die ich gefunden habe, ist mit einem 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());
  }
 }

Obwohl meine Antwort sehr spät ist das Datum der Frage unter Berücksichtigung, ich hoffe, dass diese andere Menschen hilft, die hier von Google am Ende, genau wie ich.

Ciao,

Vítor Souza

Andere Tipps

Ich nehme an, Sie formularbasierte Authentifizierung wollen mit Deployment-Deskriptoren und j_security_check.

Sie können dies auch durch nur in JSF tun die gleichen predefinied Feldnamen j_username und j_password wie im Tutorial demonstriert.

z.

<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>

Sie könnten verzögertes Laden in dem User Getter tun, um zu überprüfen, ob die User bereits angemeldet sind und wenn nicht, dann überprüfen, ob die Principal in der Anforderung vorhanden sind, und wenn ja, dann die User mit j_username zugeordnet bekommen.

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;
    }

}

Die User ist offensichtlich zugänglich in JSF EL von #{auth.user}.

Um sich abzumelden tun ein HttpServletRequest#logout() (und setzen User auf null!). Sie können einen Griff des HttpServletRequest in JSF bekommen von ExternalContext#getRequest() . Sie können auch ungültig machen nur die Sitzung zusammen.

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

Für den Rest (Definition von Benutzern, Rollen und Einschränkungen in Deployment Descriptor und Reich), folgen Sie einfach der Java EE 6-Tutorial und die servletcontainer Dokumentation des üblicher Weg.


Aktualisieren : Sie können auch die neue Servlet 3.0 verwenden HttpServletRequest#login() eine programmatische Anmeldung zu tun, anstatt j_security_check zu verwenden, die per se nicht durch eine erreichbar sein Dispatcher in einigen servletcontainers. In diesem Fall können Sie eine fullworthy JSF Form und eine Bohne mit username und password Eigenschaften und eine login Methode verwenden, die wie folgt aussehen:

<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>

Und diese Ansicht scoped Bean verwaltet, die auch die ursprünglich angeforderte Seite erinnert sich:

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

Auf diese Weise der User ist zugänglich in JSF EL von #{user}.

Es soll erwähnt werden, dass es eine Möglichkeit ist, vollständig Authentifizierungsprobleme an der Front Controller zu lassen, zum Beispiel ein Apache Webserver und bewertet den HttpServletRequest.getRemoteUser () statt, die die JAVA-Darstellung für die REMOTE_USER Umgebungsvariable ist. Dies ermöglicht auch anspruchsvolle log in Designs wie Shibboleth-Authentifizierung. Filteranforderungen an einen Servlet-Container über einen Web-Server ist ein gutes Design für Produktionsumgebungen häufig mod_jk verwendet wird, dies zu tun.

Das Thema HttpServletRequest.login nicht gesetzt Authentifizierungsstatus in der Sitzung wurde behoben in 3.0.1. Aktualisieren Sie Glassfish auf die neueste Version und du bist fertig.

Die Aktualisierung ist ganz einfach:

glassfishv3/bin/pkg set-authority -P dev.glassfish.org
glassfishv3/bin/pkg image-update
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top