آموزش سفارشی کردن Asp.Net Identity با پایگاه داده خارجی
سه شنبه 4 آبان 1395Asp.Net Identity به این دلیل طراحی شده است تا به ما توانایی و قابلیت استفاده از Storage Providerهای مختلف را در برنامه های ASP.Net ، به ما بدهد . ما میتوانیم ازIdentity Providerهایی که با Net Framework. عرضه شده است استفاده کنیم و هم میتوانیم Providerهای خودمان را طراحی کنیم . در این مقاله به بررسی ایجاد Provider های سفارشی خواهیم پرداخت .
آموزش تصویری نصب و استفاده از Asp.Net Identity 2
دو دلیل اساسی برای ایجاد Providerهای سفارشی وجود دارد .
ما نیاز به ذخیرهسازی اطلاعات Identity در data sourceای راداریم که توسط Identity Provider ای که در
Net Framework. وجود دارد ، پشتیبانی نمیشود ، مثل پایگاه داده های MySQL ، یک پایگاه داده Oracle یا منابع داده های دیگر .
ما باید اطلاعات Identity را با استفاده از یک Database schema ای که با Provider ، Database schema ما متفاوت است ، مدیریت کنیم .
در مثالی که در ادامه مقاله مشاهده خواهید کرد ، ما قصد پیاده سازی و پیکربندی یک Identity Provider سفارشی با استفاده از ASP.Net MVC 5 را داریم .
ایجاد پروژه ASP.Net MVC :
Visual Studio راباز کرده و یک پروژه ASP.NET Web application ایجاد کنید و MVC Template را انتخاب کنید .

بعد از ایجاد شدن پروژه F5 را میزنیم تا برنامه اجرا شود . بعد اجرا Register را برای ساختن یک کاربر جدید میزنیم . مراحل زیر را دنبال کنید :

بعد از پر کردن فیلد های مربوط به ثبت نام Register را بزنید :

در Solution Explorer روی فولدر App_Data کلیک راست کرده و فولدر root آن را باز کنید :


خواهید دید که بعد از اجرای برنامه پایگاه داده ایی با نام aspnet-AspNetIdentity-20160402093629 ساخته خواهد شد ، asp.net از این پایگاه داده برای ذخیره سازی اطلاعات امنیتی نظیر username ، Password و ... استفاده خواهد کرد .
توجه داشته باشید که aspnet-AspNetIdentity-2016040209362 در پایگاه داده ساخته نشده است اما به آن ضمیمه شده است . پس ، ما پایگاه داده را به SQL Server منتقل میکنیم و آن برای Customize Identity استفاده میکنیم .
در Visual Studio در قسمت منو، روی View کلیک و سپس روی SQL Server Object Explorer کلیک کنید ، پایگاه داده خود را انتخاب کرده و فولدر Table را باز کنید :
پنج Table ساخته شده است :
AspNetRoles, AspNetUserClaims, AspNetUserLogins, AspNetUserRoles, AspNetUsers .

با ایجاد یک database diagram ما میتوانیم یک نگاه اجمالی به modelهای پایگاه داده خود داشته باشیم :

در نهایت ، فایل web.Config را باز کرده و مشخصات ConnectionString را برای پایگاه داده خود تنظیم کنید :
حال F5 را میزنیم تا برنامه اجرا شود ، بعد به سراغ ایجاد یک کاربر جدید میرویم :
درحال حاضر برنامه ما، برای استفاده از یک Storage خارجی آماده است . در مرحله بعد ، چگونگی سفارشی کردن پایگاه داده خارجی را برای شما بیان خواهیم کرد .
ایجاد Identity Library Project :
یک class library ایجاد کرده و نام آن را IdentityLibrary میگذاریم :
روی References کلیک راست کرده و Manage NuGet Packages را انتخاب کنید :

Microsoft.AspNet.Identity.Core و Microsoft.AspNet.Identity.EntityFramework را نصب کنید .


یک کلاس با نام IdentityUser برای نگهداری اطلاعات کاربران ایجاد کنید ، این کلاس از IdentityUser ارثبری میکند :

کلاس IdentityRole را برای نگهداری اطلاعات در مورد نقش کاربران را ایجاد کنید :

یک کلاس با نام UserStore ایجاد کنید ، Asp.Net MVC بصورت پیش فرض از این کلاس استفاده خواهد کرد :
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
اما با این وجود ، ما برای سفارشی کردن Storage Provider آن را پیاده سازی میکنیم :

برای پیاده سازی IRoleIdentity ، کلاسی با نام RoleStore میکنیم :

ایجاد یک Entity Framework dataModel :
روی پروژه IdentityLibrary راست کلیک کرده و add new item را بزنید ، ADO.NET Entity Data Model را انتخاب کرده و Add را بزنید :

Code First From Database را انتخاب کرده و Next را بزنید :

اگه ما یک data connection داریم میتوانیم آن را انتخاب کنیم یا اینکه یک connection جدید ایجاد کنیم :

