上篇实战完成后,没想到会有那么多的圈友给了那么多的支持,甚至连只是作为代码仓储的git上也给了一些小星星,真的感觉很惶恐啊,哈哈哈,毕竟代码写的很烂啊。由于上一篇只是大概说了下项目,所以准备写下这篇详细说下自己对于获取当前登录用户的设计与实现,原本准备上周末就完成的这篇,结果周六一起来,发现自己起水痘了,嗯,很悲催。。。请了一个星期的假,今天好歹头不痛,不发烧能看电脑了,就努力努力赶出来吧。
获取当前登录用户的整体思路,我们可以通过创建一个静态的用户类,存储当前登录的用户。通过将属性值存储在session中,从而存储到服务器的内存中,做到可以在系统全局中获取当前登录用户的数据信息。
.NET Framework平台下面的MVC与.NET Core平台下面的MVC,对于Session的使用上存在着一些的差异,主要在于如何获取到Session对象。在传统的MVC项目中我们可以直接使用HttpContext.Current.Session获取到session,从而做到对于数据的取值、赋值;而在ASP.NET Core MVC中,并没有HttpContext.Current.Session这个静态类,通过查阅微软的文档可知,我们可以通过注入IHttpContextAccessor对象的方式从而获取到session对象,解决方案如下所示。
首先,在ASP.NET Core 中使用Session,我们需要将Session注入到ASP.NET Core的管道(pipeline)中,和我们使用MVC的方式相同,在ConfigureServices(IServiceCollection services)中,添加
1 services.AddSession();
在Configure(IApplicationBuilder app, IHostingEnvironment env)中添加
1 app.UseSession();
这样,我们就可以在MVC中使用到Session了。当然现在也只是能在Controller中获取到Session对象,如果想在别的类文件中使用到Session对象,我们需要注入IHttpContextAccessor对象。这里,我们可以使用nuget添加Microsoft.AspNetCore.Http.Extensions这个程序集,方便我们对于Session进行操作。
因为我们采用静态类作为当前登录用户的载体,而静态类不能拥有实例构造函数,所以我采用创建一个配置方法来进行注入,CurrentUser类如下所示。
1 public static class CurrentUser
2 {
3 #region Initialize
4
5 private static IHttpContextAccessor _httpContextAccessor;
6
7 private static ISession _session => _httpContextAccessor.HttpContext.Session;
8
9 public static void Configure(IHttpContextAccessor httpContextAccessor)
10 {
11 _httpContextAccessor = httpContextAccessor;
12 }
13
14 #endregion
15
16 #region Attribute
17
18 /// <summary>
19 /// 用户主键
20 /// </summary>
21 public static string UserOID
22 {
23 get => _session == null ? "" : _session.GetString("CurrentUser_UserOID");
24 set => _session.SetString("CurrentUser_UserOID", !string.IsNullOrEmpty(value) ? value : "");
25 }
26
27 /// <summary>
28 ///用户编号
29 /// </summary>
30 public static long UserId
31 {
32 get => _session == null ? 0 : Convert.ToInt64(_session.GetString("CurrentUser_UserId"));
33 set => _session.SetString("CurrentUser_UserId", value != 0 ? value.ToString() : "0");
34 }
35
36 /// <summary>
37 /// 用户姓名
38 /// </summary>
39 public static string UserName
40 {
41 get => _session == null ? "" : _session.GetString("CurrentUser_UserName");
42 set => _session.SetString("CurrentUser_UserName", !string.IsNullOrEmpty(value) ? value : "");
43 }
44
45 /// <summary>
46 /// 用户登录账户
47 /// </summary>
48 public static string UserAccount
49 {
50 get => _session == null ? "" : _session.GetString("CurrentUser_UserAccount");
51 set => _session.SetString("CurrentUser_UserAccount", !string.IsNullOrEmpty(value) ? value : "");
52 }
53
54 /// <summary>
55 /// 用户头像地址
56 /// </summary>
57 public static string UserImage
58 {
59 get => _session == null ? "" : _session.GetString("CurrentUser_UserImage");
60 set => _session.SetString("CurrentUser_UserImage", !string.IsNullOrEmpty(value) ? value : "");
61 }
62
63 /// <summary>
64 /// 用户角色
65 /// </summary>
66 public static string UserRole
67 {
68 get => _session == null ? "" : _session.GetString("CurrentUser_UserRole");
69 set => _session.SetString("CurrentUser_UserRole", !string.IsNullOrEmpty(value) ? value : "");
70 }
71
72 /// <summary>
73 /// 主页地址
74 /// </summary>
75 public static string UserPage
76 {
77 get => _session == null ? "" : _session.GetString("CurrentUser_UserPage");
78 set => _session.SetString("CurrentUser_UserPage", !string.IsNullOrEmpty(value) ? value : "");
79 }
80
81 #endregion
82 }
当我们创建好了这样一个静态类后,我们就可以在登录成功后,将当前登录的用户信息赋值给这个静态类,这样我们就可以在需要使用到的地方直接使用CurrentUser这个静态类即可。在当时实际使用后发现,想要获取到登录后存储的用户信息,则必须在Controller的构造方法中调用CurrentUser的Configure方法,无形中还是增加了许多的工作量。
Controller的构造函数示例代码如下:
1 [Area("Administrator")]
2 [Authorize(Policy = "Administrator")]
3 public class HomeController : DanvicController
4 {
5 #region Initialize
6
7 private readonly ApplicationDbContext _context;
8 private readonly ILogger _logger;
9 private readonly IHomeService _service;
10 private readonly IHttpContextAccessor _httpContextAccessor;
11 public HomeController(IHomeService service, ILogger<HomeController> logger, IHttpContextAccessor httpContextAccessor, ApplicationDbContext context)
12 {
13 _service = service;
14 _logger = logger;
15 _httpContextAccessor = httpContextAccessor;
16 _context = context;
17 CurrentUser.Configure(_httpContextAccessor);
18 }
19
20 #endregion
21
22 #region View
23
24 #endregion
25 }
登录成功后给CurrentUser赋值的相关代码如下所示:
1 /// <summary>
2 /// 设置当前登录用户
3 /// </summary>
4 public async Task SetCurrentUser(string oid, IHttpContextAccessor httpContextAccessor, ApplicationDbContext context)
5 {
6 CurrentUser.Configure(httpContextAccessor);
7
8 var user = await PSURepository.GetUserByOIDAsync(oid, context);
9
10 if (user != null)
11 {
12 string role = string.Empty;
13 switch (user.AccountType)
14 {
15 case 0:
16 role = "Administrator";
17 break;
18 case 1:
19 role = "Instructor";
20 break;
21 case 2:
22 role = "Student";
23 break;
24 }
25
26 CurrentUser.UserAccount = user.Account;
27 CurrentUser.UserId = user.Id;
28 CurrentUser.UserImage = user.ImageSrc;
29 CurrentUser.UserName = user.Name;
30 CurrentUser.UserOID = user.IdentityUserOID;
31 CurrentUser.UserRole = role;
32 CurrentUser.UserPage = user.HomePage;
33 }
34 }
这样就可以了,当需要使用到当前登录的用户信息时,直接CurrentUser.属性就可以了,整个项目的代码还是在项目实战的那个代码仓库中,地址点后面:源代码仓储,欢迎大家提出更好的解决方案啊。