如果一個應用程序需要登錄,則它必須知道當前用戶執行了什么操作。因此ASP.NET在展示層提供了一套自己的SESSION會話對象,而ABP則提供了一個可以在任何地方
獲取當前用戶和租戶的IAbpSession接口。
關于IAbpSession
需要獲取會話信息則必須實現IAbpSession接口。雖然你可以用自己的方式去實現它(IAbpSession),但是它在module-zero項目中已經有了完整的實現。
注入Session
IAbpSession通常是以屬性注入的方式存在于需要它的類中,不需要獲取會話信息的類中則不需要它。如果我們使用屬性注入方式,我們可以用
NullAbpSession.Instance作為默認值來初始化它(IAbpSession),如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public class MyClass : ITransientDependency { public IAbpSession AbpSession { get ; set ; } public MyClass() { AbpSession = NullAbpSession.Instance; } public void MyMethod() { var currentUserId = AbpSession.UserId; //... } } |
由于授權是應用層的任務,因此我們應該在應用層和應用層的上一層使用IAbpSession(我們不在領域層使用IAbpSession是很正常的)。
ApplicationService, AbpController 和 AbpApiController 這3個基類已經注入了AbpSession屬性,因此在Application Service的實例方法中,能直接使用AbpSession屬性。
使用Session屬性
AbpSession定義的一些關鍵屬性:
- UserId: 當前用戶的標識ID,如果沒有當前用戶則為null.如果需要授權訪問則它不可能為空。
- TenantId: 當前租戶的標識ID,如果沒有當前租戶則為null。
- MultiTenancySide: 可能是Host或Tenant。
UserId和TenantId是可以為null的。當然也提供了不為空時獲取數據的 GetUserId()和GetTenantId() 方法 。當你確定有當前用戶時,你可以使用GetUserId()方法。
如果當前用戶為空,使用該方法則會拋出一個異常。GetTenantId()的使用方式和GetUserId()類似。
ABP如何實現Session的
目錄代碼:
類圖:
IAbpSession:IAbpSession接口
1
2
3
4
5
6
7
8
9
10
11
12
13
|
using Abp.MultiTenancy; namespace Abp.Runtime.Session { public interface IAbpSession { long ? UserId { get ; } int ? TenantId { get ; } MultiTenancySides MultiTenancySide { get ; } long ? ImpersonatorUserId { get ; } int ? ImpersonatorTenantId { get ; } } } |
NullAbpSession:實現了空對象模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
using Abp.MultiTenancy; namespace Abp.Runtime.Session { /// <summary> /// Implements null object pattern for <see cref="IAbpSession"/>. /// </summary> public class NullAbpSession : IAbpSession { /// <summary> /// Singleton instance. /// </summary> public static NullAbpSession Instance { get { return SingletonInstance; } } private static readonly NullAbpSession SingletonInstance = new NullAbpSession(); /// <inheritdoc/> public long ? UserId { get { return null ; } } /// <inheritdoc/> public int ? TenantId { get { return null ; } } public MultiTenancySides MultiTenancySide { get { return MultiTenancySides.Tenant; } } public long ? ImpersonatorUserId { get { return null ; } } public int ? ImpersonatorTenantId { get { return null ; } } private NullAbpSession() { } } } |
ClaimsAbpSession:獲取會話狀態
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
using System; using System.Linq; using System.Security.Claims; using System.Threading; using Abp.Configuration.Startup; using Abp.MultiTenancy; using Abp.Runtime.Security; namespace Abp.Runtime.Session { /// <summary> /// Implements <see cref="IAbpSession"/> to get session properties from claims of <see cref="Thread.CurrentPrincipal"/>. /// </summary> public class ClaimsAbpSession : IAbpSession { private const int DefaultTenantId = 1; public virtual long ? UserId { get { var claimsPrincipal = Thread.CurrentPrincipal as ClaimsPrincipal; if (claimsPrincipal == null ) { return null ; } var claimsIdentity = claimsPrincipal.Identity as ClaimsIdentity; if (claimsIdentity == null ) { return null ; } var userIdClaim = claimsIdentity.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier); if (userIdClaim == null || string .IsNullOrEmpty(userIdClaim.Value)) { return null ; } long userId; if (! long .TryParse(userIdClaim.Value, out userId)) { return null ; } return userId; } } public virtual int ? TenantId { get { if (!_multiTenancy.IsEnabled) { return DefaultTenantId; } var claimsPrincipal = Thread.CurrentPrincipal as ClaimsPrincipal; if (claimsPrincipal == null ) { return null ; } var tenantIdClaim = claimsPrincipal.Claims.FirstOrDefault(c => c.Type == AbpClaimTypes.TenantId); if (tenantIdClaim == null || string .IsNullOrEmpty(tenantIdClaim.Value)) { return null ; } return Convert.ToInt32(tenantIdClaim.Value); } } public virtual MultiTenancySides MultiTenancySide { get { return _multiTenancy.IsEnabled && !TenantId.HasValue ? MultiTenancySides.Host : MultiTenancySides.Tenant; } } public virtual long ? ImpersonatorUserId { get { var claimsPrincipal = Thread.CurrentPrincipal as ClaimsPrincipal; if (claimsPrincipal == null ) { return null ; } var impersonatorUserIdClaim = claimsPrincipal.Claims.FirstOrDefault(c => c.Type == AbpClaimTypes.ImpersonatorUserId); if (impersonatorUserIdClaim == null || string .IsNullOrEmpty(impersonatorUserIdClaim.Value)) { return null ; } return Convert.ToInt64(impersonatorUserIdClaim.Value); } } public virtual int ? ImpersonatorTenantId { get { if (!_multiTenancy.IsEnabled) { return DefaultTenantId; } var claimsPrincipal = Thread.CurrentPrincipal as ClaimsPrincipal; if (claimsPrincipal == null ) { return null ; } var impersonatorTenantIdClaim = claimsPrincipal.Claims.FirstOrDefault(c => c.Type == AbpClaimTypes.ImpersonatorTenantId); if (impersonatorTenantIdClaim == null || string .IsNullOrEmpty(impersonatorTenantIdClaim.Value)) { return null ; } return Convert.ToInt32(impersonatorTenantIdClaim.Value); } } private readonly IMultiTenancyConfig _multiTenancy; /// <summary> /// Constructor. /// </summary> public ClaimsAbpSession(IMultiTenancyConfig multiTenancy) { _multiTenancy = multiTenancy; } } } |
AbpSessionExtensions:IAbpSession擴展方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
using System; namespace Abp.Runtime.Session { /// <summary> /// Extension methods for <see cref="IAbpSession"/>. /// </summary> public static class AbpSessionExtensions { /// <summary> /// Gets current User's Id. /// Throws <see cref="AbpException"/> if <see cref="IAbpSession.UserId"/> is null. /// </summary> /// <param name="session">Session object.</param> /// <returns>Current User's Id.</returns> public static long GetUserId( this IAbpSession session) { if (!session.UserId.HasValue) { throw new AbpException( "Session.UserId is null! Probably, user is not logged in." ); } return session.UserId.Value; } /// <summary> /// Gets current Tenant's Id. /// Throws <see cref="AbpException"/> if <see cref="IAbpSession.TenantId"/> is null. /// </summary> /// <param name="session">Session object.</param> /// <returns>Current Tenant's Id.</returns> /// <exception cref="AbpException"></exception> public static int GetTenantId( this IAbpSession session) { if (!session.TenantId.HasValue) { throw new AbpException( "Session.TenantId is null! Possible problems: No user logged in or current logged in user in a host user (TenantId is always null for host users)." ); } return session.TenantId.Value; } /// <summary> /// Creates <see cref="UserIdentifier"/> from given session. /// Returns null if <see cref="IAbpSession.UserId"/> is null. /// </summary> /// <param name="session">The session.</param> public static UserIdentifier ToUserIdentifier( this IAbpSession session) { return session.UserId == null ? null : new UserIdentifier(session.TenantId, session.GetUserId()); } } } |