cookie在setPath时:
domain="happymmall.com"
A.happymmall.com cookie:domain=A.happymmall.com;path="/"
B.happymmall.com cookie:domain=B.happymmall.com;path="/"
A.happymmall.com/test/cc cookie:domain=A.happymmall.com;path="/test/cc"
A.happymmall.com/test/dd cookie:domain=A.happymmall.com;path="/test/dd"
A.happymmall.com/test cookie:domain=A.happymmall.com;path="/test
@Slf4j
public class CookieUtil {
private final static String COOKIE_DOMAIN = "mmall.com";
private final static String COOKIE_NAME = "mmall_login_token";
public static String readLoginToken(HttpServletRequest request){
Cookie[] cks = request.getCookies();
if(cks != null){
for(Cookie ck : cks){
log.info("read cookieName:{},cookieValue:{}",ck.getName(),ck.getValue());
if(StringUtils.equals(ck.getName(),COOKIE_NAME)){
log.info("return cookieName:{},cookieValue:{}",ck.getName(),ck.getValue());
return ck.getValue();
}
}
}
return null;
}
public static void writeLoginToken(HttpServletResponse response, String token){
Cookie ck = new Cookie(COOKIE_NAME,token);
ck.setDomain(COOKIE_DOMAIN);
ck.setPath("/");//代表设置在根目录
ck.setHttpOnly(true);
//单位是秒。
//如果这个maxage不设置的话,cookie就不会写入硬盘,而是写在内存。只在当前页面有效。
ck.setMaxAge(60 * 60 * 24 * 365);//如果是-1,代表永久
log.info("write cookieName:{},cookieValue:{}",ck.getName(),ck.getValue());
response.addCookie(ck);
}
public static void delLoginToken(HttpServletRequest request,HttpServletResponse response){
Cookie[] cks = request.getCookies();
if(cks != null){
for(Cookie ck : cks){
if(StringUtils.equals(ck.getName(),COOKIE_NAME)){
ck.setDomain(COOKIE_DOMAIN);
ck.setPath("/");
ck.setMaxAge(0);//设置成0,代表删除此cookie。
log.info("del cookieName:{},cookieValue:{}",ck.getName(),ck.getValue());
response.addCookie(ck);
return;
}
}
}
}
}
这时候,坑就来了。。。。
你可能在别的博客中看到过这样的代码
区别就在多了一个点
当项目中使用单点登录功能时,通常会使用cookie进行信息的保存,这样就可以在多个子域名上存取用户信息。
三个domain分别为test.com cml.test.com b.test.com这三个域名下的cookie是需要互相访问的。这时会在response上写入cookie信息
如果你使用带 . 的域名,这样写在tomcat8.0是没问题的,二级三级域名可以共享cookie信息。但是把它放到tomcat8.5上就报错了 (java.lang.IllegalArgumentException: An invalid domain [.test.com] was specified for this cookie)
解决方法:
1.指定完整的domain信息,但是这样单点登录就会有问题了
cookie.setDomain("cml.test.com");
2.设置为一级域名(推荐)
cookie.setDomain("test.com");
sessionExpireFilter
com.mmall.controller.common.SessionExpireFilter
sessionExpireFilter
*.do
public class SessionExpireFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
String loginToken = CookieUtil.readLoginToken(httpServletRequest);
if(StringUtils.isNotEmpty(loginToken)){
//判断logintoken是否为空或者"";
//如果不为空的话,符合条件,继续拿user信息
String userJsonStr = RedisShardedPoolUtil.get(loginToken);
User user = JsonUtil.string2Obj(userJsonStr,User.class);
if(user != null){
//如果user不为空,则重置session的时间,即调用expire命令
RedisShardedPoolUtil.expire(loginToken, Const.RedisCacheExtime.REDIS_SESSION_EXTIME);
}
}
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
CookieUtil.writeLoginToken(httpServletResponse,session.getId());
RedisShardedPoolUtil.setEx(session.getId(), JsonUtil.obj2String(response.getData()),Const.RedisCacheExtime.REDIS_SESSION_EXTIME);
String loginToken = CookieUtil.readLoginToken(httpServletRequest);
CookieUtil.delLoginToken(httpServletRequest,httpServletResponse);
RedisShardedPoolUtil.del(loginToken);
String loginToken = CookieUtil.readLoginToken(httpServletRequest);
if(StringUtils.isEmpty(loginToken)){
return ServerResponse.createByErrorMessage("用户未登录,无法获取当前用户的信息");
}
String userJsonStr = RedisShardedPoolUtil.get(loginToken);
User user = JsonUtil.string2Obj(userJsonStr,User.class);
if(user == null){
return ServerResponse.createByErrorMessage("用户未登录");
}
org.springframework.session
spring-session-data-redis
1.2.0.RELEASE
springSessionRepositoryFilter
org.springframework.web.filter.DelegatingFilterProxy
springSessionRepositoryFilter
*.do
@Controller
@RequestMapping("/user/springsession/")
public class UserSpringSessionController {
@Autowired
private IUserService iUserService;
/**
* 用户登录
* @param username
* @param password
* @param session
* @return
*/
@RequestMapping(value = "login.do",method = RequestMethod.GET)
@ResponseBody
public ServerResponse login(String username, String password, HttpSession session, HttpServletResponse httpServletResponse){
//测试全局异常
// int i = 0;
// int j = 666/i;
ServerResponse response = iUserService.login(username,password);
if(response.isSuccess()){
session.setAttribute(Const.CURRENT_USER,response.getData());
// CookieUtil.writeLoginToken(httpServletResponse,session.getId());
// RedisShardedPoolUtil.setEx(session.getId(), JsonUtil.obj2String(response.getData()),Const.RedisCacheExtime.REDIS_SESSION_EXTIME);
}
return response;
}
@RequestMapping(value = "logout.do",method = RequestMethod.GET)
@ResponseBody
public ServerResponse logout(HttpSession session,HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse){
// String loginToken = CookieUtil.readLoginToken(httpServletRequest);
// CookieUtil.delLoginToken(httpServletRequest,httpServletResponse);
// RedisShardedPoolUtil.del(loginToken);
session.removeAttribute(Const.CURRENT_USER);
return ServerResponse.createBySuccess();
}
@RequestMapping(value = "get_user_info.do",method = RequestMethod.GET)
@ResponseBody
public ServerResponse getUserInfo(HttpSession session,HttpServletRequest httpServletRequest){
// String loginToken = CookieUtil.readLoginToken(httpServletRequest);
// if(StringUtils.isEmpty(loginToken)){
// return ServerResponse.createByErrorMessage("用户未登录,无法获取当前用户的信息");
// }
// String userJsonStr = RedisShardedPoolUtil.get(loginToken);
// User user = JsonUtil.string2Obj(userJsonStr,User.class);
User user = (User)session.getAttribute(Const.CURRENT_USER);
if(user != null){
return ServerResponse.createBySuccess(user);
}
return ServerResponse.createByErrorMessage("用户未登录,无法获取当前用户的信息");
}
}