web-dev-qa-db-fra.com

La déconnexion laisse JSESSIONID sur le navigateur. Comment l'effacer?

J'utilise le code suivant pour déconnecter un utilisateur de mon système.

/**
 * This function helps to set the session attribute for the present user to null and then
 * removes the attribute itself and this helps in clearing the session
 * @param request
 * @param response
 */
@RequestMapping(value = AuthConstants.EXIT, method = RequestMethod.POST)
public void exitPrime(HttpServletRequest request, HttpServletResponse response) {
        /*Getting session and then invalidating it*/
        HttpSession session = request.getSession(false);
        if(request.isRequestedSessionIdValid() && session != null)
        {
            session.invalidate();

        }
}

Cela conduit à une déconnexion réussie, mais l'ID JSESSION donné par lors de la connexion reste dans le navigateur, car pour tout nouvel utilisateur, le même ID JSESSION est utilisé à nouveau lors de la connexion. Je veux que le cookie JSESSIONID soit valide uniquement pour la session en cours et une fois que l'utilisateur se déconnecte, il doit être détruit ou invalide pour la connexion effectuée pour la prochaine fois. Mon code de connexion est le suivant: -

/**
 * This method allows one to log into the system and generates a token for a valid employee.
 * @param authRequest
 * @param request
 * @param response
 * @return
 */
@RequestMapping(value = AuthConstants.ENTRY, method = RequestMethod.POST, consumes = ApplicationConstants.APPLICATION_JSON)
public @ResponseBody
AuthResponse primeEntry(@RequestBody AuthRequest authRequest,HttpServletRequest request, HttpServletResponse response) {
    AuthResponse authResponse = new AuthResponse();
    if(authRequest != null && authRequest.getEmployeeAuth().getEmployeeNumber() != null 
            && !authRequest.getEmployeeAuth().getEmployeeNumber().isEmpty()){
        /*To check whether the user is valid*/
        String employeeNumber = authRequest.getEmployeeAuth().getEmployeeNumber();
        UserBean userBean = new UserBean();
        userBean = userService.getUser(employeeNumber);
        if(userBean != null)
            {
            HttpSession session = request.getSession(true);
            session.setAttribute("user", userBean);
            setAuthResponseSuccess(authResponse);
        }else{
            /*If user does not exist the too throw error 500*/
            setAuthResponseFailure(authResponse);
        }
    }else{
        /*If input JSON is not valid then throw error 500*/
        setAuthResponseFailure(authResponse);
    }
    return authResponse;
}

J'utilise Spring 3.2 et je souhaite me connecter et me déconnecter manuellement. Veuillez aider.

Code de classe complet

@Controller
@RequestMapping(value = "/auth")
public class AuthController {
    @Autowired
    HttpServletRequest request;

    @Autowired
    HttpSession session;

    @Autowired
    IUserService userService;

    /**
     * This method allows one to log into the system and generates a token for a valid employee.
     * @param authRequest
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = AuthConstants.ENTRY, method = RequestMethod.POST, consumes = ApplicationConstants.APPLICATION_JSON)
    public @ResponseBody
    AuthResponse primeEntry(@RequestBody AuthRequest authRequest,HttpServletRequest request, HttpServletResponse response) {
        AuthResponse authResponse = new AuthResponse();
        if(authRequest != null && authRequest.getEmployeeAuth().getEmployeeNumber() != null 
                && !authRequest.getEmployeeAuth().getEmployeeNumber().isEmpty()){
            /*To check whether the user is valid*/
            String employeeNumber = authRequest.getEmployeeAuth().getEmployeeNumber();
            UserBean userBean = new UserBean();
            userBean = userService.getUser(employeeNumber);
            if(userBean != null)
                {
                HttpSession session = request.getSession(true);
                session.setAttribute("user", userBean);
                setAuthResponseSuccess(authResponse);
            }else{
                /*If user does not exist the too throw error 500*/
                setAuthResponseFailure(authResponse);
            }
        }else{
            /*If input JSON is not valid then throw error 500*/
            setAuthResponseFailure(authResponse);
        }
        return authResponse;
    }


    /**
     * This function helps to set the session attribute for the present user to null and then
     * removes the attribute itself and this helps in clearing the session
     * @param request
     * @param response
     */
    @RequestMapping(value = AuthConstants.EXIT, method = RequestMethod.POST)
    public void exitPrime(HttpServletRequest request, HttpServletResponse response) {
            /*Getting session and then invalidating it*/
            HttpSession session = request.getSession(false);
            if(request.isRequestedSessionIdValid() && session != null)
            {
                session.invalidate();

            }
    }

    private AuthResponse setAuthResponseFailure(AuthResponse authResponse) {
        authResponse.setResponseCode(ApplicationConstants.INTERNAL_ERROR_CODE);
        authResponse.setStatus(StatusType.FAILURE);
        authResponse.setResponseMsg(ApplicationConstants.INTERNAL_ERROR_MESSAGE);
        return authResponse;
    }
    private AuthResponse setAuthResponseSuccess(AuthResponse authResponse){
        authResponse.setResponseCode(ApplicationConstants.OK);
        authResponse.setStatus(StatusType.SUCCESS);
        authResponse.setResponseMsg(ApplicationConstants.LOGIN_SUCCESS);
        return authResponse;
    }
}
18
Shiv Kumar Ganesh

