造成这个的问题的原因是每个机器上面的ASP.NET Core的应用程序的密钥是不一样的,所以没有办法得到前一个应用程序保存的Session数据;为了解决这个问题,.NET Core团队为提供了Microsoft.AspNetCore.DataProtection.AzureStorage和Microsoft.AspNetCore.DataProtection.Redis包将密钥保存到Azure或Redis中。这里选择将密钥保存到Redis。
利用Microsoft.AspNetCore.DataProtection.Redis包提供的PersistKeysToRedis重载方法将密钥保存到Redis里面去。所以这里需要在ConfigureServices方法中添AddDataProtection()
var redis = ConnectionMultiplexer.Connect("127.0.0.1:6379"); services.AddDataProtection() .SetApplicationName("session_application_name") .PersistKeysToRedis(redis, "DataProtection-Keys");
下面演示怎样实现分布式Session
配置步骤
同时创建两个项目,分别为app1和app2
添加Microsoft.AspNetCore.DataProtection.Redis和StackExchange.Redis.StrongName包
由于在同一台机器上,ASP.NET Core程序默认启动的时候端口为5000,由于app1已经占用了,所以将app2的启端口设置为5001
完整代码
app1项目
Startup.cs
using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Caching.Redis; using Microsoft.Extensions.Caching.Distributed; namespace app1{ public class Startup{ public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services){ var redis = ConnectionMultiplexer.Connect("127.0.0.1:6379"); services.AddDataProtection() .SetApplicationName("session_application_name") .PersistKeysToRedis(redis, "DataProtection-Keys"); services.AddDistributedRedisCache(options =>{ options.Configuration = "127.0.0.1"; options.InstanceName = "sampleInstance"; }); services.AddMvc(); services.AddSession(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env){ if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseSession(); app.UseStaticFiles(); app.UseMvc(routes =>{ routes.MapRoute(name: "default",template: "{controller=Home}/{action=Index}/{id?}"); }); } } }
HomeControler.cs
public class HomeController : Controller { public IActionResult Index() { HttpContext.Session.Set("app1test",Encoding.UTF8.GetBytes("app1testvalue")); return View(); } public IActionResult ShowRedis() { byte[] temp; if(HttpContext.Session.TryGetValue("app1test",out temp)) { ViewData["Redis"]=Encoding.UTF8.GetString(temp); } return View(); } }
ShowRedis.cshtml
Redis Session Value:ViewData["Redis"]
app2项目
Startup.cs
配置同app1配置一样。
HomeControler.cs
public class HomeController : Controller { public IActionResult Index() { byte[] temp; if(HttpContext.Session.TryGetValue("app1test",out temp)) { ViewData["Redis"]=Encoding.UTF8.GetString(temp); } return View(); } }
Index.cshtml
ViewData["Redis"]
运行效果
app1 项目
首次打开进入ShowRedis页面,Session值为空
点击SetSessionValue以后,再回到ShowRedis页面:
app2项目,直接在浏览器访问::5001
以上是用Redis实现分布式Session示例。
1.4. 总结
本节讲解了中间件的运行原理及配置过程,中间件之间对象依赖关系的配置和平时项目中常用到Session的配置问题。并在实际代码展示了怎样使用中间件实现分布式Session。