在AbpController中,通过属性注入的方式注入IAbpSession对象。
IAbpSession的实例ClaimsAbpSession。
public class ClaimsAbpSession : IAbpSession, ISingletonDependency { public virtual long? UserId { get { var userIdClaim = PrincipalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier); if (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 MultiTenancyConsts.DefaultTenantId; } var tenantIdClaim = PrincipalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == AbpClaimTypes.TenantId); if (string.IsNullOrEmpty(tenantIdClaim?.Value)) { return null; } return Convert.ToInt32(tenantIdClaim.Value); } }
View CodePrincipalAccessor.Principal指的是ClaimsPrincipal类型的对象。该对象获得的方式如下:
public virtual ClaimsPrincipal Principal => Thread.CurrentPrincipal as ClaimsPrincipal;
public static IPrincipal CurrentPrincipal { [System.Security.SecuritySafeCritical] // auto-generated get { lock (CurrentThread) { IPrincipal principal = (IPrincipal) CallContext.Principal; if (principal == null) { principal = GetDomain().GetThreadPrincipal(); CallContext.Principal = principal; } return principal; } } [System.Security.SecuritySafeCritical] // auto-generated [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)] set { CallContext.Principal = value; } }
View CodeThread.CurrentPrincipal通过CallContext.Principal或GetDomain().GetThreadPrincipal(). 获得IPrincipal对象。
无论通过哪种方式,该IPrincipal对象,都是从请求上下文获得的。
因此:IAbpSession保存的值是从请求上下文获得的,应用程序必然在某个时刻,将值保存到请求上下文中。这一步是通过OWIN实现的。
与IAbpSession相关的OWIN
在MVC项目App_Start文件夹添加Startup文件。
public class Startup { public void Configuration(IAppBuilder app) { app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/"), CookieSecure = CookieSecureOption.Never, }); }
View Code这一步的作用是向请求管道注册了一个事件。该事件在请求处理的Authenticate阶段执行,执行的内容是获得请求上下文的cookie(string字符串),经过解码和解密,将键值对保存成多个Claim类型的对象,并将这些Claim对象集合保存到ClaimsIdentity类型的对象Claims属性中。
ClaimsIdentity类型中的Claims属性:public virtual IEnumerable<Claim> Claims { get; }
ClaimsIdentity类型的对象又被上下文所引用。
因此可理解:Thread.CurrentPrincipal as ClaimsPrincipal 即是指这个解密出来的ClaimsIdentity对象。
如何将用户信息保存到上下文,并加密到cookie
AuthenticationManager类型
internal class AuthenticationManager : IAuthenticationManager
为控制器添加如下属性: