我正在遇到一个特殊的问题,正在使用我正在处理的解决方案。它使用ASP.NET身份系统与我构建的自定义实现,该系统可以与现有数据一起使用。直到昨天,它运行良好,但是以某种方式我无法登录。据我所知,看起来密码HASHER在每个请求上都会产生不同的哈希,而其中的hash均与数据库中存储的哈希匹配。
我做错了什么使这种情况发生的?不确定这是否重要,但是我正在研究我从办公室计算机下载的解决方案的本地副本,因为RDP变得烦人。它确实在本地工作了,但是我认为当我将数据库种子从基于对象的播种更改为直接SQL脚本时,它停止了。不确定为什么考虑我插入相同的值,为什么这会使它不起作用,但是我在这里无法进行身份验证。
update
我正在使用的UserManager
通过ninjects在我的UserStore
实例中传递。这是我的UserStore
的代码:
public class EmployeeStore : IQueryableUserStore<Employee, int>, IUserStore<Employee, int>, IUserPasswordStore<Employee, int>, IUserRoleStore<Employee, int>, IDisposable {
private bool Disposed;
private IDatabaseRepository<Role> RolesRepository { get; set; }
private IDatabaseRepository<Employee> EmployeesRepository { get; set; }
public EmployeeStore(
IDatabaseRepository<Role> rolesRepository,
IDatabaseRepository<Employee> employeesRepository) {
this.RolesRepository = rolesRepository;
this.EmployeesRepository = employeesRepository;
}
#region IQueryableUserStore Members
public IQueryable<Employee> Users {
get {
return this.EmployeesRepository.Set;
}
}
#endregion
#region IUserStore Members
public async Task CreateAsync(
Employee employee) {
this.ThrowIfDisposed();
if (employee == null) {
throw new ArgumentNullException("employee");
}
await this.EmployeesRepository.AddAndCommitAsync(employee);
}
public async Task DeleteAsync(
Employee employee) {
this.ThrowIfDisposed();
if (employee == null) {
throw new ArgumentNullException("employee");
}
await this.EmployeesRepository.RemoveAndCommitAsync(employee);
}
public Task<Employee> FindByIdAsync(
int employeeId) {
this.ThrowIfDisposed();
return Task.FromResult<Employee>(this.EmployeesRepository.FindSingleOrDefault(
u =>
(u.Id == employeeId)));
}
public Task<Employee> FindByNameAsync(
string userName) {
this.ThrowIfDisposed();
return Task.FromResult<Employee>(this.EmployeesRepository.FindSingleOrDefault(
e =>
(e.UserName == userName)));
}
public async Task UpdateAsync(
Employee employee) {
this.ThrowIfDisposed();
if (employee == null) {
throw new ArgumentNullException("employee");
}
await this.EmployeesRepository.CommitAsync();
}
#endregion
#region IDisposable Members
public void Dispose() {
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(
bool disposing) {
this.Disposed = true;
}
private void ThrowIfDisposed() {
if (this.Disposed) {
throw new ObjectDisposedException(base.GetType().Name);
}
}
#endregion
#region IUserPasswordStore Members
public Task<string> GetPasswordHashAsync(
Employee employee) {
this.ThrowIfDisposed();
if (employee == null) {
throw new ArgumentNullException("employee");
}
return Task.FromResult<string>(employee.PasswordHash);
}
public Task<bool> HasPasswordAsync(
Employee employee) {
return Task.FromResult<bool>(!String.IsNullOrEmpty(employee.PasswordHash));
}
public Task SetPasswordHashAsync(
Employee employee,
string passwordHash) {
this.ThrowIfDisposed();
if (employee == null) {
throw new ArgumentNullException("employee");
}
employee.PasswordHash = passwordHash;
return Task.FromResult<int>(0);
}
#endregion
#region IUserRoleStore Members
public Task AddToRoleAsync(
Employee employee,
string roleName) {
this.ThrowIfDisposed();
if (employee == null) {
throw new ArgumentNullException("employee");
}
if (String.IsNullOrEmpty(roleName)) {
throw new ArgumentNullException("roleName");
}
Role role = this.RolesRepository.FindSingleOrDefault(
r =>
(r.Name == roleName));
if (role == null) {
throw new InvalidOperationException("Role not found");
}
employee.Roles.Add(role);
return Task.FromResult<int>(0);
}
public Task<IList<string>> GetRolesAsync(
Employee employee) {
this.ThrowIfDisposed();
if (employee == null) {
throw new ArgumentNullException("employee");
}
return Task.FromResult<IList<string>>(employee.Roles.Select(
r =>
r.Name).ToList());
}
public Task<bool> IsInRoleAsync(
Employee employee,
string roleName) {
this.ThrowIfDisposed();
if (employee == null) {
throw new ArgumentNullException("employee");
}
if (String.IsNullOrEmpty(roleName)) {
throw new ArgumentNullException("roleName");
}
return Task.FromResult<bool>(employee.Roles.Any(
r =>
(r.Name == roleName)));
}
public Task RemoveFromRoleAsync(
Employee employee,
string roleName) {
this.ThrowIfDisposed();
if (employee == null) {
throw new ArgumentNullException("employee");
}
if (String.IsNullOrEmpty(roleName)) {
throw new ArgumentNullException("roleName");
}
Role role = this.RolesRepository.FindSingleOrDefault(
r =>
(r.Name == roleName));
if (role == null) {
throw new InvalidOperationException("Role is null");
}
employee.Roles.Remove(role);
return Task.FromResult<int>(0);
}
#endregion
}
这是我的登录控制器:
public sealed class SiteController : BaseController {
private IAuthenticationManager AuthenticationManager {
get {
return this.HttpContext.GetOwinContext().Authentication;
}
}
private UserManager<Employee, int> EmployeeManager { get; set; }
public SiteController(
UserManager<Employee, int> employeeManager) {
this.EmployeeManager = employeeManager;
}
[HttpGet, AllowAnonymous]
public ActionResult Default() {
return base.View();
}
[HttpPost, AllowAnonymous, ValidateAntiForgeryToken]
public async Task<RedirectToRouteResult> Default(
[Bind(Prefix = "Credentials", Include = "Email,Password")] Credentials credentials) {
if (this.ModelState.IsValid) {
Employee employee = await EmployeeManager.FindAsync(credentials.Email, credentials.Password);
if (employee != null) {
ClaimsIdentity identityClaim = await this.EmployeeManager.CreateIdentityAsync(employee, DefaultAuthenticationTypes.ApplicationCookie);
if (identityClaim != null) {
AuthenticationManager.SignIn(new AuthenticationProperties(), identityClaim);
return base.RedirectToAction("Dashboard");
}
}
}
return base.RedirectToAction("Default");
}
[HttpGet]
public RedirectToRouteResult SignOut() {
this.AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
return base.RedirectToAction("Default");
}
}
就机器键而言,是的,当我将解决方案复制到家用计算机中时,它确实发生了变化。话虽这么说,我将其从一台Windows 7机器带到另一台Windows 7机器,但我从未在任何配置文件中指定机器键,因此在这两台机器上都应相同的行为。至于盐,我认为我不会在任何地方设置它。我只有三到四天的ASP.NET身份实现,因此可能不完整。
好吧,这真的很愚蠢。该问题是由实体框架引起的,因为我选择在数据库初始化器中执行SQL脚本,因为我有很多语句,并且不想编写对象初始化等效词,因此我选择执行SQL脚本。事实证明,即使在其中有正确的数据,由于EF没有创建并缓存对象,它仍然会一直返回nulls。它甚至没有尝试出去DB并检查数据是否存在。
因此,学习的课程:不要使用ExecuteSqlCommand
将数据播种到初始化器上的数据库中。浪费了整整一天,我欣喜若狂!