I have an ASP.NET webforms website that uses the .NET MySql connector and MySql as a back-end. I'm using role-based authentication to protect certain areas of my site. The problem is that the user's role information is not being persisted after I move my site to the server (works fine on my local development machine). What is happening is that I can login using the logincontrol which directs me to the admin area after authenticating the user. At this point User.IsInRole("admin") is true. But when I click a link to go to a different page in the admin section User.IsInRole("admin") is false.
Web.config
<membership defaultProvider="MySqlMembershipProvider" userIsOnlineTimeWindow="15">
<providers>
<remove name="MySQLMembershipProvider"/>
<add name="MySQLMembershipProvider" type="MySql.Web.Security.MySQLMembershipProvider, MySql.Web, Version=6.2.2.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" connectionStringName="LocalMySqlServer" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" applicationName="/" requiresUniqueEmail="true" passwordFormat="Clear" maxInvalidPasswordAttempts="3" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="1" passwordAttemptWindow="3" passwordStrengthRegularExpression="" autogenerateschema="true"/>
</providers>
</membership>
<profile>
<providers>
<remove name="MySQLProfileProvider"/>
<add name="MySQLProfileProvider" type="MySql.Web.Profile.MySQLProfileProvider, MySql.Web, Version=6.2.2.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" connectionStringName="LocalMySqlServer" applicationName="/"/>
</providers>
</profile>
<roleManager enabled="true" defaultProvider="MySqlRoleProvider">
<providers>
<remove name="MySqlRoleProvider"/>
<add name="MySqlRoleProvider" type="MySql.Web.Security.MySQLRoleProvider, MySql.Web, Version=6.2.2.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" connectionStringName="LocalMySqlServer" applicationName="/"/>
</providers>
</roleManager>
Global.asax
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if (HttpContext.Current.User != null) {
if (Request.IsAuthenticated == true) {
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(Context.Request.Cookies[FormsAuthentication.FormsCookieName].Value);
// In this case, ticket.UserData = "Admin"
string[] roles = new string[1] { ticket.UserData };
FormsIdentity id = new FormsIdentity(ticket);
Context.User = new System.Security.Principal.GenericPrincipal(id, roles);
}
}
}
Are you using different data sources in development and on the server (I do)? If so, make sure your data is in sync. This is likely the case only if you specify (local) or . as the server in your database connection.
Otherwise, output to a log to see if the user roles ever contain "admin".
It turns out the problem was that I had disabled viewstate across the entire site in my web.config. Once I re-enabled viewstate the role information seemed to persist as expected.
Related
I have 2 applications (MVC) like this :
Website
and
Admininistration
In each of them, I'm using asp.net membership provider (using mysql) like this :
Website web.config
<roleManager enabled="true" defaultProvider="MySQLRoleProvider">
<providers>
<clear />
<add name="MySQLRoleProvider" type="MySql.Web.Security.MySQLRoleProvider, MySql.Web, Version=6.8.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" connectionStringName="mySqlConnectionString" applicationName="Website" />
</providers>
</roleManager>
<membership defaultProvider="MySQLMembershipProvider" hashAlgorithmType="SHA1">
<providers>
<clear />
<add name="MySQLMembershipProvider" autogenerateschema="false"
type="MySql.Web.Security.MySQLMembershipProvider, MySql.Web, Version=6.8.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"
connectionStringName="mySqlConnectionString"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
applicationName="Website"
requiresUniqueEmail="true"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="25"
minRequiredPasswordLength="6"
minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10"
passwordStrengthRegularExpression="" />
</providers>
</membership>
Adminitration web.config
<roleManager enabled="true" defaultProvider="MySQLRoleProvider">
<providers>
<clear />
<add name="MySQLRoleProvider" type="MySql.Web.Security.MySQLRoleProvider, MySql.Web, Version=6.8.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" connectionStringName="mySqlConnectionString" applicationName="Administration" />
</providers>
</roleManager>
<membership defaultProvider="MySQLMembershipProvider" hashAlgorithmType="SHA1">
<providers>
<clear />
<add name="MySQLMembershipProvider" autogenerateschema="true" type="MySql.Web.Security.MySQLMembershipProvider, MySql.Web, Version=6.8.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" connectionStringName="mySqlConnectionString" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" applicationName="Glocalapps" requiresUniqueEmail="true" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" />
</providers>
</membership>
<profile defaultProvider="MySqlProfileProvider">
<providers>
<clear />
<add name="MySQLProfileProvider" type="MySql.Web.Profile.MySQLProfileProvider, MySql.Web, Version=6.8.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" connectionStringName="mySqlConnectionString" applicationName="Administration" />
</providers>
</profile>
Both use same connection string.
Everything works without a problem, I can register and login on both sites and users are created perfectly within it's own application.
I'm trying to implement a Create User from the Administration web application for the Website application like this :
Membership.ApplicationName = "Website";
var membership = Membership.CreateUser(username, password);
this does create the user without a problem, but if I try to log in from the website application, it returns a password error. I did testing and this is indeed a password error. (if i copy another hash/salt from other user created on the website I can then login with this new created user, so the user is created OK, but for some reason the password is not recognized when the user is created from the Administration application)
Anyone has already faced this problem or have any idea on why is not working ?
The problem was that on one config I have this :
<membership defaultProvider="MySQLMembershipProvider" hashAlgorithmType="SHA1">
while the other application
<membership defaultProvider="MySQLMembershipProvider">
adding the hashAlgorithType solved the issue. Application name CAN be changed on runtime.
When i'm trying to get to Web Site Administration Tool (WAT) (Project->ASP.NET Configuration in Visual Studio) i get following error
You must call the "WebSecurity.InitializeDatabaseConnection" method before you call any other >method of the "WebSecurity" class. This call should be placed in an _AppStart.cshtml file in >the root of your site.
And this is my connection string:
<add name="DefaultConnection" connectionString="Data Source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|Database1.mdf;User Instance=true" providerName="System.Data.SqlClient" />
I've also enabled simple membership
<add key="enableSimpleMembership" value="true" />
My roleshipprivider config looks like this
<roleManager enabled="true" defaultProvider="MySqlRoleProvider">
<providers>
<clear />
<add connectionStringName="DefaultConnection" applicationName="/"
name="MySqlRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData" />
</providers>
</roleManager>
And my membership conf
<membership defaultProvider="MyOwnSqlMembershipProvider">
<providers>
<clear/>
<add connectionStringName="DefaultConnection" enablePasswordRetrieval="false"
enablePasswordReset="true" requiresQuestionAndAnswer="false"
requiresUniqueEmail="true" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6"
minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
name="MyOwnSqlMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
Does anybody know where's the bug?
Thanks in advance, Mateusz Urban
You should add the code below to Global.aspx.cs inside protected void Application_Start() and should appear at the top before any other registrations. This way, it will always be Initialized before an other operations.
if (!WebSecurity.Initialized)
WebSecurity.InitializeDatabaseConnection("DefaultConnection",
"UserProfile", "UserId", "UserName", autoCreateTables: true);
You need to include code to actually initialize the membership provider. The following in _AppStart.cshtml should work:
#{
if (!WebSecurity.Initialized)
{
WebSecurity.InitializeDatabaseConnection("dbContext", "Users", "Id", "Login", autoCreateTables: false);
}
}
I'm getting this error:
Line 246: <roleManager>
Line 247: <providers>
Line 248: <add name="AspNetSqlRoleProvider" connectionStringName="LocalSqlServer" applicationName="/" type="System.Web.Security.SqlRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
Line 249: <add name="AspNetWindowsTokenRoleProvider" applicationName="/" type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
Line 250: </providers>
Source File: C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config Line: 248
However, it shouldn't be as we're not using the aspnetroleprovider. But it's in the machine.config. Other sites don't have this problem. What could be making it pick up the aspnetsqlroleprovider?
fix
add enableSimpleMembership with value false app setting to your web.config.
cause
<roleManager enabled="false" />
will cause Roles.Enabled flag to be set to false, as expected,
but there is 'WebMatrix.WebData.WebSecurity' that says:
internal static void PreAppStartInit()
{
if (!ConfigUtil.SimpleMembershipEnabled)
return;
...
Roles.Enabled = true;
const string BuiltInRolesProviderName = "AspNetSqlRoleProvider";
var builtInRoles = Roles.Providers[BuiltInRolesProviderName];
if (builtInRoles != null)
{
var simpleRoles = CreateDefaultSimpleRoleProvider(BuiltInRolesProviderName, currentDefault: builtInRoles);
Roles.Providers.Remove(BuiltInRolesProviderName);
Roles.Providers.Add(simpleRoles);
}
...
}
this will override roleManager setting (this code is executed before RoleManager module is), including adding AspNetSqlRoleProvider
to disable 'SimpleMembership' you can add app setting enableSimpleMembership with value="false" (web.config):
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings>
<add key="enableSimpleMembership" value="false" />
</appSettings>
</configuration>
this will prevent webmatrix from reconfiguring RoleManager.
Add the <clear/> to your web.config's section of role providers. On this way you avoid inheriting if you don't use one. You should add it also for Membership and Profile providers section.
<roleManager>
<providers>
<clear/>
</providers>
....
Edit: Maybe you need to remove it explicitely:
<roleManager>
<providers>
<clear/>
<remove name="AspNetSqlRoleProvider" />
Another try:
Disable the role provider:
<system.web>
<roleManager enabled="false" />
</system.web>
http://msdn.microsoft.com/en-us/library/ms998314.aspx#paght000013_step2
This is my first attempt at doing roles for asp.net, what I have is a mySQL backend, and I want to add a bunch of roles to a user. The code i'm using below, i keep getting the error Unable to connect to SQL Server database. I'm assuming this is because the default provider refers to SQL, but i'm not able to figure out how to switch it so I can add multiple roles to a user. Thanks for the help!
using (MySqlConnection cn2 = new MySqlConnection("Server=localhost;Database=users; User=root;Password=PASSWORD;"))
{
cn2.Open();
MySqlCommand cmd2 = new MySqlCommand(storedProcedureName2, cn);
cmd2.CommandType = CommandType.StoredProcedure;
cmd2.Parameters.Add("#usernameID", userID);
MySqlDataReader dr2 = cmd2.ExecuteReader();
while (dr2.Read())
{
string roleName = dr2["role"].ToString();
Roles.AddUserToRole(userID, roleName);
}
}
You can configure the ASP.NET Membership and roles in the web.config file. Something like this would set your default provider to a MySQL backend:
<membership defaultProvider="MySqlMembershipProvider">
<providers>
<clear />
<add name="MySqlMembershipProvider" type="MySql.Web.Security.MySqlMembershipProvider,M ySql.Web,Version=6.3.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" autogenerateschema="true" connectionStringName="LocalMySqlServer" enablePasswordRetrieval="false" enablePasswordReset="true" requireQuestionAndAnswer="false" requireUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="0" passwordStrengthRegularExpression="" applicationName="/" />
</providers>
</membership>
<profile defaultProvider="MySqlProfileProvider">
<providers>
<clear/>
<add name="MySqlProfileProvider" type="MySql.Web.Profile.MySQLProfileProvider, MySql.Web, Version=6.3.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" conectionStringName="LocalMySqlServer" applicationName="/"/>
</providers>
</profile>
<roleManager enabled="true" defaultProvider="MySqlRoleProvider">
<providers>
<clear/>
<add connectionStringName="LocalMySqlServer" applicationName="/" name="MySqlRoleProvider"
type="MySql.Web.Security.MySQLRoleProvider, MySql.Web, Version=6.3.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"/>
</providers>
</roleManager>
<trust level="Full"/>
<machineKey validationKey="AutoGenerate" validation="SHA1"/>
EDIT: I added the connectionStrings section below:
<connectionStrings>
<remove name="LocalMySqlServer"/>
<add name="LocalMySqlServer" connectionString="Server=localhost;Database=users; User=root;Password=PASSWORD;" providerName="MySql.Data.MySqlClient"/>
</connectionStrings>
Try the following as the connection string:
"Server=localhost;Port=3306;Database=users;Uid=root;Pwd=PASSWORD;"
And if it works, change the password :)
If this doesn't work, and assuming the error is in the connecting ot the database (you confused my by publishing so many lines of code) do the usual checks:
Is the server running?
Is the password correct
Is the port default (3306)
Are there internal firewall issues, as MySQL uses TCP:3306 and in theory firewall can block this.
when i want to use ResetPassword method in vb.net or c# , it can not reset password and make an exeption that say : "The password-answer supplied is wrong".
i think it is caused by hashing system and machine code of hash and salt.
how can i solve this problem ?
add following attribute to your membership cofig section in your Web.Config file.
requiresQuestionAndAnswer="false"
full example
<configuration>
<connectionStrings>
<add name="SqlServices"
connectionString="Data Source=MySqlServer;Integrated Security=SSPI;Initial
Catalog=aspnetdb;" />
</connectionStrings>
<system.web>
<membership
defaultProvider="SqlProvider"
userIsOnlineTimeWindow="20">
<providers>
<remove name="AspNetSqlProvider" />
<add name="SqlProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="SqlServices"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
passwordFormat="Hashed"
applicationName="/" />
</providers>
</membership>
</system.web>
</configuration>
I used it in a wrong way, and got the same error, hope helps you too. This is my code:
MembershipUser mu = Membership.GetUser(c.Username);
if (mu.PasswordQuestion == c.Question)
{
string pwd = mu.ResetPassword(c.Answer);
mu.ChangePassword(pwd, c.Password);
return RedirectToAction("SignIn");
}
else
{
ViewBag.Message = "Error!";
return View();
}