- 概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession
一次会话代表一次打开浏览器, 比如说一次打开浏览器,然后第一次访问的时候,往Httpsession中,加数据;第二次访问的时候,读取Httpsession数据 -
- 快速入门:
- 获取HttpSession对象:
HttpSession session = request.getSession(); - 使用HttpSession对象:
Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)
测试:
在创建一个用来读取数据:
重新启动:发现报错,查看发现路径错误,故在路径上加入/
启动成功,先访问http://localhost/day18_session_war_exploded/session01;
再访问:
http://localhost/day18_session_war_exploded/session02
结果如下:
测试成功
当浏览器关闭之后再打开就为空了。
- 原理
Session的实现是依赖于Cookie的。
测试如下:
第一次访问/session01,发现请求头中没有JSESSIONID而响应头中有;
当访问/session02的时候,发现请求头中Cookie有了这个JSESSIONID了。此时,如果要取session数据的话,就会先去内存中找是不是有这个JSESSIONID,有的话就用它了。 - 细节:
- 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
默认情况下。不是。
如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。
此时,在一个小时内,不管浏览器关不关获取的session都是同一个。
2.客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
服务器关闭了,内存释放,则在内存中的session对象就销毁了,第二次创建很难一样,一样也是巧合,内容也不一样。所以不是同一个。
针对这个现象会发生一些问题,比如说,我去淘宝买东西,我把很多东西添加到购物车上,这些数据是存在session中的,这时候,突然淘宝服务器重启了,这时候,session中数据就会丢失,用户就不能购买了。所以,要解决好这个问题。所以,虽然,服务器关闭的时候,第二次访问的session不是同一个,但是要确保数据不能丢失。
session的钝化:在服务器正常关闭之前,将session对象系列化到硬盘上
session的活化:在服务器启动后,将session文件转化为内存中的session对象即可。
钝化和活化,tomcat已经帮我们做了,在idea上不能演示,只能在tomcat上进行。
测试:
我们先在本地上找到当前项目并复制该项目:路径如下:
这里是idea部署的,在out找到当前项目,复制一份到桌面上
将里面东西打包:
进行改名:
再把该war包放tomcat上
启动tomcat
发现端口占用:
查看被占用的端口号:netstat -ano | findstr 8080
taskkill /pid 5852 /f
但是这里怎么改还是报端口占用错,故我改了一下端口号为8083
先访问http://localhost:8083/day18/session02 输出为null
再访问http://localhost:8083/day18/session01;设置内容
再访问http://localhost:8083/day18/session02;结果如下:
此时,我把服务器关闭:再启动;访问http://localhost:8083/day18/session02;结果如下:
所以,可以发现钝化和活化tomcat都给我们做了,其实原因如下:
当正常关闭服务器的时候,在work下面会生成如下内容:
当重新启动的时候,这个东西会还原,删除。
而idea为什么不行,其实当idea关闭的时候,这个文件是生成的,但是,当它启动的时候,work目录会删除,所以,里面的这个文件也就没有了。
- 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
Spring Security OAuth2.0认证授权
认证:当我们用户进行登录的时候,就是认证,用户输入账户和密码来进行校验就是一个认证的过程;
授权:系统要校验你有没有使用某些资源的权限;
OAuth2.0:满足系统第三方应用认证的一个公开的协议;主要应用于分布式系统认证授权;
什么是会话
用户认证通过后,为了避免用户每次操作都进行认证可将用户的信息保存在会话中,会话就是系统 为了保证当前用户的登录状态所提供的机制,常见的有基于session方式、基于token方式等。
1.基于session的认证方式如下:
它的交互流程是,用户认证成功后,在服务端生成用户相关的数据保存在session中,发给客户端的session_id存放到cookie中,这样用户客户端请求时带上session_id就可以验证服务器端是否存在session数据,以此完成用户的合法校验,当用户退出系统或session过期销毁时,客户端的session_id也就无效了;
2.基于token的认证方式如下:
它的交互流程是,用户认证成功后,服务端生成一个token发给客户端,客户端可以 放到cookie或(不支持cookie的话,就存储到支持存储的存储介质中)localStorage等存储中,每次请求时带上token,服务器收到token通过验证后即可确认用户身份。
基于session的认证方式是由Servlet规范定制,服务端要存储session信息需要占用内存资源,客户端需要支持cookie;基于token的方式则一般不需要服务端存储token,并且不限制客户端的存储方式。现在,系统多采用前后端分离的架构进行实现,所以基于token的方式更适合;
什么是授权:
当需要访问一些资源时,要查看该用户有没有相应的权限,这个根据用户的权限来控制用户使用资源的过程就是授权;
所以:认证是为了保护用户身份的合法性,授权则是为了更细粒度的对隐私数据进行划分;就我自己的项目来说:认证就是看这个用户是不是我的用户,授权就是看我的这个用户是不是有相应的权限;
用户认证通过后,根据用户的权限来控制用户访问资源的过程,拥有资源的访问权限则正常访问,没有权限则拒绝访问。
访问方式
访问方式 有基于角色的访问方式 和基于资源的访问方式;
基于角色的访问控制:也是我项目中使用的,比如说总经理,那就可以看所有流水线的信息
部门经理,只能看它自己管理的流水线信息,而普通用户就什么都看不到;
基于角色的访问方式:可扩展性比较差,比如说,我想让普通用户也要看信息就得更改代码,但是,由于,我这个项目比较简单,所以,在我这个项目中也可以进行使用;
基于资源的访问控制: 判断用户有没有这个权限,来进行操作;这时候,就可以通过给该用户设置权限来解决这些问题,效果较好,可扩展性强; 一般是推荐资源的访问控制,反正到时候也可以改的;
Spring Security 定义了拦截功能,不需要定义拦截器了;
安全认证流程
服务端生成一个HttpSession都会有一个对应的sessionId,这个sessionid会通过cookie传递给前端,前端以后发送请求的时候,就带上这个sessionid参数,服务器看到这个sessionid就会把这个前端请求和服务器的某一个HttpSession对应起来,形成会话的感觉
浏览器关闭并不会导致服务器的HttpSession失效,想让服务端的HttpSession失效,要么调用方法,要么等待session自动过期,要么重启服务器;
但是为什么有人感觉浏览器关闭之后,session就失效了呢?这是因为浏览器关闭以后,(默认情况下)保存在浏览器里面的sessionid就丢了。所以,当浏览器再次访问服务器的时候,服务器就会重新给浏览器重新分配一个sessionid,这个sessionid和之前的HttpSession对应不上,所以,用户就需要重新登登陆,用户就会感觉session失效了;
以Spring boot为例,服务端生成sessionid之后,返回给前端的响应头是这样的:
服务器中,会有一个Set-Cookie字段,该字段指示浏览器更新sessionid,这里还有一个HttpOnly属性,通过这个属性表示JS脚本无法读取到Cookie信息,防止XSS攻击;当下一次浏览器再去发送请求的时候,就会自觉的携带上这个sessionid了;(但是,厂联网好像是使用token来实现的)
会话固定攻击
正常来说,如果这个sessionid不发生变化,那么如果获取到这个sessionid就可以进行攻击
流程如下:
1.攻击者自己访问淘宝网站,然后,淘宝网给攻击者分配了一个sessionid;
2.攻击者利用自己拿到的sessionid构造一个淘宝网站的链接,并把该链接发送给受害者
3.受害者使用该链接登录淘宝网站(含有的sessionid是攻击者的id),登录成功后,一个合法的会话就建立了;
4.攻击者利用手里的sessionid 冒充受害者
URL重写: 用户如果在浏览器中禁用了cookie,那么sessionid就用不了了,所以,就需要把sessionid放在请求地址上;
http://www.taobao.com;jsessionid=xxxxx
如何防御
这个问题产生的原因是未登录时和登录成功时,sessionid都是同一个;如果用户在未登录时,拿到的是一个sessionid,登录之后服务器重新给用户生成一个sessionid,就可以防止会话固定攻击了;
Spring Security中防御主要体现在三个方面:
1.Set-Cookie字段中有HttpOnly属性,避免通过XSS攻击来获取Cookie中会话信息
2.请求地址中有;会被直接拒绝;
3.默认情况下,当登陆成功后,会创建一个新的会话;
默认情况下,是使用session 来保持会话的,为此,我特意让我自己的项目禁用所有的cookie,发现果然报错了;所以,针对我当前项目,想要改变这个问题,需要将会话技术改成token 不过我这个是微信公众号,使用的微信浏览器就不需要进行改变了;