一. Cookie
Cookie是一种客户端技术,可以理解成用户信息存储在客户端。客户端第一次请求服务器时,如果需要记录用户状态,就用response特意给客户端生成一个Cookie,客户端会自动保存起来。当再次请求时,客户端把Cookie也提交给服务器。服务器通过request拿到cookie,就可以判断用户状态。下面举个简单的代码应用。
//自定义拦截器,要结合MyWebConfig使用
@Component
public class CookieInterceptor implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(CookieInterceptor.class);
/**
* 在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("CookieInterceptor preHandle");
String requestURI = request.getRequestURI();
Cookie[] cookies = request.getCookies();
//1.如果是登录接口,则设置cookie
if (requestURI.contains("/loginInfo/login")) {
response.addCookie(new Cookie("hasLogined", "true"));
//2.如果不是登录接口,则校验有无cookie
} else {
boolean flag = false;
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("hasLogined")) {
flag = true;
break;
}
}
}
if (!flag) {
LOGGER.error("please login first");
return false;
}
}
return true;
}
举例代码里,我们把Cookie处理放在拦截器里,一般项目里也都可以这样处理,拦截器可以用请求做一些预处理,比如这里用Cookie校验用户的登录状态。如果请求是登录接口,那么生成一个Cookie(客户端可以存储多个cookie),用response.addCookie方法即可传给客户端。当不是登录的请求过来时,就先从request里拿到所有Cookie,看看是否有用户登录状态,如果没有直接被拦截。这里只是个简单的应用,实际场景会相对复杂,也可以给cookie设置域,存活时间等。
二. Session
Session是一种服务器端技术,可以理解成把用户登录状态存在服务器端。登录接口里,服务器生成一个Session,里面可以保存用户信息。当请求业务接口时,先获取Session,再进一步核对用户信息。那么客户端是怎么获取到Session的呢,实际上Session还是要配合Cookie使用,在生成Session时候,底层会把这个Session对应的SessionId存到Cookie中传给客户端,再次请求时就可以拿到SessionId去服务器里找对应的Session。下面举个简单的代码应用。
private Set<String> sessionIds = Sets.newHashSet();
/**
* 在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("SessionInterceptor preHandle");
String requestURI = request.getRequestURI();
//1.如果是登录接口,则设置session
if (requestURI.contains("/loginInfo/login")) {
// 用户登陆时如果携带了sessionid,则先将session做invalid处理
HttpSession session = request.getSession(false);
if (null != session) {
session.invalidate();
}
// ture,则如果获取不到session,会生成一个;因为上面已失效,所以这里会新生成一个
session = request.getSession(true);
String sessionId = session.getId();
System.out.println("preHandle sessionId=" + sessionId);
//可以将sessionID存到数据库,redis,内存中;分布式场景中一般会存到redis;此处存在内存中
sessionIds.add(sessionId);
//额外业务
InfoVO infoVO = new InfoVO();
infoVO.setName("libai");
session.setAttribute("myKey",infoVO);
} else {
String sessionId = request.getSession().getId();
System.out.println("request sessionId = " + sessionId);
if (!sessionIds.contains(sessionId)) {
LOGGER.error("please login first");
return false;
}
//额外业务
HttpSession session = request.getSession();
InfoVO myKey =(InfoVO) session.getAttribute("myKey");
System.out.println(myKey);
}
return true;
}
同样把Session处理放到拦截器里。可以看到生成Session很简单,就是request.getSession(boolean flag)。flag为false表示获取Session,如果获取不到为null。如果flag为true,如果获取不到,则新生成一个Session。上面的业务场景每次登陆都把原来的Session失效,新生成一个Session。然后把Session对应的SessionId(随机生成的字符串,大概长这样:D8F5058D22978D71D14644777571AD18)存到内存里。再次请求时,Cookie就会附带SessionId(叫JSESSIONID),简单的场景用SessionId就可以判断登陆状态了。复杂场景里,也可以把真个用户信息放到Session里,如上面代码里注释的额外业务里。
三. 总结
Cookie有安全问题,因为用户信息直接放到客户端,可以被别人看到。另外Cookie存的信息也有限。
Session有性能问题,因为Session一般也会存额外一些信息,比如可以存购物车信息,存在服务器端,用占用服务器的性能。
因为相信,所以看见.