我正在使用以下代码从我的系统中注销用户。
/**
* 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 ID仍然保留在浏览器中,因为对于任何新用户,登录时再次使用相同的JSESSION ID。我希望JSESSIONID cookie仅对当前会话有效,一旦用户注销,它将被销毁或无效以便下次完成登录。我的登录代码如下: -
/**
* 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;
}
}
答案 0 :(得分:7)
只要浏览器的JSESSIONID已经无效,它就没有任何问题。 JSESSIONID只是一堆随机字符,不包含您的实际数据。
但是我怀疑您的问题是您在课程级别使用了@SessionAttributes
注释,并尝试session.invalidate()
。在上一个会话失效后的情况下,Spring会自动为您创建一个新会话(和JSESSIONID),因为它必须将指定的模型属性保存到会话中。
IMO更好的方法是创建一个没有@SessionAttributes
的新控制器,并从那里使会话无效。
答案 1 :(得分:7)
经过实验后,我得出结论,如果你想让浏览器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。
答案 2 :(得分:3)
不确定它是否仍然存在,但是可以像这样扩展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>
答案 3 :(得分:2)
我能想到的一种方法是在注销操作时删除JSESSIONID
cookie。删除cookie的方法是将其年龄设置为零,如下所示。
Cookie cookie = new Cookie();
cookie.setValue(null);
cookie.setMaxAge(0);
cookie.setPath("/");
这里我以root身份添加了路径。请在浏览器中查看JSESSIONID
Cookie以获取正确的路径。
完成后,将其添加到回复
response.addCookie(cookie);
您可以将此代码放入exitPrime()
方法中。
答案 4 :(得分:1)
之前列出的方法对我来说并不起作用,但经过一些修改我得到了它的工作,我只做了有限的测试,尽管如此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;
}
}
}
}
答案 5 :(得分:1)
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
}