Reputation: 5480
I have an ASP.NET MVC 4 project which I have successfully connected to a MySQL database. I have done this by adding a ADO.NET/EntityFramework
class which created a Model.edmx
object.
Within the database, I have created a table called user
which holds what you should expect in a User table such as Email, UserName, Password, FirstName. etc etc.
I have created some dummy records and added the following code to the Login
method within the AccountController
:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var database = new Database();
user user = database.SelectByUserName(model.UserName).FirstOrDefault<user>();
var hash = Utilities.HashPassword(model.Password, user.Salt);
if (hash == user.Password && WebSecurity.Login(user.UserName, user.Password))
{
//Correct Login Details!
RedirectToAction("About", "Home");
}
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
For some reason, the WebSecurity.Login
method returns false and the user isn't redirected to the Home page.
Why is it returning false? What am I missing and how would the WebSecurity.Login
even know what credentials are required i.e. How does it even know that it should look inside the user
table which I created?
Upvotes: 2
Views: 5728
Reputation: 1344
WebSecurity doesn't default to looking at your database, it will actually make it's own tables using the DefaultConnection that is defined in Web.Config. To work around this you need to add a new connection string Web.Config and then during app initialization force WebSecurity to look at that connection.
The easiest way to accomplish this, assuming you have a MySQL specific connection string in your Web.Config named "AccountConnection" is by adding the following to your Application_Start()
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
And then you'll need the following fields and function:
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
Database.SetInitializer<UsersContext>(null);
try
{
using (var context = new UsersContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
// Overload is: Web.Config Connection string by name, user table name, user id column name, user name column name, auto create missing tables
WebSecurity.InitializeDatabaseConnection("AccountConnection", "UserProfile", "UserId", "Email", autoCreateTables: true);
}
catch (Exception ex)
{
throw new InvalidOperationException("The Membership database could not be initialized.", ex);
}
}
}
Whether you can make WebSecurity work with MySQL I have no idea, though I believe I've read some place that it is supported.
Note: the UserContext
should have been auto generated when you installed WebSecurity into your solution. If not it's a CodeFirst model that you can easily add.
Upvotes: 4
Reputation: 54628
There are one of two reasons your code will not work. Understand that WebSecurity and SimpleMembershipProvider (assuming you are using it) uses PBKDF2 algorithm to populate the password field when you call WebSecurity.CreateUserAndAccount or WebSecurity.CreateAccount.
So Either:
You did not use one of these two methods to create the user, in which case WebSecurity.Login will almost always fail (99.99%).
or
You did use one of the methods above and the code in Utilities.HashPassword()
(which seems redundant since the Create Account methods listed above hash passwords anyway...) does not hash the password Exactly the same way WebSecurity does so hash == user.Password
will always fail.
Upvotes: 2