.NET Core Session源码探究 (3)

那么问题来了当前类里并没有地方调用CommitAsync,那么到底是在什么地方调用的该方法呢?姑且别着急,我们之前说过使用Session的三要素,现在才说了两个,还有一个UseSession的中间件没有提及到呢。

UseSession中间件

通过上面注册的相关方法我们大概了解到了Session的工作原理。接下来我们查看UseSession中间件里的代码,探究这里究竟做了什么操作。我们找到UseSession方法所在的地方SessionMiddlewareExtensions找到第一个方法

public static IApplicationBuilder UseSession(this IApplicationBuilder app) { if (app == null) { throw new ArgumentNullException(nameof(app)); } return app.UseMiddleware<SessionMiddleware>(); }

SessionMiddleware的源码

public class SessionMiddleware { private static readonly RandomNumberGenerator CryptoRandom = RandomNumberGenerator.Create(); private const int SessionKeyLength = 36; // "382c74c3-721d-4f34-80e5-57657b6cbc27" private static readonly Func<bool> ReturnTrue = () => true; private readonly RequestDelegate _next; private readonly SessionOptions _options; private readonly ILogger _logger; private readonly ISessionStore _sessionStore; private readonly IDataProtector _dataProtector; public SessionMiddleware( RequestDelegate next, ILoggerFactory loggerFactory, IDataProtectionProvider dataProtectionProvider, ISessionStore sessionStore, IOptions<SessionOptions> options) { if (next == null) { throw new ArgumentNullException(nameof(next)); } if (loggerFactory == null) { throw new ArgumentNullException(nameof(loggerFactory)); } if (dataProtectionProvider == null) { throw new ArgumentNullException(nameof(dataProtectionProvider)); } if (sessionStore == null) { throw new ArgumentNullException(nameof(sessionStore)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } _next = next; _logger = loggerFactory.CreateLogger<SessionMiddleware>(); _dataProtector = dataProtectionProvider.CreateProtector(nameof(SessionMiddleware)); _options = options.Value; //Session操作类在这里被注入的 _sessionStore = sessionStore; } public async Task Invoke(HttpContext context) { var isNewSessionKey = false; Func<bool> tryEstablishSession = ReturnTrue; var cookieValue = context.Request.Cookies[_options.Cookie.Name]; var sessionKey = CookieProtection.Unprotect(_dataProtector, cookieValue, _logger); //会话首次建立 if (string.IsNullOrWhiteSpace(sessionKey) || sessionKey.Length != SessionKeyLength) { //将会话唯一标识通过Cookie返回到客户端 var guidBytes = new byte[16]; CryptoRandom.GetBytes(guidBytes); sessionKey = new Guid(guidBytes).ToString(); cookieValue = CookieProtection.Protect(_dataProtector, sessionKey); var establisher = new SessionEstablisher(context, cookieValue, _options); tryEstablishSession = establisher.TryEstablishSession; isNewSessionKey = true; } var feature = new SessionFeature(); //创建Session feature.Session = _sessionStore.Create(sessionKey, _options.IdleTimeout, _options.IOTimeout, tryEstablishSession, isNewSessionKey); //放入到ISessionFeature,给HttpContext中的Session数据提供具体实例 context.Features.Set<ISessionFeature>(feature); try { await _next(context); } finally { //置空为了在请求结束后可以回收掉Session context.Features.Set<ISessionFeature>(null); if (feature.Session != null) { try { //请求完成后提交保存Session字典里的数据到DistributedCache存储里 await feature.Session.CommitAsync(); } catch (OperationCanceledException) { _logger.SessionCommitCanceled(); } catch (Exception ex) { _logger.ErrorClosingTheSession(ex); } } } } private class SessionEstablisher { private readonly HttpContext _context; private readonly string _cookieValue; private readonly SessionOptions _options; private bool _shouldEstablishSession; public SessionEstablisher(HttpContext context, string cookieValue, SessionOptions options) { _context = context; _cookieValue = cookieValue; _options = options; context.Response.OnStarting(OnStartingCallback, state: this); } private static Task OnStartingCallback(object state) { var establisher = (SessionEstablisher)state; if (establisher._shouldEstablishSession) { establisher.SetCookie(); } return Task.FromResult(0); } private void SetCookie() { //会话标识写入到Cookie操作 var cookieOptions = _options.Cookie.Build(_context); var response = _context.Response; response.Cookies.Append(_options.Cookie.Name, _cookieValue, cookieOptions); var responseHeaders = response.Headers; responseHeaders[HeaderNames.CacheControl] = "no-cache"; responseHeaders[HeaderNames.Pragma] = "no-cache"; responseHeaders[HeaderNames.Expires] = "-1"; } internal bool TryEstablishSession() { return (_shouldEstablishSession |= !_context.Response.HasStarted); } } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsxzpp.html