如果一个应用程序需要登录,则它必须知道当前用户执行了什么操作。因此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()); } } } |