文档章节

从零开始的Spring Session(一)

二十岁以后
 二十岁以后
发布于 2017/09/12 10:41
字数 1522
阅读 72
收藏 1
点赞 0
评论 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)

 

完美解决!!!

 

本文转载自:

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

评论(1)

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

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

徐靖峰
04/20
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
次世代的会话管理项目 Spring Session

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文来自云+社区翻译社,由Tnecesoc编译。 会话管理一直是 Java 企业级应用的重要部分。不过在很长的一段时间里,这一部分都被我...

腾讯云加社区
06/26
0
0
Hibernate4 No Session found for current thread原因

Hibernate4 与 spring3 集成之后, 如果在取得session 的地方使用了getCurrentSession, 可能会报一个错:“No Session found for current thread”, 这个错误的原因,网上有很多解决办法, 但...

poxiao001
2015/01/04
0
0
springmvc-session+redis控制

springmvc-session+redis控制 一、maven导入需要的jar包 <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>je......

上海滩
2017/10/30
0
0
DNS服务器BlackHole开发日记-起源及一点心得

起因 最近公司在做一个邮件系统的项目,涉及到测试对外发送的环节。开始构思是这样:建立一个接收服务器,并将所有请求导向该服务器。这里面就涉及到一个DNS拦截的问题。这个问题其实在开发和...

黄亿华
2012/12/19
0
7
spring-boot整合spring-session,使用redis共享

本文讲述spring-boot工程中使用spring-session机制进行安全认证,并且通过redis存储session,满足集群部署、分布式系统的session共享。 java工程中,说到权限管理和安全认证,我们首先想到的...

louieSun
05/13
0
0
apache+tomcat负载均衡中springmvc项目session遇到的问题

apache+tomcat集群的负载均衡,按照网上的教程,集群的负载均衡我用的是mod_jk的模式,在同一部机器下配置成功,我用了简单的例子去跑可以实现session的复制和session内容的共享,测试截图一如...

tuzibuluo
2015/03/16
1K
3

没有更多内容

加载失败,请刷新页面

加载更多

下一页

10.28 rsync工具介绍 , rsync常用选项, rsync通过ssh同步

rsync远程同步 重点!重点!!重点!!! 例子 • rsync -av /etc/passwd /tmp/1.txt • rsync -av /tmp/1.txt 192.168.188.128:/tmp/2.txt rsync格式 • rsync [OPTION] … SRC DEST • rs......

Linux_老吴
16分钟前
0
0
iis php 环境搭建,非常详细的教程

准备篇 一、环境说明: 操作系统:Windows Server 2016 PHP版本:php 7.1.0 MySQL版本:MySQL 5.7.17.0 二、相关软件下载: 1、PHP下载地址: http://windows.php.net/downloads/releases/ph...

T_star
18分钟前
0
0
Day35 rsync通过服务同步

rsync通过服务同步 rsyncd.conf配置文件详解 port:指定在哪个端口启动rsyncd服务,默认是873端口。 log file:指定日志文件。 pid file:指定pid文件,这个文件的作用涉及服务的启动、停止等...

杉下
24分钟前
1
0
【最新最全】为 iOS 和 Android 的真机和模拟器编译 Luajit 库

编译 Luajit 库,的确是一个挑战。因为官网的教程,在当前版本的 Xcode 和 NDK 环境中,已经不适用了。以前只是编译了适用于真机的 Luajit 库。最近在尝试编译模拟器 Luajit 库,就顺便梳理了...

ios122
24分钟前
0
0
rsync至ssh同步

rsync: 文件同步工具,可实现“增量拷贝”;使用yum安装rsync包 常用选项:-a=-rtplgoD (-r同步目录,-t保持文件的时间属性,-p保持文件的权限属性,-l保持软连接,-g保持文件的属组,-o保持...

ZHENG-JY
30分钟前
0
0
TradingView 学习笔记

#前言 公司最后需要使用TradingView展示K线图走势。由于之前没接触过,拿到文档时一脸蒙逼。还好找到二篇文章+Demo代码,直接改改就行了。 #被批 由于上面的懵懂,有个问题困扰4个小时没解决...

hihubs
30分钟前
0
0
10.28 rsync工具介绍~10.31 rsync通过ssh同步

rsync命令是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件。rsync使用所谓的“rsync算法”来使本地和远程两个主机之间的文件达到同步,这个算法只传送两个文件的不同部分,而...

洗香香
32分钟前
1
0
php如何使用JSON-RPC查找以太坊中的最新块哈希hash值?

我用PHP中开发了一个以太坊块资源管理器,并成功地与我的服务器Geth节点建立了JSON-RPC通信。然而,当我试图找出最后一个区块时,我陷入了困境。我在https://ethereum.gitbooks.io/frontier...

智能合约
38分钟前
1
0
卷积为什么要旋转180度

参考《最容易理解的对卷积(convolution)的解释》 https://blog.csdn.net/bitcarmanlee/article/details/54729807 这篇博客详细讲解了“卷积”,提及了为什么要反转180度,我简述下。 1.卷积的...

datadev_sh
41分钟前
0
0
【2018.07.18学习笔记】【linux高级知识 20.23-20.26】

20.23/20.24/20.25 告警系统邮件引擎 告警系统邮件引擎由两个文件组成,放在/mon/mail/目录下:mail.py、mail.sh mail.py:是邮件的核心python脚本,邮件功能的实现mail.sh:是告警邮件系统...

lgsxp
46分钟前
17
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部