Cookie + session 理解
Http是一种无状态的应用层传输协议。可以理解成请求之间没有联系。但是很多场景,比如需要知道上次是哪个用户登录了。这时就要用到cookie和session了。
一. 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一般也会存额外一些信息,比如可以存购物车信息,存在服务器端,用占用服务器的性能。
因为相信,所以看见.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
2022-08-02 人生大事--- 选对伴侣