文档章节

从零开始的Spring Session(一)

二十岁以后
 二十岁以后
发布于 2017/09/12 10:41
字数 1522
阅读 77
收藏 1

本文作者:徐靖峰
原文链接:http://t.cn/Rp7xUro
版权归作者所有,转载请注明出处

 

之前项目需要使用Redis管理Session,找了很多的Demo,研究了一天Spring Session源码,感觉有点难继续。突然看到群里Pivotal的周辉大牛发了一篇连接,突然豁然开朗。

 

Session和Cookie这两个概念,在学习java web开发之初,大多数人就已经接触过了。最近在研究跨域单点登录的实现时,发现对于Session和Cookie的了解,并不是很深入,所以打算写两篇文章记录一下自己的理解。在我们的应用集成Spring Session之前,先补充一点Session和Cookie的关键知识。

Session与Cookie基础

由于http协议是无状态的协议,为了能够记住请求的状态,于是引入了Session和Cookie的机制。我们应该有一个很明确的概念,那就是Session是存在于服务器端的,在单体式应用中,他是由tomcat管理的,存在于tomcat的内存中,当我们为了解决分布式场景中的session共享问题时,引入了redis,其共享内存,以及支持key自动过期的特性,非常契合session的特性,我们在企业开发中最常用的也就是这种模式。但是只要你愿意,也可以选择存储在JDBC,Mongo中,这些,spring都提供了默认的实现,在大多数情况下,我们只需要引入配置即可。而Cookie则是存在于客户端,更方便理解的说法,可以说存在于浏览器。Cookie并不常用,至少在我不长的web开发生涯中,并没有什么场景需要我过多的关注Cookie。http协议允许从服务器返回Response时携带一些Cookie,并且同一个域下对Cookie的数量有所限制,之前说过Session的持久化依赖于服务端的策略,而Cookie的持久化则是依赖于本地文件。虽然说Cookie并不常用,但是有一类特殊的Cookie却是我们需要额外关注的,那便是与Session相关的sessionId,他是真正维系客户端和服务端的桥梁。

代码示例

用户发起请求,服务器响应请求,并做一些用户信息的处理,随后返回响应给用户;用户再次发起请求,携带sessionId,服务器便能够识别,这个用户就是之前请求的那个。

使用Springboot编写一个非常简单的服务端,来加深对其的理解。需求很简单,当浏览器访问localhost:8080/test/cookie?browser=xxx时,如果没有获取到session,则将request中的browser存入session;如果获取到session,便将session中的browser值输出。顺便将request中的所有cookie打印出来。

@Controller
public class CookieController {
    @RequestMapping("/test/cookie")
    public String cookie(@RequestParam("browser") String browser, HttpServletRequest request, HttpSession session) {
        //取出session中的browser
        Object sessionBrowser = session.getAttribute("browser");
        if (sessionBrowser == null) {
            System.out.println("不存在session,设置browser=" + browser);
            session.setAttribute("browser", browser);
        } else {
            System.out.println("存在session,browser=" + sessionBrowser.toString());
        }
        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie cookie : cookies) {
                System.out.println(cookie.getName() + " : " + cookie.getValue());
            }
        }
        return "index";
    }
}

我们没有引入其他任何依赖,看看原生的session机制是什么。

1 使用chrome浏览器,访问localhost:8080/test/cookie?browser=chrome,控制台输出如下:

 

1

 

Session Info: 不存在session,设置browser=chrome

既没有session,也没有cookie,并且根据我们将browser=chrome已经设置到了session中。

再次访问同样的地址,控制台输出如下:

 

1

2

 

Session Info: 存在session,browser=chrome

Cookie Info: JSESSIONID : 4CD1D96E04FC390EA6C60E8C40A636AF

多次访问之后,控制台依旧打印出同样的信息。

稍微解读下这个现象,可以验证一些结论。当服务端往session中保存一些数据时,Response中自动添加了一个Cookie:JSESSIONID:xxxx,再后续的请求中,浏览器也是自动的带上了这个Cookie,服务端根据Cookie中的JSESSIONID取到了对应的session。这验证了一开始的说法,客户端服务端是通过JSESSIONID进行交互的,并且,添加和携带key为JSESSIONID的Cookie都是tomcat和浏览器自动帮助我们完成的,这很关键。

2 使用360浏览器,访问localhost:8080/test/cookie?browser=360

第一次访问:

 

1

 

Session Info: 不存在session,设置browser=360

后续访问:

 

1

2

 

Session Info: 存在session,browser=360

Cookie Info: JSESSIONID : 320C21A645A160C4843D076204DA2F40

为什么要再次使用另一个浏览器访问呢?先卖个关子,我们最起码可以得出结论,不同浏览器,访问是隔离的,甚至重新打开同一个浏览器,JSESSIONID也是不同的。

安全问题

其实上述的知识点,都是非常浅显的,之所以啰嗦一句,是为了引出这一节的内容,以及方便观察后续我们引入Spring Session之后的发生的变化。