Server Name را انتخاب کنید ، از Windows Authentication یا SQL Server Authentication استفاده کنید ،
سپس پایگاه داده مورد نظر را انتخاب کرده و Ok را بزنید :

جداول پایگاه داده را چک انتخاب کرده تا model ما را تولید کند :

خب ، پنج کلاس در پروژه IdentityLibrary ایجاد شده است ، که به جداول پایگاه داده متصل است :

برای هدف قرار دادن ASP.Net Client ، Custom Identity Library را پیکربندی میکنیم :



پیاده سازی Custom Identity :
• پیاده سازی UserStore :
/// <summary>
/// Class that implements the key ASP.NET Identity user store iterfaces
/// </summary>
public class UserStore<T> : IUserRoleStore<T>,
IUserStore<T>,
IUserPasswordStore<T>,
IUserEmailStore<T>,
IUserLockoutStore<T, string>,
IUserTwoFactorStore<T, string>
where T : IdentityUser
{
private readonly UserRepository<T> _userTable;
private readonly UserRolesRepository _userRolesTable;
public UserStore(DatabaseContext databaseContext)
{
_userTable = new UserRepository<T>(databaseContext);
_userRolesTable = new UserRolesRepository(databaseContext);
}
public Task CreateAsync(T user)
{
if (user == null)
{
throw new ArgumentNullException(“user”);
}
return Task.Run(() => _userTable.Insert(user));
}
public Task<T> FindByIdAsync(string userId)
{
if (string.IsNullOrEmpty(userId))
{
throw new ArgumentException(“Null or empty argument: userId”);
}
return Task.Run(() => _userTable.GeTById(userId));
}
public Task<bool> GetTwoFactorEnabledAsync(T user)
{
return Task.FromResult(user.TwoFactorEnabled);
}
public Task<T> FindByNameAsync(string userName)
{
if (string.IsNullOrEmpty(userName))
{
throw new ArgumentException(“Null or empty argument: userName”);
}
return Task.Run(() => _userTable.GeTByName(userName));
}
public Task<IList<string>> GetRolesAsync(T user)
{
if (user == null)
{
throw new ArgumentNullException(“user”);
}
return Task.Run(() => _userRolesTable.FindByUserId(user.Id));
}
public Task<string> GetPasswordHashAsync(T user)
{
return Task.Run(() => _userTable.GetPasswordHash(user.Id));
}
public Task SetPasswordHashAsync(T user, string passwordHash)
{
return Task.Run(() => user.PasswordHash = passwordHash);
}
public Task<T> FindByEmailAsync(string email)
{
if (String.IsNullOrEmpty(email))
{
throw new ArgumentNullException(“email”);
}
return Task.Run(() => _userTable.GeTByEmail(email));
}
public Task<string> GetEmailAsync(T user)
{
return Task.FromResult(user.Email);
}
public Task<int> GetAccessFailedCountAsync(T user)
{
return Task.FromResult(user.AccessFailedCount);
}
public Task<bool> GetLockoutEnabledAsync(T user)
{
return Task.FromResult(user.LockoutEnabled);
}
public Task<DateTimeOffset> GetLockoutEndDateAsync(T user)
{
return
Task.FromResult(user.LockoutEndDateUtc.HasValue
? new DateTimeOffset(DateTime.SpecifyKind(user.LockoutEndDateUtc.Value, DateTimeKind.Utc))
: new DateTimeOffset());
}
public Task SetLockoutEnabledAsync(T user, bool enabled)
{
user.LockoutEnabled = enabled;
return Task.Run(() => _userTable.Update(user));
}
public Task SetLockoutEndDateAsync(T user, DateTimeOffset lockoutEnd)
{
throw new NotImplementedException();
}
public Task SetTwoFactorEnabledAsync(T user, bool enabled)
{
throw new NotImplementedException();
}
public Task DeleteAsync(T user)
{
throw new NotImplementedException();
}
public Task<int> IncrementAccessFailedCountAsync(T user)
{
throw new NotImplementedException();
}
public Task ResetAccessFailedCountAsync(T user)
{
throw new NotImplementedException();
}
public Task<bool> GetEmailConfirmedAsync(T user)
{
throw new NotImplementedException();
}
public Task SetEmailAsync(T user, string email)
{
throw new NotImplementedException();
}
public Task SetEmailConfirmedAsync(T user, bool confirmed)
{
throw new NotImplementedException();
}
public Task<bool> IsInRoleAsync(T user, string roleName)
{
throw new NotImplementedException();
}
public Task RemoveFromRoleAsync(T user, string roleName)
{
throw new NotImplementedException();
}
public Task<bool> HasPasswordAsync(T user)
{
throw new NotImplementedException();
}
public Task UpdateAsync(T user)
{
throw new NotImplementedException();
}
public Task AddToRoleAsync(T user, string roleName)
{
throw new NotImplementedException();
}
public void Dispose()
{
//throw new NotImplementedException();
}
}
• ایجاد یک کلاس UserRepository و پیادهسازی آن :