Après avoir expérimenté un peu, je suis arrivé à la conclusion que si vous voulez que la valeur du cookie du navigateur persiste, ne faites rien et le code ci-dessus fonctionnerait bien pour vous. D'un autre côté, si vous voulez la sortie du cookie quelque chose comme

Set-Cookie: JSESSIONID=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/

Ensuite, vous pouvez prendre cet extrait de code et l'essayer.

private void handleLogOutResponseCookie(HttpServletResponse response) {
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            cookie.setMaxAge(0);
            cookie.setValue(null);
            cookie.setPath("/");
            response.addCookie(cookie);
        }

Cela résoudrait le problème et détruirait le cookie lorsque vous vous déconnectez.

8
Shiv Kumar Ganesh

Il n'y a rien de mal avec les restes de JSESSIONID sur votre navigateur tant qu'il est déjà invalide. JSESSIONID n'est qu'un groupe de caractères aléatoires qui ne contiennent pas vos données réelles.

Cependant, je soupçonne que votre problème est que vous avez utilisé l'annotation @SessionAttributes Au niveau de la classe et que vous avez tenté session.invalidate(). Avec ce scénario après invalidation de la session précédente, Spring automatiquement crée une nouvelle session (et JSESSIONID) pour vous car il doit conserver les attributs de modèle spécifiés dans la session.

IMO une meilleure approche consiste à créer un nouveau contrôleur qui n'a pas @SessionAttributes Et invalider votre session à partir de là.

7
gerrytan

Je ne sais pas s'il est toujours réel, mais on peut étendre LogoutFilter comme ceci pour spécifier les étapes exactes à effectuer lors de la déconnexion, y compris l'invalidation des cookies personnalisés.

<beans:bean id="sessionInvalidationFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
    <beans:property name="filterProcessesUrl" value="/logout"/>
    <beans:constructor-arg>
        <beans:array>
            <beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
            <beans:bean class="org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler">
                <beans:constructor-arg value="JSESSIONID"/>
            </beans:bean>
        </beans:array>
    </beans:constructor-arg>
</beans:bean>
3
Igor Grunskiy

Une façon dont je pourrais penser est de supprimer le cookie JSESSIONID lors de la déconnexion. La façon de supprimer le cookie est de mettre son âge à zéro comme suit.

Cookie cookie = new Cookie();
cookie.setValue(null);
cookie.setMaxAge(0);
cookie.setPath("/");

Ici, j'ai ajouté le chemin en tant que root. Veuillez vérifier JSESSIONID cookie dans votre navigateur pour le chemin correct.

Une fois que vous avez ceci, ajoutez ceci à la réponse

response.addCookie(cookie);

Vous pouvez mettre ce code dans votre méthode exitPrime().

2
Santosh

L'approche listée précédemment n'a pas fonctionné pour moi, mais avec quelques modifications, je l'ai fait fonctionner, je n'ai fait que des tests limités, donc YMMV.

protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
  HttpSession session = req.getSession(false);
  if (session != null) {
    String sessionId = session.getId();
    session.invalidate();
    Cookie[] cookies = req.getCookies();
    for (Cookie cookie : cookies) {
      if (sessionId.equalsIgnoreCase(cookie.getValue())) {
        cookie.setMaxAge(0);
        cookie.setValue(null);
        cookie.setDomain(req.getServerName());
        cookie.setPath(req.getServletContext().getContextPath() + "/");
        cookie.setSecure(req.isSecure());
        res.addCookie(cookie);
        break;
      }
    }
  }
}
1
J Gibbs

Tomcat ajoute une barre oblique à la fin du chemin de contexte. Désormais, lorsque vous définissez l'attribut delete-cookie, Spring essaie de trouver le cookie du chemin sans barre oblique à la fin. Parce qu'il ne le trouve pas, le cookie ne sera pas supprimé, ce qui entraînera l'affichage de la page d'expiration de la session au lieu de la page de connexion.

La solution de contournement suivante fera l'affaire.

public void logout(HttpServletRequest request, HttpServletResponse response,
                    Authentication auth) {
    Cookie cookieWithSlash = new Cookie("JSESSIONID", null);
    //Tomcat adds extra slash at the end of context path (e.g. "/foo/")
    cookieWithSlash.setPath(request.getContextPath() + "/"); 
    cookieWithSlash.setMaxAge(0); 

    Cookie cookieWithoutSlash = new Cookie("JSESSIONID", null);
    //JBoss doesn't add extra slash at the end of context path (e.g. "/foo")
    cookieWithoutSlash.setPath(request.getContextPath()); 
    cookieWithoutSlash.setMaxAge(0); 

    //Remove cookies on logout so that invalidSessionURL (session timeout) is not displayed on proper logout event
    response.addCookie(cookieWithSlash); //For Tomcat 
    response.addCookie(cookieWithoutSlash); //For JBoss
}
1
Debasmita Sahoo