还记得上一节的代码示例中,我们使用了两个浏览器:

  • chrome浏览器访问时,JSESSIONID为4CD1D96E04FC390EA6C60E8C40A636AF,后端session记录的值为:browser=chrome
  • 360浏览器访问时,JSESSIONID为320C21A645A160C4843D076204DA2F40,后端session记录的值为:browser=360。

我们使用chrome插件Edit this Cookie,将chrome浏览器中的JSESSIONID修改为360浏览器中的值

EditThisCookieEditThisCookie

同样访问原来的端点:localhost:8080/test/cookie?browser=chrome,得到的输出如下:

 

1

2

 

存在session,browser=360

JSESSIONID : 320C21A645A160C4843D076204DA2F40

证实了一点,存放在客户端的Cookie的确是存在安全问题的,我们使用360的JSESSIONID“骗”过了服务器。毕竟,服务器只能通过Cookie中的JSESSIONID来辨别身份。(这提示我们不要在公共场合保存Cookie信息,现在的浏览器在保存Cookie时通常会让你确定一次)

然而我使用以上Demo报出了Redis错误!经过排查和浏览官网找到了答案。

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'enableRedisKeyspaceNotificationsInitializer' defined in org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration: Invocation of init method fail ed; nested exception is java.lang.IllegalStateException: Unable to configure Redis to keyspace notifications. See http://docs.spring.io/spring-session/docs/current/reference/html5/#api-redisoperationssessionrepository-sessiondestroyedevent at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)

 

完美解决!!!

 

本文转载自:

共有 人打赏支持
二十岁以后
粉丝 230
博文 25
码字总数 23016
作品 0
海淀
架构师
私信 提问
加载中

评论(1)

熊猫你好
熊猫你好
前面写的不过,但是后面是个什么鬼,从 完美解决错误哪里完全是牛头不对马嘴啊,大兄弟
从Spring-Session源码看Session机制的实现细节

去年我曾经写过几篇和 Spring Session 相关的文章,从一个未接触过 Spring Session 的初学者视角介绍了 Spring Session 如何上手,如果你未接触过 Spring Session,推荐先阅读下「从零开始学...

徐靖峰
04/20
0
0
Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密...

小致dad
08/03
0
0
Spring中使用getSession()与通过HibernateTemplate进行数据操作...

在 Spring+Hibernate的集成环境里,如果DAO直接使用HibernateDaoSupport的getSession()方法获取 session进行数据操作而没有显式地关闭该session,那么程序表现为:每个session会打开一个con...

小样
2012/08/02
0
1
eclipse下搭建SSH整合环境(Struts2+Spring+Hibernate+maven)

1,创建一个maven工程,在选择Archetype时选择webapp: 2,下一步配置maven的pom.xml文件,获取依赖的jar包: <!-- struts2核心包 --><dependency> </dependency> <!-- struts2与spring整合的......

徐航
2014/05/08
0
5
spring事务管理错误createSQLQuery is not valid without active transaction

网上扒的,很管用,自己就借此发一下,方便以后看。。。。。。。 原文网址http://blog.csdn.net/yinjian520/article/details/8666695 很多时候我们使用hibernate的session时,都是让session...

技术小牛
2014/04/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

升压变换器 Boost

工作特点 输入输出极性相同。 开关管 MOS 和负载构成并联,在MOS 导通时,电流通过 L 滤波,电源对 L 充电。 当 MOS 断开时,L 向负载及电源放电,输出电压将是 Ui+U L ,达到升压的目的。 ...

colinux
27分钟前
1
0
OSChina 周一乱弹 —— 你狗命在我手上

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 小小编辑:推荐歌曲,《I.W.A.B.N》- Lil Ghost 《I.W.A.B.N》- Lil Ghost 手机党少年们想听歌,请使劲儿戳(这里) 几天没见, 大王(@罗马的...

小小编辑
28分钟前
169
6
轻量级 memcached缓存代理 twemproxy实践

本文内容脑图如下: 文章共 533字,阅读大约需要 2分钟 ! 概 述 twemproxy(nutcracker) 是 Twitter开源的轻量级 memcached / redis 代理服务器,本质就是一个集群管理工具,主要用来弥补 ...

CodeSheep
48分钟前
7
0
Apache日志不记录访问静态文件,访问日志切割,静态元素过期时间设置

Apache配置不记录访问静态文件的日志 网站大多元素为静态文件,如图片、css、js等,这些元素可以不用记录 vhost原始配置 <VirtualHost *:80> ServerAdmin test@163.com DocumentRoo...

野雪球
今天
3
0
聊聊storm的ICommitterTridentSpout

序 本文主要研究一下storm的ICommitterTridentSpout ICommitterTridentSpout storm-core-1.2.2-sources.jar!/org/apache/storm/trident/spout/ICommitterTridentSpout.java public interface......

go4it
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部