public class UserRepository<T> where T : IdentityUser
{
private readonly DatabaseContext _databaseContext;
public UserRepository(DatabaseContext databaseContext)
{
_databaseContext = databaseContext;
}
internal T GeTByName(string userName)
{
var user = _databaseContext.AspNetUsers.SingleOrDefault(u => u.UserName == userName);
if (user != null)
{
T result = (T)Activator.CreateInstance(typeof(T));
result.Id = user.Id;
result.UserName = user.UserName;
result.PasswordHash = user.PasswordHash;
result.SecurityStamp = user.SecurityStamp;
result.Email = result.Email;
result.EmailConfirmed = user.EmailConfirmed;
result.PhoneNumber = user.PhoneNumber;
result.PhoneNumberConfirmed = user.PhoneNumberConfirmed;
result.LockoutEnabled = user.LockoutEnabled;
result.LockoutEndDateUtc = user.LockoutEndDateUtc;
result.AccessFailedCount = user.AccessFailedCount;
return result;
}
return null;
}
internal T GeTByEmail(string email)
{
var user = _databaseContext.AspNetUsers.SingleOrDefault(u => u.Email == email);
if (user != null)
{
T result = (T)Activator.CreateInstance(typeof(T));
result.Id = user.Id;
result.UserName = user.UserName;
result.PasswordHash = user.PasswordHash;
result.SecurityStamp = user.SecurityStamp;
result.Email = result.Email;
result.EmailConfirmed = user.EmailConfirmed;
result.PhoneNumber = user.PhoneNumber;
result.PhoneNumberConfirmed = user.PhoneNumberConfirmed;
result.LockoutEnabled = user.LockoutEnabled;
result.LockoutEndDateUtc = user.LockoutEndDateUtc;
result.AccessFailedCount = user.AccessFailedCount;
return result;
}
return null;
}
internal int Insert(T user)
{
_databaseContext.AspNetUsers.Add(new AspNetUsers
{
Id = user.Id,
UserName = user.UserName,
PasswordHash = user.PasswordHash,
SecurityStamp = user.SecurityStamp,
Email = user.Email,
EmailConfirmed = user.EmailConfirmed,
PhoneNumber = user.PhoneNumber,
PhoneNumberConfirmed = user.PhoneNumberConfirmed,
LockoutEnabled = user.LockoutEnabled,
LockoutEndDateUtc = user.LockoutEndDateUtc,
AccessFailedCount = user.AccessFailedCount
});
return _databaseContext.SaveChanges();
}
/// <summary>
/// Returns an T given the user’s id
/// </summary>
/// <param name=”userId”>The user’s id</param>
/// <returns></returns>
public T GeTById(string userId)
{
var user = _databaseContext.AspNetUsers.Find(userId);
T result = (T)Activator.CreateInstance(typeof(T));
result.Id = user.Id;
result.UserName = user.UserName;
result.PasswordHash = user.PasswordHash;
result.SecurityStamp = user.SecurityStamp;
result.Email = result.Email;
result.EmailConfirmed = user.EmailConfirmed;
result.PhoneNumber = user.PhoneNumber;
result.PhoneNumberConfirmed = user.PhoneNumberConfirmed;
result.LockoutEnabled = user.LockoutEnabled;
result.LockoutEndDateUtc = user.LockoutEndDateUtc;
result.AccessFailedCount = user.AccessFailedCount;
return result;
}
/// <summary>
/// Return the user’s password hash
/// </summary>
/// <param name=”userId”>The user’s id</param>
/// <returns></returns>
public string GetPasswordHash(string userId)
{
var user = _databaseContext.AspNetUsers.FirstOrDefault(u => u.Id == userId);
var passHash = user != null ? user.PasswordHash : null;
return passHash;
}
/// <summary>
/// Updates a user in the Users table
/// </summary>
/// <param name=”user”></param>
/// <returns></returns>
public int Update(T user)
{
var result = _databaseContext.AspNetUsers.FirstOrDefault(u => u.Id == user.Id);
if (result != null)
{
result.UserName = user.UserName;
result.PasswordHash = user.PasswordHash;
result.SecurityStamp = user.SecurityStamp;
result.Email = result.Email;
result.EmailConfirmed = user.EmailConfirmed;
result.PhoneNumber = user.PhoneNumber;
result.PhoneNumberConfirmed = user.PhoneNumberConfirmed;
result.LockoutEnabled = user.LockoutEnabled;
result.LockoutEndDateUtc = user.LockoutEndDateUtc;
result.AccessFailedCount = user.AccessFailedCount;
return _databaseContext.SaveChanges();
}
return 0;
}
}
• ایجاد یک کلاس UserRolesRepository و پیاده سازی آن :

حال ، برنامه ما برای استفاده از IdentityLibrary آماده است .
آموزش asp.net mvc
- ASP.net MVC
- 4k بازدید
- 10 تشکر