Sécurité Java EE-Non redirigé vers la page initiale après la connexion


Je viens de commencer à apprendre Java EE. Mon objectif est de mettre en place un portail web (avec EJB 3 et JSF) pour les joueurs de badminton, où les utilisateurs peuvent publier et analyser leurs résultats.

Pour rester simple (eh bien, il s'avère que ce n'est vraiment pas le cas), j'ai décidé d'utiliser le système de sécurité fourni par le conteneur (JBoss as7). Après un problème, j'ai réussi à faire fonctionner l'authentification/autorisation. Cependant, j'ai un problème que je n'ai pas pu résoudre.

Lorsque j'essaie d'accéder à un page protégée Je suis, comme prévu, intercepté par le système de sécurité. Cependant, après m'être connecté, je ne suis pas redirigé vers la page que j'ai initialement demandée. Au lieu de cela, on me demande une fois de plus de me connecter. Si je tape manuellement l'adresse d'origine, je peux accéder à la page sans aucun problème.

J'ai lu de nombreux threads sur stackoverflow, mais je n'ai pas pu résoudre mon problème. Je serais vraiment reconnaissant si quelqu'un pouvait m'aider!

Authentification.java:

@ManagedBean
@SessionScoped
public class Authentication {

    private String username = "";
    private String password = "";

    private User user = new User();

    @EJB
    UserService service;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public User getUser() {
        return user;
    }

    public void login() {
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest) context
            .getExternalContext().getRequest();

        try {
            Principal userPrincipal = request.getUserPrincipal();
            if (userPrincipal != null) {
                request.logout();
            }
            request.login(username, password);
            user = service.find(username, password);
        } catch (ServletException e) {
            context.addMessage(null, new FacesMessage("Unknown login"));
        }
    }

    public String logout() {
        FacesContext.getCurrentInstance().getExternalContext()
            .invalidateSession();
        return "login";
    }
}

Connexion.xhtml

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

À la maison.xhtml

<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml'
xmlns:f='http://java.sun.com/jsf/core'
xmlns:h='http://java.sun.com/jsf/html'
xmlns:ui='http://java.sun.com/jsf/facelets'
xmlns:p="http://primefaces.org/ui">
<h:head>
    <link type="text/css" rel="stylesheet"
        href="#{request.contextPath}/themes/cupertino/skin.css" />
</h:head>
<h:body>
    <h:form>
        <h:commandButton action="login" value="Log in" />
    </h:form>
</h:body>

Web.xml

....
<display-name>BadmintonPortal</display-name>
<welcome-file-list>
    <welcome-file>/pages/protected/user/user_home.xhtml</welcome-file>
</welcome-file-list>
<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
    <url-pattern>*.jsf</url-pattern>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<context-param>
    <param-name>primefaces.THEME</param-name>
    <param-value>cupertino</param-value>
</context-param>

<!-- Protected area definition -->
<security-constraint>
    <web-resource-collection>
        <web-resource-name>Restricted Area - ADMIN Only</web-resource-name>
        <url-pattern>/pages/protected/admin/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>admin</role-name>
    </auth-constraint>
</security-constraint>
<security-constraint>
    <web-resource-collection>
        <web-resource-name>Restricted Area - USER and ADMIN</web-resource-name>
        <url-pattern>/pages/protected/user/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>user</role-name>
        <role-name>admin</role-name>
    </auth-constraint>
</security-constraint>

<!-- Login page -->
<login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
        <form-login-page>/pages/public/login.xhtml</form-login-page>
        <form-error-page>/pages/public/loginError.xhtml</form-error-page>
    </form-login-config>
</login-config>

<!-- System roles -->
<security-role>
    <role-name>admin</role-name>
</security-role>
<security-role>
    <role-name>user</role-name>
</security-role>

Modifier:

J'ai oublié d'inclure faces-config.fichier xml

<?xml version="1.0" encoding="UTF-8"?>

<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd"
    version="2.1">

    <navigation-rule>
        <navigation-case>
            <from-outcome>login</from-outcome>
            <to-view-id>/pages/protected/user/user_home.xhtml</to-view-id>  
            <redirect/>
        </navigation-case>
    </navigation-rule>
</faces-config>

Jboss-web.xml

<?xml version='1.0' encoding='UTF-8'?>

<jboss-web>
    <context-root>BadmintonPortal</context-root>
    <security-domain>java:/jaas/BadmintonPortalRealm</security-domain>
</jboss-web>

Modifier 2:

Solution de Travail

@ManagedBean
@ViewScoped
public class Authentication {
    ...
    public Authentication() {
        ExternalContext eContext = FacesContext.getCurrentInstance()
            .getExternalContext();
        uri = (String) eContext.getRequestMap().get(
            RequestDispatcher.FORWARD_REQUEST_URI);
    }

    public void login() {
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest) context
            .getExternalContext().getRequest();

        try {
            Principal userPrincipal = request.getUserPrincipal();
            if (userPrincipal != null) {
                request.logout();
            }
            request.login(username, password);
            user = service.find(username, password);
            context.getExternalContext().getSessionMap().put("user", user);
            context.getExternalContext().redirect(uri);
        } catch (ServletException e) {
            context.addMessage(null, new FacesMessage("Unknown login"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String logout() {
        FacesContext.getCurrentInstance().getExternalContext()
            .invalidateSession();
        return "login";
    }
}
Author: BalusC, 2012-11-16

1 answers

Vous prenez en charge la partie connexion en utilisant un formulaire JSF qui effectue une connexion programmatique dans un bean géré JSF lors de la soumission. Si vous utilisiez un formulaire HTML simple qui soumet directement à l'URL d'authentification gérée par conteneur j_security_checkcomme indiqué dans la première partie de cette réponse, vous seriez en effet automatiquement redirigé vers la page initiale.

Cependant, puisque vous prenez la connexion entre vos propres mains en utilisant JSF vous-même, vous devriez également naviguer vers le page initiale en utilisant JSF vous-même. Comme la page de connexion est généralement ouverte côté serveur par RequestDispatcher#forward(), la page initialement demandée est disponible en tant qu'attribut de demande avec le nom spécifié dans RequestDispatcher.FORWARD_REQUEST_URI constant. En termes JSF, cela est donc disponible comme suit:

String originalURI = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI);

(gardez à l'esprit d'avoir une URL de secours pour le cas où elle renvoie null, c'est-à-dire lorsqu'elle a été ouverte directement sans avoir d'abord frappé une URL restreinte)

Le meilleur endroit pour collect it serait le constructeur (post) d'un bean @ViewScoped associé à la page de connexion. Avec l'approche bean de portée de session actuelle, il serait probablement préférable d'en faire une vue étendue et pendant la connexion, placez explicitement le User dans la portée de session comme suit:

externalContext.getSessionMap().put("user", user);

De Cette façon, l'utilisateur est disponible par #{user} directement à la place de #{authentication.user}.

 8
Author: BalusC, 2017-05-23 12:09:41