ASP.NET Core 中 Session 的使用

会话(Session)

HTTP是一种采用请求/响应消息交换模式且无状态的传输协议。HTTP协议旨在确保客户端将请求报文发送给目标服务器,并成功接收来自服务端的响应报文,这个基本的报文交换被称为一个HTTP事务(Transaction)。从协议角度来讲,即便在使用长连接的情况下,同一个客户端和服务器之间进行的多个HTTP事务也是完全独立的,所以需要在应用层,为二者建立一个上下文(类似于聊天记录)来保存多次消息交换的状态(即数据),我们将其称为会话(Session)。

  • 会话的目的就是在同一个客户端和服务器之间建立两者交谈的语境或者上下文(Context)。//就是保存一些历史数据的手段。
  • 会话使用 Cookie 跟踪和标识来自单个浏览器的请求。
  • 会话是有有效期的。

SessionMiddleware

ASP.NET Core 利用一个名为 SessionMiddleware 的中间件实现了会话。默认使用分布式缓存来存储会话状态,且默认采用的是基于滑动时间的过期策略,默认采用的滑动过期时间是20分钟,20分钟内的任意一次请求都会将会话的寿命延长至20分钟以后。

若要启用会话中间件,Startup 中需要:

疑问 ??

Startup 中不配置分布式缓存,session 也能正常使用,可以正常存取数据。那么这个数据是放到哪儿了?内存中?ASP.NET Core分布式缓存支持Redis和Sql Server两种,但我都没配置,可是上面提到这个session默认使用分布式缓存呀。

Session key 和 Session ID

每个会话都有一个被称为 Session key 的标识(但不是唯一标识),会话状态以一个数字字典的形式将 Session Key 保存在服务端。当 SessionMiddleware 中间件在处理会话的第一个请求时(请求没有以Cookie的形式携带Session Key),它会创建一个 Session Key ,并基于它创建一个独立的数据字典来存储会话状态,应用程序设置的会话状态总是自动保存在当前会话对应的数据字典中。这个 Session Key 最终会以 Cookie 的形式写入响应并返回客户端,客户端之后在每次发送请求时都会自动附加这个Cookie,从而使应用程序能够准确的定位当前会话对应的数据字典。

SessionKey写入客户端时,不仅会加密,还会对Cookie设置 httponly 标签。

如果HTTP响应标头中包含HttpOnly标志(可选),客户端脚本将无法访问cookie(如果浏览器支持该标志的话)。因此即使客户端存在跨站点脚本(XSS)漏洞,浏览器也不会将Cookie透露给第三方。

会话状态是基于作为会话标识的 Session key 进行存储的,直到目前为止,我们不能使用公布出来的 API 来获取它,但可以利用反射的方式来获取 Session key 。

当会话状态在采用默认的分布式缓存进行存储时,整个数据字典(包括 key和value)会采用预定义的格式序列化成字节数组。

Session ID 可以作为会话的唯一标识,但 Session key 不可以,原因如下:

当 SessionMiddleware 中间件在处理会话的第一个请求时,它会创建两个不同的GUID来分别表示 Session key 和 Session ID 。会话是具有有效期的,当会话过期的时候,服务端存储的会话状态数据(包括SessionID)会被清除,但是请求携带的可能还是原来的Session Key。在这种情况下,SessionMiddleware 中间件会创建一个新的会话,该会话具有不同的 Session ID ,但是整个会话状态依然沿用这个 Session Key,所以 Session Key 不能唯一标识一个会话。

默认情况下,表示Session的是一个 DistributedSession 对象。他有一个是有字段:_sessionKey .

ISession 和 DistributedSession

应用程序会使用 ISession 对象来读写会话状态(数据),这个对象来源于当前 HttpContext 上下文的 Session 属性。

我们设置和提取的缓存状态的值体现为字节数组,所以应用程序需要自行完成序列化和反序列化的工作。针对某个会话状态的设置、提取、移除和清除都是在内存中进行的。我们会在操作缓存状态之前调用 ISession 对象的 LoadAsync 方法以异步的方式将所有的会话状态加载到内存中,这是一种推荐的做法。

ISession的方法:Set、TryGetValue、Remove、Clear

ISession 的扩展方法中:

  • Get 方法在指定的会话状态项不存在,即没有指定的key,则会直接返回null
  • GetString 方法和 SetString 方法会采用 UTF-8 对字符串进行编码和解码

DistributedSession 类型就是针对 ISession 接口的默认实现。它利用 IDistributedCache 对象表示的分布式缓存来存储会话状态。

注意:会话过期时间依据缓存项的滑动过期时间。

ISessionStore 和 DistributedSessionStore

ISessionStore 接口表示创建 ISession 对象的工厂。DistributedSessionStore 是对 ISessionStore 的默认实现,他创建的是一个 DistributedSession 对象。

SessionOptions

SessionOptions 是 SessionMiddleware 中间件对应的配置选项类型。

在请求处理过程中,利用注册的 ISessionStore 对象了创建表示会话的 ISession 对象是由 SessionMiddleware 中间件来完成的。

CookieBuilder 与 SessionCookieBuilder,后者继承自前者。

SessionOptions 承载的核心配置选项是 Cookie 属性表示的 CookieBuilder对象,实际上返回的是一个 SessionCookieBuilder 对象。

SessionOptions

Cookie属性

Cookie 常识

服务端可以通过Set-Cookie 响应报头,在浏览器中加入新的cookie属性和值,以便之后客户端每次请求都携带上他们。

客户端(通常指浏览器)请求时,会通过Cookie请求头, 携带cookie信息。每次请求都会携带,而且可以自定义属性和值。

固有的Cookie属性和值

  • SameSite
  • httponly
  • IsEssential:值为true或false,表示为了实现会话支持,针对Cookie的设置是否需要得到最终用户的显示授权,默认false。

IdealTimeout

客户端最后一次访问时间到会话过期之间的时长,默认20分钟。

注意:如果想设置更长的时间,且部署在iis上,保险起见,那么iis的站点属性【IdealTimeout】即闲置超时,要设置的不低于该时长。


参考:

  • 《ASP.NET Core 6 框架揭秘》 //P813~814,两页代码片段,模拟了 SessionMiddleware 针对Session的实现,可以有空在好好品味一下。

  • Artech - 博客园 (cnblogs.com)


更新于:2023-05-08

posted @   AI大胜  阅读(557)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示