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