(转)从零开始的Spring Session(一)
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打印出来。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@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也是不同的。另外可以尝试把保存session的操作注视掉,则可以发现Response中就不会返回JSESSIONID了,即这是一次无状态的请求。
安全问题
其实上述的知识点,都是非常浅显的,之所以啰嗦一句,是为了引出这一节的内容,以及方便观察后续我们引入Spring Session之后的发生的变化。
还记得上一节的代码示例中,我们使用了两个浏览器:
- chrome浏览器访问时,JSESSIONID为4CD1D96E04FC390EA6C60E8C40A636AF,后端session记录的值为:browser=chrome。
- 360浏览器访问时,JSESSIONID为320C21A645A160C4843D076204DA2F40,后端session记录的值为:browser=360。
我们使用chrome插件Edit this Cookie,将chrome浏览器中的JSESSIONID修改为360浏览器中的值
EditThisCookie
同样访问原来的端点:localhost:8080/test/cookie?browser=chrome,得到的输出如下:
1
2
|
存在session,browser=360
JSESSIONID : 320C21A645A160C4843D076204DA2F40
|
证实了一点,存放在客户端的Cookie的确是存在安全问题的,我们使用360的JSESSIONID“骗”过了服务器。毕竟,服务器只能通过Cookie中的JSESSIONID来辨别身份。(这提示我们不要在公共场合保存Cookie信息,现在的浏览器在保存Cookie时通常会让你确定一次)
下一篇文章,将正式讲解如何在应用中集成Spring Session。
(转)从零开始的Spring Session(一)的更多相关文章
- Re:从零开始的Spring Session(三)
上一篇文章中,我们使用Redis集成了Spring Session.大多数的配置都是Spring Boot帮我们自动配置的,这一节我们介绍一点Spring Session较为高级的特性. 集成Spri ...
- Re:从零开始的Spring Session(二)
上一篇文章介绍了一些Session和Cookie的基础知识,这篇文章开始正式介绍Spring Session是如何对传统的Session进行改造的.官网这么介绍Spring Session: Spri ...
- Re:从零开始的Spring Session(一)
Session和Cookie这两个概念,在学习java web开发之初,大多数人就已经接触过了.最近在研究跨域单点登录的实现时,发现对于Session和Cookie的了解,并不是很深入,所以打算写两篇 ...
- 从零开始的Spring Session(一)
Session和Cookie这两个概念,在学习java web开发之初,大多数人就已经接触过了.最近在研究跨域单点登录的实现时,发现对于Session和Cookie的了解,并不是很深入,所以打算写两篇 ...
- (38)Spring Boot分布式Session状态保存Redis【从零开始学Spring Boot】
[本文章是否对你有用以及是否有好的建议,请留言] 在使用spring boot做负载均衡的时候,多个app之间的session要保持一致,这样负载到不同的app时候,在一个app登录之后,而访问到另外 ...
- 57. Spring 自定义properties升级篇【从零开始学Spring Boot】
之前在两篇文章中都有简单介绍或者提到过 自定义属性的用法: 25.Spring Boot使用自定义的properties[从零开始学Spring Boot] 51. spring boot属性文件之多 ...
- 17、Spring Boot普通类调用bean【从零开始学Spring Boot】
转载:http://blog.csdn.net/linxingliang/article/details/52013017 我们知道如果我们要在一个类使用spring提供的bean对象,我们需要把这个 ...
- 21. Spring Boot过滤器、监听器【从零开始学Spring Boot】
转载:http://blog.csdn.net/linxingliang/article/details/52069490 上一篇文章已经对定义Servlet 的方法进行了说明,过滤器(Filter) ...
- 81. Spring Boot集成JSP疑问【从零开始学Spring Boot】
[原创文章,转载请注明出处] 针对文章: ()Spring Boot 添加JSP支持[从零开始学Spring Boot] 有网友提了这么一些疑问: 1.Spring Boot使用jsp时,仍旧可以打成 ...
随机推荐
- spy-debugger 前端调试工具
一站式页面调试.抓包工具.远程调试任何手机浏览器页面,任何手机移动端webview(如:微信,HybirdApp等).支持HTTP/HTTPS,无需USB连接设备. Language: Engl ...
- YAML语法介绍
官网YAML: http://yaml.org/ http://yaml.org/xml 参考链接: http://www.ruanyifeng.com/blog/2016/07/yaml.html? ...
- (转载)解决AndroidStudio导入项目在 Building gradle project info 一直卡住
源地址http://blog.csdn.net/yyh352091626/article/details/51490976 Android Studio导入项目的时候,一直卡在Building gra ...
- Centos 升级 python
昨天把redmine的测试环境给搞Over了,想了下,干脆直接把环境给整成docker化的,配置环境的时候,安装docker-compose需要python2.7支持. CentOS 6 系统默认 P ...
- DXP 内电层分割
多层电路板中间层设置与内电层如何分割 多层电路板与一般的电路板不同之处在于,多层电路板除了顶层和底层之外,还有若干中间层,这些中间层可以是信号层(mid layer),也可以是内部电源/接地层(int ...
- msyql DATETIME类型和Timestamp之间的转换
DATETIME -> Timestamp: UNIX_TIMESTAMP(...) Timestamp -> DATETIME: FROM_UNIXTIME(...) select da ...
- MatLab Load cv::Mat 导入数据
我们有时候在项目中需要将OpenCV中的cv::Mat导入MatLab进行分析与处理,那么如果把数据转过去呢,我们的做法是首先将cv::Mat导出为txt文件,或者是yml文件,请参见我之前的博客Wr ...
- HOJ 2091 Chess(三维简单DP)
Chess My Tags (Edit) Source : Univ. of Alberta Local Contest 1999.10.16 Time limit : 1 sec Memory li ...
- Alice, Bob, Oranges and Apples CodeForces - 586E
E - Alice, Bob, Oranges and Apples CodeForces - 586E 自己想的时候模拟了一下各个结果 感觉是不是会跟橘子苹果之间的比例有什么关系 搜题解的时候发现了 ...
- 基础知识系列☞C#中→委托
有些.NET中的高级特性,比如:委托! 有一种怎么也搞不懂的赶脚... 博客读了好几篇,代码也动手写了,书中的一些介绍也看了, 各种搜索关于委托的,至今还处于"会用"的阶段. 该怎 ...