2013-12-11 15 views
25

在默認的AccountController創建我看到如何在asp.net web api 2中自定義身份驗證到我自己的表中?

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>()); 

我我正在尋找一種正確的方式來定製認證。

回答

42

假設你的表稱爲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<AppUser>(new UserStoreService()) { PasswordHasher = new MyPasswordHasher() }; 

更換

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

ApplicationOAuthProvider.cs,更換IdentityUserAppUser

AccountController.cs,與AppUser取代IdentityUser並刪除所有的外部身份驗證方法,如GetManageInfoRegisterExternal

+0

謝謝你的答案,但我怎麼可以從另一個控制器獲得'AppUser'當前請求? –

+0

'User.Identity.Name'會爲您提供經過驗證的請求中的用戶名。 – sunil

+0

偉大的文章和解釋。謝謝,sunil。 –