记AbpSession扩展实现过程

  AbpSession只给了userId和TenantId,此次实际项目中并不够用,网上找了好久也没找到好的实现方法。项目初期没有时间进行研究,最近空了试了一下,大体实现添加额外字段并读取相应值的功能。html

  本文以实现添加用户名字字段为例session

  主要参考如下文章:框架

  1、基于 DDD 的. NET 开发框架 - ABP Session 实现
async

    该文主要介绍了ABP中关于AbpSession的源码及其实现,注:源码及其实现请参考此文,本文不作赘述ide

  2、ABP 初探 之 AbpSession 扩展post

    该文记录做者对于AbpSession扩展的尝试,彷佛是在源代码上进行的修改(仅我的猜想),实现方法大体与本文相同,但本文的实现未修改源代码this

  3、MVC5 - ASP.NET Identity 登陆原理 - Claims-based 认证和 OWINgoogle

    该文介绍并讲解了ABP使用的登录验证组件 ASP.NET Identity url

 

    参考上述文章后大概有一个实现思路,思路以下:spa

  1.建立一个继承自ClaimsAbpSession的类,该类中实现本身新加字段的读取

    代码以下:

 1  public class MyAbpSession : ClaimsAbpSession
 2     {
 3         public MyAbpSession(IMultiTenancyConfig multiTenancy) : base(multiTenancy)
 4         {
 5 
 6         }
 7 
 8         public virtual string UserName
 9         {
10             get
11             {
12                 var userIdClaim = PrincipalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == "UserName");
13                 return userIdClaim.Value;
14             }
15         }
16     }

  2.替换ABP中IAbpSession接口的实现类ClaimsAbpSession为MyAbpSession 

  

1         public override void PreInitialize()
2          {
3              //Enable database based localization
4              Configuration.Modules.Zero().LanguageManagement.EnableDbLocalization();
5  
6              //替换IAbpSession的实现类
7              Configuration.ReplaceService<IAbpSession, MyAbpSession>(DependencyLifeStyle.Transient);
8             
9          }

  3.用户登录后往现有的Claims中插入UserName的Claim

 1   private async Task SignInAsync(User user, ClaimsIdentity identity = null, bool rememberMe = false)
 2         {
 3 
 4             if (identity == null)
 5             {
 6                 identity = await _userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
 7             }
 8             else
 9             {
10                 //UserName为查询用标识(key)
11                 identity.AddClaim(new Claim("UserName", user.Name));
12             }
13             AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
14             AuthenticationManager.SignIn(new AuthenticationProperties {IsPersistent = rememberMe}, identity);
15         }

  通过这些代码后,设置断点可查看到,新的session中已经存在咱们须要的UserName字段而且数据已经拿到手了。

  

  可是因为IAbpSession接口没有提供UserName字段,因此这个时候咱们是没有办法在写代码的时候经过AbpSession.UserName来获取的,这样作会报错。固然你能够强制转换后强行获取,这样明显是不符合咱们要求的。

  因而参考了ABP的源码,ABP中有一个扩展类AbpSessionExtensions,实现了经过方法来获取UserId的值。因而我转换了一下实现思路

  

  4.经过扩展类,以方法的方式来获取该值

  该扩展实现后原MyAbpSession类已经没有用了,能够删去,本文主要从最早思路开始,因此还留着。即最终实现只须要按三、4的步骤进行,无需从一开始。

1     public static class MyAbpSessionExtensions
2     {
3         public static string GetUserName(this IAbpSession session)
4         {
5             //在ABP源码中也是经过DefaultPrincipalAccessor.Instance来获取PrincipalAccessor  即此处的DefaultPrincipalAccessor.Instance等价于上文中的PrincipalAccessor
6             var userIdClaim = DefaultPrincipalAccessor.Instance.Principal?.Claims.FirstOrDefault(c => c.Type == "UserName");
7             return userIdClaim.Value;
8         }
9     }

  至此能够在代码中以方法的方式来获取UserName的值了

  

  

  附:实在是想不出怎么以字段的方式来实现(即AbpSession.UserName),除了改ABP源码修改IAbpSession,只能求其次以方法来实现。菜鸟实力只到这里,望有大神能够解决此问题 

   实现过程仍是走了弯路的特别是替换IAbpSession的实现类,直接接触的IOC相关才少,都不知道怎么换,不过最终仍是查到了相关代码,果真仍是要多百度和google。

  看到ABP 入门系列(10)——扩展 AbpSession受启发

  新建IMyAbpSession接口

 

   public interface IMyAbpSession:IAbpSession
    {

        string UserName{ get;}
    }

  并使MyAbpSession继承该接口,以后再controller和 Service基类中替换原有AbpSession便可以属性方式来使用

 public new IMyAbpSession AbpSession { get; set; }

  ABP的求知路还很漫长啊~求基友一块儿啊

相关文章
相关标签/搜索