一、为什么需要session
举例:比如张三登录的A网页然后进行用户名和密码登录之后,当跳转到B页面的时候,如果B页面也需要登录信息。这个时候由于HTTP协议是一个无状态协议,这样就需要张三再次登录。因此需要在HTTP协议之上进行扩展,这个时候就引入了cookie和session。
二、Cookie与Session
1. cookie 是什么?
- 是存储于用户主机浏览器中的一小段文本文件
- 由服务器端生成,发送给浏览器,KV形式存储
2. Session 是什么?
- 字面理解为 “会话”
- 保存在服务端的数据结构
3. Session 和 cookie 的区别
4. Session 的工作原理
5. 简单的代码实现session
@RestController
public class TestController {
@RequestMapping(value = "/first-index", method = RequestMethod.GET)
public String helloWorld(){
return "hello, springboot!!!";
}
static Map<String, String> passwordMap = new HashMap<>();
static {
passwordMap.put("zhangsan", "123");
passwordMap.put("lisi", "321");
}
@RequestMapping("/index")
@ResponseBody
public String index(HttpServletRequest request){
HttpSession httpSession = request.getSession();
//从session中获取用户登录信息
Boolean isLogin = (Boolean)httpSession.getAttribute("isLogin");
if(isLogin != null && isLogin){
return "欢迎 " + httpSession.getAttribute("username")
+ " 进入首页!";
}else {
return "请登录!";
}
}
@RequestMapping(value = "/login", method = RequestMethod.GET)
@ResponseBody
public String login(HttpServletRequest request,
@RequestParam("username")String username,
@RequestParam("password")String password){
//1、验证用户名和密码
if(!passwordMap.containsKey(username)){
return "请先注册";
}
if(!passwordMap.get(username).equalsIgnoreCase(password)){
return "密码错误";
}
//2、生成session
HttpSession httpSession = request.getSession();
//3、将登录信息写入session
httpSession.setAttribute("isLogin", Boolean.TRUE);
httpSession.setAttribute("username", username);
//4、返回
return "welcome " + username;
}
}
根据源码可得知,当创建session的时候 默认会生成一个cookiesName=“JSESSIONID”
三、分布式session
1. 分布式session失效
单体服务器到分布式环境集群的时候,用户第一次访问路由到了A服务器登录信息写入到A服务器,当用户再次访问,网关路由到了B服务器,然后B服务器没有保存用户信息,这样导致session失效
2. session粘连,解决session失效
思路:
反向代理层让同一个用户的请求保证落在一台server上呢?
方法一:四层代理hash。反向代理层使用用户ip来做hash,以保证同一个ip的请求落在同一个server上(更推荐,保证传输层不引入业务层的逻辑)
方法二:七层代理hash。反向代理使用http协议中的某些业务属性来做hash,例如sid,city_id,user_id等,能够更加灵活的实施hash策略,以保证同一个浏览器用户的请求落在同一个server上
优点:
只需要改nginx配置,不需要修改应用代码
可以支持server水平扩展
不足:
server水平扩展,rehash后session重新分布,会有一部分用户路由不到正确的session,即使hash散列均匀,也不能保证server的负载均匀
3. session复制
思路:
多个server之间相互同步session,这样每个server之间都包含全部的session
优点:
只需要设定配置,应用程序不需要修改代码
不足:
session的同步需要数据传输,占内网带宽,有延时所有server都包含所有session数据,数据量受最小内存的sever限制,水平拓展能力差
4. session中心存储
四、redis实现分布式session
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class RedisSessionConfig {
}
在写完配置类后,前万记得要在在spring boot的启动类上写上注解@EnableRedisHttpSession