diff --git a/java/springboot系列/数据库/2.springboot整合redis缓存.md b/java/springboot系列/数据库/2.springboot整合redis缓存.md
index 149ee53..9445169 100644
--- a/java/springboot系列/数据库/2.springboot整合redis缓存.md
+++ b/java/springboot系列/数据库/2.springboot整合redis缓存.md
@@ -10,10 +10,12 @@ categories:
![薄暮传说](https://raw.githubusercontent.com/FleyX/files/master/blogImg/20190311141056.png)
-**本篇原创发布于:**[springboot整合redis](http://www.tapme.top/blog/detail/2019-02-22-14-59)
+**本篇原创发布于:**[springboot 整合 redis](http://www.tapme.top/blog/detail/2019-02-22-14-59)
**项目源码:**:[github](https://github.com/FleyX/demo-project/tree/master/1.SSO%E5%8D%95%E7%82%B9%E7%99%BB%E5%BD%95/sso)
+**特别说明**:本文针对的是新版 spring boot 2.1.3,其 spring data 依赖为 spring-boot-starter-data-redis,且其默认连接池为 lettuce
+
redis 作为一个高性能的内存数据库,如果不会用就太落伍了,之前在 node.js 中用过 redis,本篇记录如何将 redis 集成到 spring boot 中。提供 redis 操作类,和注解使用 redis 两种方式。主要内容如下:
- docker 安装 redis
@@ -46,12 +48,28 @@ services:
## 添加 maven 依赖
- 只需添加`spring-boot-starter-data-redis`依赖即可
+ 只需添加`spring-boot-starter-data-redis`依赖即可,并排除 lettuce 依赖,然后引入 jedis 和 jedis 的依赖 commons-pool2
```xml
org.springframework.boot
spring-boot-starter-data-redis
+
+
+ io.lettuce
+ lettuce-core
+
+
+
+
+
+ org.apache.commons
+ commons-pool2
+
+
+
+ redis.clients
+ jedis
```
@@ -120,7 +138,7 @@ public class RedisConfig extends CachingConfigurerSupport {
@SuppressWarnings("all")
@Bean
- public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
+ public RedisTemplate redisTemplate(JedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
@@ -135,6 +153,29 @@ public class RedisConfig extends CachingConfigurerSupport {
template.afterPropertiesSet();
return template;
}
+
+ //使用jedis连接池建立jedis连接工厂
+ @Bean
+ public JedisConnectionFactory jedisConnectionFactory() {
+ logger.info("jedisConnectionFactory:初始化了");
+ JedisPoolConfig config = new JedisPoolConfig();
+ config.setMaxIdle(maxIdle);
+ config.setMinIdle(minIdle);
+ config.setMaxWaitMillis(maxWaitMillis);
+ config.setMaxTotal(maxActive);
+ //链接耗尽时是否阻塞,默认true
+ config.setBlockWhenExhausted(true);
+ //是否启用pool的jmx管理功能,默认true
+ config.setJmxEnabled(true);
+ JedisConnectionFactory factory = new JedisConnectionFactory();
+ factory.setPoolConfig(config);
+ factory.setHostName(host);
+ factory.setPort(port);
+ factory.setPassword(password);
+ factory.setDatabase(database);
+ factory.setTimeout(timeout);
+ return factory;
+ }
}
```
@@ -232,12 +273,13 @@ public class RedisService {
return user;
}
```
-上面的代码执行后将在redis中插入两条记录。使用`keys *`将看到如下结果:
+
+上面的代码执行后将在 redis 中插入两条记录。使用`keys *`将看到如下结果:
![结果](https://raw.githubusercontent.com/FleyX/files/master/blogImg/20190311140300.png)
### 手动控制
- 手动控制就相当于mybatis的手写sql语句,需要调用`redisTemplate`中的各种方法来进行缓存查询,缓存更新,缓存删除等操作。
+ 手动控制就相当于 mybatis 的手写 sql 语句,需要调用`redisTemplate`中的各种方法来进行缓存查询,缓存更新,缓存删除等操作。
- 使用方法参见util/RedisUtil中的方法。`redisTemplate`基本可以实现所有的redis操作。
+ 使用方法参见 util/RedisUtil 中的方法。`redisTemplate`基本可以实现所有的 redis 操作。
diff --git a/java/web相关/2.spring boot SSO单点登录.md b/java/web相关/2.spring boot SSO单点登录.md
index 4b4a050..11d341b 100644
--- a/java/web相关/2.spring boot SSO单点登录.md
+++ b/java/web相关/2.spring boot SSO单点登录.md
@@ -32,6 +32,8 @@ categories:
单点点说就是:一次登录后可免登陆访问其他的可信平台。比如我们登录淘宝网后,再打开天猫首页可以发现已经是登录状态了。SSO 是一种比较流行的服务于企业业务整合的一种解决方案。
+
+
# 如何实现 SSO
我们都知道目前的 http 协议是无状态的,也就是第一次请求和第二次请求是完全独立,不相关的,但现实中我们的业务逻辑都是有状态的,这样就引入了 cookie-session 的机制来维护状态,浏览器端存储一个 sessionId,后台存储跟该 sessionId 相关的数据。每次向后台发起请求时都携带此 sessionId 就能维持状态了。然后就有了 cookie,浏览器在发送请求时自动将 cookie 中的数据放到请求中,发给服务端,无需手动设置。
@@ -107,22 +109,38 @@ categories:
这个办法就是**回调**。系统 A 的前台在跳转到 SSO 的前台时,将当前路径作为 url 参数传递给 sso 前台,sso 前台在获取到 jwt 后,再跳转到系统 A 传过来的 url 路径上,并带上 jwt 作为 url 参数。这就完成了 jwt 的一次共享,从 sso 共享到系统 A。
-打个比方:你点了个外卖,别人要怎么把外卖给你呢?显然你会留下的地址,让别人带上饭送到这个地址,然后你就能享用美食了。这和jwt的传递非常相识了。
+打个比方:你点了个外卖,别人要怎么把外卖给你呢?显然你会留下的地址,让别人带上饭送到这个地址,然后你就能享用美食了。这和 jwt 的传递非常相识了。
-系统A说:我要jwt,快把它送到http://localhost:8081/test1/这个地址上。
+系统 A 说:我要 jwt,快把它送到http://localhost:8081/test1/这个地址上。
-SSO说:好嘞,这个地址是合法的可以送jwt过去,这就跳转过去:http://localhost:8081/test1/?jwt=abcdefj.asdf.asdfasf
+SSO 说:好嘞,这个地址是合法的可以送 jwt 过去,这就跳转过去:http://localhost:8081/test1/?jwt=abcdefj.asdf.asdfasf
-系统A说:不错不错,真香。
+系统 A 说:不错不错,真香。
- 要注意这里**有个坑**就是:如果另外一个恶意系统C安装相同的格式跳转到SSO,想要获取jwt,这显然是不应该给它的。所以在回跳回去的时候要判断一下这个回调地址是不是合法的,能不能给jwt给它,可以向后台请求判断也可以在sso前台直接写死合法的地址。在demo是没有这个判断过程的。
+ 要注意这里**有个坑**就是:如果另外一个恶意系统 C 安装相同的格式跳转到 SSO,想要获取 jwt,这显然是不应该给它的。所以在回跳回去的时候要判断一下这个回调地址是不是合法的,能不能给 jwt 给它,可以向后台请求判断也可以在 sso 前台直接写死合法的地址。在 demo 是没有这个判断过程的。
+
+### 实现业务系统
+
+ 业务系统代码非常简单,主要是用了一个拦截器,拦截 http 请求,提取出 token 向 sso 认证中心验证 token 是否有效,有效放行,否则返回错误给前端。太简单也不贴代码了,到 github 上看看就明白了。
# 效果
- 上面说了一大串都是原理了,其实这个难也就难在原理部分,代码实现并没有那么复杂。这里就不贴代码了,有需要直接到github上看。
+ 上面说了一大串都是原理了,其实这个难也就难在原理部分,代码实现并没有那么复杂。这里就不贴代码了,有需要直接到 github 上看。
- 这里上个效果图:
+ 这里上几个效果图:
+- 系统 A 首次登陆系统
+ ![系统A登陆gif](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E7%B3%BB%E7%BB%9F1%E9%A6%96%E6%AC%A1%E7%99%BB%E5%BD%95.gif)
-可以看到,在系统A登录系统后,系统B,系统C都不再需要输入用户名密码进行登录。如果速度足够快甚至都注意不到调到SSO再跳回来的过程。
+可以看到首次登陆是需要跳到 sso 认证中心输入用户名密码进行登陆验证的。登陆成功回跳后接口请求成功。
+- 将 A 的启动端口改为 8082 后再次启动,当作系统 B
+ ![系统B登陆gif](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E7%B3%BB%E7%BB%9F2%E7%99%BB%E5%BD%95.gif)
+
+可以看到这次是无需登陆的,跳到认证中心后就马上跳回了,如果去掉 alert 一般是看不出跳转过程的。
+
+最后在任意一个系统注销,都会让所有的系统推出登陆。
+
+可以看到,在系统 A 登录系统后,系统 B,系统 C 都不再需要输入用户名密码进行登录。如果速度足够快甚至都注意不到调到 SSO 再跳回来的过程。
+
+ 如果有什么问题,可以在下方留言,或者邮件给我。看到都会回复的。
diff --git a/java/web相关/file/系统1首次登录.gif b/java/web相关/file/系统1首次登录.gif
new file mode 100644
index 0000000..0b73eab
Binary files /dev/null and b/java/web相关/file/系统1首次登录.gif differ
diff --git a/java/web相关/file/系统2登录.gif b/java/web相关/file/系统2登录.gif
new file mode 100644
index 0000000..88f3db1
Binary files /dev/null and b/java/web相关/file/系统2登录.gif differ