Выход из системы выходит за пределы JSESSIONID в браузере. Как его очистить?

Я использую следующий код для выхода пользователя из системы.

/**
 * 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();

        }
}

Это приводит к успешному завершению работы, но идентификатор JSESSION, заданный во время входа в систему, по-прежнему остается в браузере, из-за чего для любого нового пользователя снова используется тот же идентификатор JSESSION во время входа в систему. Я хочу, чтобы файл cookie JSESSIONID был действителен только для текущего сеанса, и как только пользователь выходит из системы, он должен быть уничтожен или недействителен для входа в систему в следующий раз. Код моего входа выглядит следующим образом: -

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

Я использую Spring 3.2 и хочу выполнить вход и выход вручную. Пожалуйста, помогите.

Код полного класса

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

Ответ 1

Нет ничего плохого в том, что JSESSIONID остался в вашем браузере, если он уже недействителен. JSESSIONID - это всего лишь куча случайных символов, которые не содержат ваши фактические данные.

Однако я подозреваю, что ваша проблема заключается в том, что вы использовали аннотацию @SessionAttributes на уровне класса, и вы попытались session.invalidate(). При этом сценарии после предыдущего сеанса недействительно Spring автоматически создает для вас новый сеанс (и JSESSIONID), поскольку он должен сохранять указанные атрибуты модели в сеансе.

IMO лучше подходит для создания нового контроллера, у которого нет @SessionAttributes, и отмените сеанс оттуда.

Ответ 2

После нескольких экспериментов я пришел к выводу, что если вы хотите сохранить значение cookie браузера, просто не делайте ничего, и приведенный выше код будет работать для вас. С другой стороны, если вы хотите, чтобы выход файла cookie выглядел как

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

Затем вы можете взять этот фрагмент кода и попробовать его.

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

Это позволит решить проблему и уничтожить файл cookie во время выхода из системы.

Ответ 3

Один из способов, о котором я мог думать, - удалить cookie JSESSIONID при выходе из системы. Способ удаления файла cookie - установить его возраст равным нулю, как показано ниже.

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

Здесь я добавил путь как root. Пожалуйста, проверьте JSESSIONID cookie в своем браузере для правильного пути.

После этого добавьте это в ответ

response.addCookie(cookie);

Вы можете поместить этот код в свой метод exitPrime().

Ответ 4

Не уверен, что он по-прежнему актуальный, но можно расширить LogoutFilter таким образом, чтобы указать точные шаги, которые необходимо выполнить при выходе из системы, включая недействительность пользовательских cookie.

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

Ответ 5

Подход, указанный выше, не работал у меня, но с некоторой модификацией я получил его на работу, я только сделал ограниченное тестирование, хотя и 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;
      }
    }
  }
}

Ответ 6

Tomcat добавляет косую черту в конце контекстного пути. Теперь, когда вы устанавливаете атрибут delete-cookie, Spring пытается найти файл cookie для пути без косой черты в конце. Поскольку он не находит его, cookie не будет удален, что приведет к отображению страницы с истечением срока действия сеанса, а не к странице входа.

Следующее обходное решение сделает трюк.

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
}