什么是Session
http是无状态的,就是每个请求都是独立的,上一个请求是用户登录,本来用户已经登录了,下一个请求显示登录后的主页,由于http无状态,显示主页这个请求根本不知道用户登录了。
Session就可以用来记录登录这种状态,在用户登录的时候,就给这个用户创建一个session,这个session里面保存一些自定义配置,用户信息等。Session是存在于服务器的内存中,当然可以存在文件,或者数据库里面,创建的时候还可以设置session的过期时间。到期了session就被销毁了。
Session存放位置
Session一般创建的时候是存在服务的内存中,到期自动销毁。
但是有个弊端。
用户多了,创建大量的Session,内存???
所以有了Session持久化一说,把Session存在文件里面。或者数据库里面。随便存,当我硬盘和内存一样小啊。
但是吧,如果要频繁访问Session,你频繁的读取文件或者数据库,也不太合适吧,而且过期了不能自动删除。
但是想要删除保存在文件或者数据库中的session也不是不可以,它不能自行判断过期时间自动删除,比如,你可以在用户登录的时候创建这个用户的session,然后进行遍历所有的文件或者数据库里面的session。过期的删掉。
性能不佳啊,曲线救国嘛。
怎么匹配Session是那个用户的
在创建session时,会创建一个sessionid,这个sessionid放在cookie里面。随着响应头,把这个cookie一起发给客户端。响应成功后,这个客户端的浏览器就收到了这个cookie。之后每次发送请求,都会自动加上这个cookie一起发给后端。
如果要查询session里面的值,会自动匹配这个请求头里面的cookie里面的sessionid,匹配到了,就给相应的session。
没有sessionid匹配?哪怕服务器内存中的session没有过期?
服务器:对不起没有sessionid,我不认!
使用
打开项目的依赖项,看框架,只有AspNetCore.App才能使用这个session,cookie 单独创建的类库,依赖项的框架里面只有 NetCore.App,不能像下面这样使用session,cookie 需要在类库里面安装两个包, AspNetCore.Http和AspNetCore.Session
先注册服务
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
//设置过期时间,单位秒,也可以设置分钟
//指的是在这个时间内,对session没有任何操作(包括查询设置),session就自动过期了
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.HttpOnly = true;是否可以通过客户端脚本访问cookie
});
//用这个来操作cookie,session
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
然后使用中间件,注意使用顺序,在路由后面,
app.UseRouting();
//配置Cors
app.UseCors("a");
app.UseAuthorization();
app.UseSession();//使用Session中间件
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
然后在控制器的构造方法中注入服务
private Users user;
private Blog6Context db;
private IHttpContextAccessor accessor;
private ISession session;
public UsersController(Users u,Blog6Context b, IHttpContextAccessor h)
{
user = u;
db = b;
accessor = h;
session = h.HttpContext.Session;
}
最后就可以使用session了
session.SetString("qq", "123456");//设置session
指向同一个session
前端axios发送请求时,只要涉及到session,发送的请求都要设置withCredentials: true
this.$http({
method:"post",
url:this.url+"/api/users/login",
data:user,
withCredentials: true
})
SessionHelper
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BookApi.CookieSession
{
/// <summary>
/// Session操作类
/// </summary>
public class SessionHelper
{
private readonly IHttpContextAccessor httpContextAccessor_;
public SessionHelper(IHttpContextAccessor httpContextAccessor)
{
httpContextAccessor_ = httpContextAccessor;
}
/// <summary>
/// 新增复杂型session
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
public void SetObject<T>(string key, T value)
{
httpContextAccessor_.HttpContext.Session.SetString(key, JsonConvert.SerializeObject(value));
}
/// <summary>
/// 获取复杂型session
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public T GetObject<T>(string key)
{
var value = httpContextAccessor_.HttpContext.Session.GetString(key);
return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
}
/// <summary>
/// 添加Session
/// </summary>
/// <param name="strSessionName">Session键</param>
/// <param name="strValue">Session值</param>
public void Add(string strSessionName, string strValue)
{
httpContextAccessor_.HttpContext.Session.SetString(strSessionName, strValue);
}
/// <summary>
/// 读取某个Session对象值
/// </summary>
/// <param name="strSessionName">Session键</param>
/// <returns>Session对象值</returns>
public object Get(string strSessionName)
{
if (httpContextAccessor_.HttpContext.Session == null
|| httpContextAccessor_.HttpContext.Session.GetString(strSessionName) == null)
{
return null;
}
else
{
return httpContextAccessor_.HttpContext.Session.GetString(strSessionName);
}
}
/// <summary>
/// 修改Session
/// </summary>
/// <param name="strSessionName"></param>
/// <param name="objVal"></param>
public void Update(string strSessionName, string objVal)
{
object obj = Get(strSessionName);
if (obj != null)
{
Del(strSessionName);
}
Add(strSessionName, objVal);
}
/// <summary>
/// 删除某个Session对象
/// </summary>
/// <param name="strSessionName">Session对象名称</param>
public void Del(string strSessionName)
{
httpContextAccessor_.HttpContext.Session.Remove(strSessionName);
}
}
}