如何在 asp.net web api 2 中自定义对我自己的一组表的身份验证?

Posted

技术标签:

【中文标题】如何在 asp.net web api 2 中自定义对我自己的一组表的身份验证?【英文标题】:How to customize authentication to my own set of tables in asp.net web api 2? 【发布时间】:2013-12-30 00:45:53 【问题描述】:

在我看到的默认 AccountController 创建中

    public AccountController()
        : this(Startup.UserManagerFactory(), Startup.OAuthOptions.AccessTokenFormat)
    
    

在 Startup.Auth.cs 我看到

    UserManagerFactory = () => 
                new UserManager<IdentityUser>(new UserStore<IdentityUser>());   

UserStore 的实现似乎来自 Microsoft.AspNet.Identity.EntityFramework

所以,要自定义身份验证,我是否必须实现我自己的 UserStore 版本,例如

 class MYSTUFFUserStore<IdentityUser> : UserStore<IdentityUser>
 
  

并覆盖方法,然后在 Startup.Auth.cs 中执行此操作

UserManagerFactory = () => 
               new UserManager<IdentityUser>(new MYSTUFFUserStore<IdentityUser>());   

我正在寻找自定义身份验证的正确方法。

【问题讨论】:

【参考方案1】:

假设你的表被称为AppUser,像这样将你自己的AppUser域对象转换为IUser(using Microsoft.AspNet.Identity)

using Microsoft.AspNet.Identity;
public class AppUser : IUser

    //Existing database fields
    public long AppUserId  get; set; 
    public string AppUserName  get; set; 
    public string AppPassword  get; set; 

    public AppUser()
    
        this.Id = Guid.NewGuid().ToString();  
    

    [Ignore]
    public virtual string Id  get; set;          
    [Ignore]
    public string UserName
    
        get
        
            return AppUserName;
        
        set
        
            AppUserName = value;
        
    

像这样实现UserStore 对象

using Microsoft.AspNet.Identity;
public class UserStoreService 
         : IUserStore<AppUser>, IUserPasswordStore<AppUser>

    CompanyDbContext context = new CompanyDbContext();

    public Task CreateAsync(AppUser user)
                
        throw new NotImplementedException();
    

    public Task DeleteAsync(AppUser user)
    
        throw new NotImplementedException();
    

    public Task<AppUser> FindByIdAsync(string userId)
    
        throw new NotImplementedException();
    

    public Task<AppUser> FindByNameAsync(string userName)
    
        Task<AppUser> task = context.AppUsers.Where(
                              apu => apu.AppUserName == userName)
                              .FirstOrDefaultAsync();

        return task;
    

    public Task UpdateAsync(AppUser user)
    
        throw new NotImplementedException();
    

    public void Dispose()
    
        context.Dispose();
    

    public Task<string> GetPasswordHashAsync(AppUser user)
    
        if (user == null)
        
            throw new ArgumentNullException("user");
        

        return Task.FromResult(user.AppPassword);
    

    public Task<bool> HasPasswordAsync(AppUser user)
    
        return Task.FromResult(user.AppPassword != null);
    

    public Task SetPasswordHashAsync(AppUser user, string passwordHash)
    
        throw new NotImplementedException();
    


如果您有自己的自定义密码哈希,您还需要实现IPasswordHasher。下面是一个没有密码散列的例子(哦,不!)

using Microsoft.AspNet.Identity;
public class MyPasswordHasher : IPasswordHasher

    public string HashPassword(string password)
    
        return password;
    

    public PasswordVerificationResult VerifyHashedPassword
                  (string hashedPassword, string providedPassword)
    
        if (hashedPassword == HashPassword(providedPassword))
            return PasswordVerificationResult.Success;
        else
            return PasswordVerificationResult.Failed;
    

在 Startup.Auth.cs 中替换

UserManagerFactory = () => 
     new UserManager<IdentityUser>(new UserStore<IdentityUser>());

    UserManagerFactory = () => 
     new UserManager<AppUser>(new UserStoreService())  PasswordHasher = new MyPasswordHasher() ;

ApplicationOAuthProvider.cs 中,将IdentityUser 替换为AppUser

AccountController.cs中,将IdentityUser替换为AppUser,并删除GetManageInfoRegisterExternal等所有外部认证方式。

【讨论】:

感谢您的回答,但是对于当前请求,我如何从另一个控制器获取AppUser User.Identity.Name 将在经过身份验证的请求中为您提供用户名。 Sunil,你能解释一下为什么自定义类“AppUser”需要实现内置接口“IUser”吗? @Thomas.Benz 这是我发现有用的一篇文章中的一个 sn-p:“Microsoft.AspNet.Identity.UserManager where T: IUser 这个类允许创建、删除和查找用户以及创建身份。身份是为用户创建的,可用于做出授权和身份验证决策。这里的想法是使用 ASP.NET Identity 的一些/大部分内置功能,然后使用自定义实现覆盖/替换您需要的功能 - 至少这就是我在这里所做的,这要归功于 Sunil 的回答

以上是关于如何在 asp.net web api 2 中自定义对我自己的一组表的身份验证?的主要内容,如果未能解决你的问题,请参考以下文章

防止 ASP.NET Web API 路由引擎扣除自定义方法名

ASP.NET Core 3.1 中的 Ocelot API Gateway 自定义聚合器问题

如何在 ASP.NET Web API 5.2.3 中使用 FromForm 属性

Asp.Net Web API 2第十一课——在Web API中使用Dependency Resolver

Asp.Net Web API 2第十课——使用OWIN自承载Web API

Web API系列教程2.1 — ASP.NET Web API中的路由机制