单点登录原理
实现简单的同域名下的单点登录,适合分布式系统下使用,因为在分布式系统中,用户的请求可能被不同的服务器处理,而不同的服务器自动生成的cookie–JSESSIONID是不一致的,不能通过这个cookie去定位用户的登录状态,因此需要一个自定义的cookie注入到用户浏览器,不管用户的请求被哪个服务器处理,均能通过该cookie定位用户的信息是否存在缓存中;用户首次访问网页时,需要验证登录,用户登录成功后,服务器会生成自定义的cookie注入用户浏览器,并将用户信息写入Redis缓存中,具有一定的有效期;用户再次访问时,通过cookie中存储的SessionID去Redis中查找用户信息,若用户信息存在,可直接访问网页,不需要再次登录。
原理分析时序图如下
单点登录实现
- 引入jedis依赖到pom.xml中
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.6.0</version>
</dependency>
- 构建Redis连接池–JedisPool
public class RedisPool {
//static --> 保证jedispool在Tomcat启动时加载
private static JedisPool pool; //jedis连接池
private static Integer maxTotal = Integer.parseInt(PropertiesUtil.getProperty("redis.max.total", "20")); //控制连接池与Redis Server最大的连接数
private static Integer maxIdle = Integer.parseInt(PropertiesUtil.getProperty("redis.max.idle", "10")); //连接池中最大的空闲的jedis实例,想用的时候可以立刻使用
private static Integer minIdle = Integer.parseInt(PropertiesUtil.getProperty("redis.min.idle", "2")); //连接池中最小的空闲的jedis实例,想用的时候可以立刻使用
private static Boolean testOnBorrow = Boolean.parseBoolean(PropertiesUtil.getProperty("redis.test.borrow", "true")); //在borrow一个jedis实例的时候,是否要进行验证操作,如果赋值为true,则得到的jedis实例肯定是可以用的。
private static Boolean testOnReturn = Boolean.parseBoolean(PropertiesUtil.getProperty("redis.test.return", "true")); //在return一个jedis实例的时候,是否要进行验证操作,如果赋值为true,则放回jedispool的jedis实例肯定是可以用的。
private static String redisIp = PropertiesUtil.getProperty("redis.ip");//ip地址
private static Integer redisPort = Integer.parseInt(PropertiesUtil.getProperty("redis.port"));//端口
private static void initPool() {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(maxTotal);
config.setMaxIdle(maxIdle);
config.setMinIdle(minIdle);
config.setTestOnBorrow(testOnBorrow);
config.setTestOnReturn(testOnReturn);
config.setBlockWhenExhausted(true); //连接耗尽时是否阻塞,false会抛出异常,true阻塞直到超时。默认值为true
pool = new JedisPool(config, redisIp, redisPort, 1000*2);
}
// JVM 加载的时候就初始化jedispool
static {
initPool();
}
//从连接池获取一个jedis
public static Jedis getJedis() {
return pool.getResource();
}
//放回一个坏的jedis连接
public static void returnBrokenResource(Jedis jedis) {
pool.returnBrokenResource(jedis);
}
//将一个jedis放回连接池
public static void returnResource(Jedis jedis) {
pool.returnResou