امن سازی برنامههای ASP.NET Core توسط IdentityServer 4x - قسمت دهم- ذخیره سازی اطلاعات کاربران IDP در بانک اطلاعاتی
نویسنده: وحید نصیری
تاریخ: ۱۳۹۷/۰۶/۲۲ ۱۹:۲۵
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
namespace DNT.IDP.DomainClasses
{
public class User
{
[Key]
[MaxLength(50)]
public string SubjectId { get; set; }
[MaxLength(100)]
[Required]
public string Username { get; set; }
[MaxLength(100)]
public string Password { get; set; }
[Required]
public bool IsActive { get; set; }
public ICollection<UserClaim> UserClaims { get; set; }
public ICollection<UserLogin> UserLogins { get; set; }
}
} namespace DNT.IDP.DomainClasses
{
public class UserClaim
{
public int Id { get; set; }
[MaxLength(50)]
[Required]
public string SubjectId { get; set; }
public User User { get; set; }
[Required]
[MaxLength(250)]
public string ClaimType { get; set; }
[Required]
[MaxLength(250)]
public string ClaimValue { get; set; }
}
} namespace DNT.IDP.DomainClasses
{
public class UserLogin
{
public int Id { get; set; }
[MaxLength(50)]
[Required]
public string SubjectId { get; set; }
public User User { get; set; }
[Required]
[MaxLength(250)]
public string LoginProvider { get; set; }
[Required]
[MaxLength(250)]
public string ProviderKey { get; set; }
}
} public interface IUsersService
{
Task<bool> AreUserCredentialsValidAsync(string username, string password);
Task<User> GetUserByEmailAsync(string email);
Task<User> GetUserByProviderAsync(string loginProvider, string providerKey);
Task<User> GetUserBySubjectIdAsync(string subjectId);
Task<User> GetUserByUsernameAsync(string username);
Task<IEnumerable<UserClaim>> GetUserClaimsBySubjectIdAsync(string subjectId);
Task<IEnumerable<UserLogin>> GetUserLoginsBySubjectIdAsync(string subjectId);
Task<bool> IsUserActiveAsync(string subjectId);
Task AddUserAsync(User user);
Task AddUserLoginAsync(string subjectId, string loginProvider, string providerKey);
Task AddUserClaimAsync(string subjectId, string claimType, string claimValue);
} @using DNT.IDP.Controllers.Account; @using DNT.IDP.Controllers.Consent; @using DNT.IDP.Controllers.Grants; @using DNT.IDP.Controllers.Home; @using DNT.IDP.Controllers.Diagnostics; @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
public static class IdentityServerBuilderExtensions
{
public static IIdentityServerBuilder AddTestUsers(this IIdentityServerBuilder builder, List<TestUser> users)
{
builder.Services.AddSingleton(new TestUserStore(users));
builder.AddProfileService<TestUserProfileService>();
builder.AddResourceOwnerValidator<TestUserResourceOwnerPasswordValidator>();
return builder;
}
} using DNT.IDP.Services;
using Microsoft.Extensions.DependencyInjection;
namespace DNT.IDP
{
public static class IdentityServerBuilderExtensions
{
public static IIdentityServerBuilder AddCustomUserStore(this IIdentityServerBuilder builder)
{
// builder.Services.AddScoped<IUsersService, UsersService>();
builder.AddProfileService<CustomUserProfileService>();
return builder;
}
}
} namespace DNT.IDP.Services
{
public class CustomUserProfileService : IProfileService
{
private readonly IUsersService _usersService;
public CustomUserProfileService(IUsersService usersService)
{
_usersService = usersService;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var subjectId = context.Subject.GetSubjectId();
var claimsForUser = await _usersService.GetUserClaimsBySubjectIdAsync(subjectId);
context.IssuedClaims = claimsForUser.Select(c => new Claim(c.ClaimType, c.ClaimValue)).ToList();
}
public async Task IsActiveAsync(IsActiveContext context)
{
var subjectId = context.Subject.GetSubjectId();
context.IsActive = await _usersService.IsUserActiveAsync(subjectId);
}
}
} namespace DNT.IDP
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddCustomUserStore()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients()); public AccountController(
IIdentityServerInteractionService interaction,
IClientStore clientStore,
IAuthenticationSchemeProvider schemeProvider,
IEventService events,
TestUserStore users = null)
{
_users = users ?? new TestUserStore(TestUsers.Users);
_interaction = interaction;
_clientStore = clientStore;
_schemeProvider = schemeProvider;
_events = events;
} private readonly TestUserStore _users;
private readonly IUsersService _usersService;
public AccountController(
// ...
IUsersService usersService)
{
_usersService = usersService;
// ...
} public async Task<IActionResult> Login(LoginInputModel model, string button)
{
//...
if (ModelState.IsValid)
{
if (await _usersService.AreUserCredentialsValidAsync(model.Username, model.Password))
{
var user = await _usersService.GetUserByUsernameAsync(model.Username); public class RegisterUserViewModel
{
// credentials
[MaxLength(100)]
public string Username { get; set; }
[MaxLength(100)]
public string Password { get; set; } public class RegisterUserViewModel
{
// ...
// claims
[Required]
[MaxLength(100)]
public string Firstname { get; set; }
[Required]
[MaxLength(100)]
public string Lastname { get; set; }
[Required]
[MaxLength(150)]
public string Email { get; set; }
[Required]
[MaxLength(200)]
public string Address { get; set; }
[Required]
[MaxLength(2)]
public string Country { get; set; } varuserToCreate=newUser
{
Password=model.Password.GetSha256Hash(),
Username=model.Username,
IsActive=true
};
userToCreate.UserClaims.Add(newUserClaim("country",model.Country));
userToCreate.UserClaims.Add(newUserClaim("address",model.Address));
userToCreate.UserClaims.Add(newUserClaim("given_name",model.Firstname));
userToCreate.UserClaims.Add(newUserClaim("family_name",model.Lastname));
userToCreate.UserClaims.Add(newUserClaim("email",model.Email));
userToCreate.UserClaims.Add(newUserClaim("subscriptionlevel","FreeUser"));
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var subjectId = context.Subject.GetSubjectId();
var claimsForUser = await _usersService.GetUserClaimsBySubjectIdAsync(subjectId).Select(c => new Claim(c.ClaimType, c.ClaimValue)).ToList();
context.AddRequestedClaims(claimsForUser );
} php, oracle adf, asp.net web forms, asp.net mvc, ...
// continue with the flow
if (_interaction.IsValidReturnUrl(model.ReturnUrl) || Url.IsLocalUrl(model.ReturnUrl))
{
return Redirect(model.ReturnUrl);
}