I am using code that inherits SqlMembershipProvider, named MyMembershipClass so that I can make use of the functions.
I have created my inherited class and specified it in the Web.config file like so:
<membership defaultProvider="MyMembershipClass">
<providers>
<clear/>
<add name="MyMembershipClass" type="MyMembershipClass" applicationName="/"/>
</providers>
</membership>
Now that I have done that, to make use of the Membership functions, do I refer to it within my code as:
MyMembershipClass or just Membership?
EDIT:
If you refer to it at just Membership, is this due to defaultProvider="MyMembershipClass"?
Just as Membership. It will automatically map to your defined membership class. That enables to change the provider later without needing to change all of your code.
So you don't have to write:
MyMembershipClass.GetUser
but
Membership.GetUser
By the way, the same is true if you define a custom RoleProvider, for example:
Roles.AddUserToRole(userName, roleName);
Edit:
If you refer to it at just Membership, is this due to
defaultProvider="MyMembershipClass"?
Yes, that must be the name of your class that inherits from MembershipProvider (or another class inheriting from it like SqlMembershipProvider).
According to your second comment that you can define what you want even if it doesn't exist, i get an exeption if i name the provider "Bob" in web.config:
Exception information:
Exception type: ConfigurationErrorsException
Exception message: Default Membership Provider could not be found.
Just Membership. The static methods on Membership will call the methods on your provider.
Related
I have an ASP.NET MVC 5 application. I'm using the standard ASP.NET Identity provider for user and role management. It is important that I'm using the IdentityUser from an own repository project, but this seems ok. I can register, login, edit users, and manage their roles.
I add user to Role with these lines:
UserManager.AddToRole(userdetail.Id, r);
db.Entry(userdetail).State = EntityState.Modified;
db.SaveChanges();
This seems working in DB level.
But, I can't use Role based authentications, actually the simples
HttpContext.User.IsInRole("Administrator")
doesn't working too.
[Authorize(Roles="Administrator")]
doesn't working too.
I can check only with this method, whether user is an administrator:
UserManager.IsInRole(userID, "Administrator").
Why?
In every tutorial what I found, everything works fine. The different project repository could be the reason? Or ASP.NET Identity is broken so much?
Please advice,
There seems to be an issue. [The issue by design]
The role names are case sensitive in AuthorizeAttribute and User.IsInRole
The role names are case insensitive in UserManager.IsInRole
Moreover, check for the correct role name is used for the verification.
[The above is based on the test performed with below code. Role Name="Admin", User is added to Role "Admin".]
[Authorize(Roles="Admin")] /*True as "Admin" has A capital as entered in Role name*/
public ActionResult Secured()
{
if (User.IsInRole("admin")) /*This is False*/
{
Console.WriteLine("In");
}
if(UserManager.IsInRole(User.Identity.GetUserId(), "admin")) /*This is True!!*/
{
Console.WriteLine("In");
}
return View();
}
If we change the attribute to [Authorize(Roles="admin")], it redirects to Login page.
In that case you need to logout and login the user again.
Because the roles data is also stored in cookies,
So you must issue the cookie again to work it.
Do you have this entry in your web.config?
<roleManager enabled="true">
<providers>
<clear />
<add connectionStringName="ApplicationServices" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" applicationName="/" />
</providers>
</roleManager>
Also, if I remember correctly, there is a different namespace for the role provider assembly in different versions of .NET.
I was using IsInRoleAsync in Asp.Net core and in my case the problem was that I had ignored the role's normalized name when I created it. Therefore, after updating the normalized name for the role everything worked properly.
I am using Asp.Net/C# in my application , I am using Asp.Net built-in membership framework .The installation of aspnet_regsql services have been properly installed on my database.The aspnet_users table however contains basic information about the user , How do I add additional information about a user.Should I modify the table itself or should I use another table and link it with aspnet_users table.Also the Membership.ValidateUser(username,password) works well , but I have a requirement where the login is based on the user code.How can I achieve this , is it possible with built-in Membership.
Any suggestions are most welcome.
Thanks
Use an ASP.NET Profile-Provider instead.
https://web.archive.org/web/20211020111657/https://www.4guysfromrolla.com/articles/101106-1.aspx
You can store any kind of additional information even binary(images).
I've used The SqlProfileProvide myself in my current application to let the user himself select his startpage.
Therefor i just needed to add this to the web.config:
<profile defaultProvider="AspNetSqlProfileProvider">
<providers>
<clear/>
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="RM2ConnectionString" applicationName="/ERP"/>
</providers>
<properties>
<add name="Startpage"/>
</properties>
</profile>
And i could write this property in codebehind:
if(User.Identity.IsAuthenticated)
{
HttpContext.Current.Profile.SetPropertyValue("Startpage", startPage); //startPage is a String
HttpContext.Current.Profile.Save();
}
and read it in the following way:
if(User.Identity.IsAuthenticated)
{
Dim user = Membership.GetUser();
Dim startPage = HttpContext.Current.Profile.GetPropertyValue("Startpage") as String;
}
You can store anything you want, see the link above for further informations.
You can use the ProfileProvider (ref).
More info here: http://msdn.microsoft.com/en-us/library/2y3fs9xs.aspx
And here: How to assign Profile values?
You could create a custom membership provider by inheriting from System.Web.Security.MembershipProvider - this way you can implement any additional functionality you need. You can then store the user details in your own table structure etc. You'd then point your web.config at your custom provider to use it.
Useful links:
http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx
http://www.asp.net/web-forms/videos/how-do-i/how-do-i-create-a-custom-membership-provider
http://www.devx.com/asp/Article/29256
I am using an email address as my "username" for Login. When a user logs in the User object that is created has the Email address as the name which is incorrect. The actual name is another field in the DB. How do I login and authenticate against the email address and then load the correct name in the User object?
I am using forms authentication with a custom MembershipProvider and RoleProvider.
Edits Below to Clarify
I have a custom MembershipProvider that validates users by email address and password. It is called by the basic Login Control and registered in web.config.
<asp:Login ID="AdminLogin" runat="server" MembershipProvider="AdminMembershipProvider">
</asp:Login>
Web.Config:
<authentication mode="Forms">
<forms loginUrl="Default.aspx" />
</authentication>
<membership defaultProvider="AdminMembershipProvider">
<providers>
<clear />
<add name="AdminMembershipProvider"
type="AdminMembershipProvider"
connectionStringName="EvalSysConnectionString"
/>
</providers>
</membership>
With just this my users are logged in correctly. However it returns a Context.User.Identity.Name of the email address. I have the first name and last name stored in the DB and want this to be the Name.
I read various posts that seem to indicate that I would have to create a Global.asax file and override the PostAutheticateRequest method to do this. However I have no idea how to proceed with this strategy.
<%# Application Language="C#" %>
<script runat="server">
protected void Application_PostAuthenticateRequest()
{
string test = HttpContext.Current.User.ToString();
}
</script>
I'm sorry my question was so vague. I'm so lost with this that I don't know how to write a good question.
I believe what you are asking is: Can I change the property Context.User.Identity.Name to display something other than the username?
EDIT
It is not possible using the implementation of the property Context.User.Identity.Name as it is read-only and is set to the username with no way to change it.
A quick and easy solution
You can write a method that calls a stored procedure (or query in your code) in your database to do a lookup based on the value in Context.User.Identity.Name and returns First and Last. You can store the result in a Session variable or use the Profile object (as noted below).
Alternate solution
You can write your own implementation of IIdentity. It's something I've never done, so I don't have any snippets to contribute. However this link should give you a place to start. I'd be careful with this solution since you lose your unique way of identifying a user unless you add an additional property to your implementation of IIdentity and make sure you cast Context.User.Identity, whenever referenced, to your own implementation.
Hope that helps.
I would do exactly what you have done so far and then store the users name, address and so on in the Profile object.
This is as easy as adding some configuration (web.config):
<profile>
<providers>
<clear />
<add name="SqlProvider"
type="System.Web.Profile.SqlProfileProvider"
connectionStringName="SqlServices"
applicationName="SampleApplication"
description="SqlProfileProvider for SampleApplication" />
</providers>
<properties>
<add name="Name" />
</properties>
</profile>
And then retrieve/set it like so:
txtName.Text = Profile.Name;
Profile.Name = txtName.Text;
You could definitely look into using a Profile provider like Jimmy suggested. Or, you could implement an IPrincipal and set the HttpContext.User property in your PostAuthenticateRequest event.
Basically, you just do something like
var userName = Database.GetUserName(httpContext);
httpContext.User = new GenericPrincipal(new GenericIdentity(userName, "FORMS"), new[] {"UserRole1"});
The first line is an example of a call to your db to get the username. The second line creates a principal and identity from this info then assigns it to the User property of the HttpContext
Dim username As String = Membership.GetUserNameByEmail(txtUsername.Text)
If (Membership.ValidateUser(username, txtPassword.Text)) Then
Here is some Vb code. that seems to retain the columns in the Membership Provider. Basically you allow a user to enter their email address which is unique and get their username using an email address. Then use the validation method to authenticate the user by their username and password.
What do you think guys.
I have multiple calls to Membership.GetUser() and can't seem to find anything built in to cope with this (without hitting the database multiple times).
I first looked into static variables before realising this was not suitable. I know I can use sessions but I would need to hash/encrypt the userID to make it safe, which is fine but I didn't want to do this without checking if there was a built in way to do this within the .net membership provider
Is there a built in way of remembering a value like the UserID and safely storing that for the current user?
I recommend using the Singleton-per-Request pattern which uses the HttpContext.Items property.
public class UserPerRequest
{
/// <summary>
/// Returns the result of Membership.GetUser(), but will cache the results within the
/// current request so it's only called once per request.
/// </summary>
public static MembershipUser Current
{
get
{
const string key = "UserPerRequest";
if (HttpContext.Current.Items[key] == null)
HttpContext.Current.Items[key] = Membership.GetUser();
return (MembershipUser)HttpContext.Current.Items[key];
}
}
}
So everywhere you'd call Membership.GetUser() just call UserPerRequest.Current instead. The only time you'll still get multiple calls to the database during a request is if Membership.GetUser() returns null.
Membership.GetUser() is an indirect call to the class MembershipProvider's method:
public abstract MembershipUser GetUser(string username, bool userIsOnline);
So, you can write a class that derives from the MembershipProvider you're using (for example SqlMembershipProvider or ActiveDirectoryMembershipProvider, or a custom one) and override this method using some clever cache mechanism.
Then you will need to change the web.config to declare this new MembershipProvider class:
<membership defaultProvider="MyProvider">
<providers>
<clear/>
<add name="MyProvider" type="...MyProvider" ... />
</providers>
</membership>
I'm implementing a custom membership provider, and everything seems to go swimmingly until I create a MembershipUser object. At that point, I receive the error:
The membership provider name specified
is invalid. Parameter name:
providerName
In web.config the membership key is
<membership defaultProvider="MembersProvider">
<providers>
<clear/>
<add name="MembersProvider" type="Members.Providers.MembersProvider" connectionStringName="ApplicationServices"
enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
applicationName="DeviceDatabase" />
</providers>
</membership>
When creating the MembershipUser object from my custom User class:
public static MembershipUser ToMembershipUser(User user)
{
MembershipUser member = new MembershipUser
("MembersProvider"
, user.Name
, user.Id
, user.EmailAddress
, user.PasswordQuestion
, user.Comment
, user.IsApproved
, user.IsLockedOut
, user.DateCreated
, user.LastLoginDate ?? DateTime.MinValue
, user.LastActivityDate ?? DateTime.MinValue
, user.LastPasswordChangedDate ?? DateTime.MinValue
, user.LastLockoutDate ?? DateTime.MinValue
);
return member;
}
(I realize I could probably just inherit my User class from MembershipUser, but it's already part of an existing class hierarchy. I honestly think this is the first time I've encountered a legitimate need for for multiple inheritance!)
My feeling is that the new MembershipUser(...) providerName parameter is supposed to match what's set in web.config, but, since they match already, I'm at a loss as to how to proceed.
Is there a convenient way to get the name of the active membership provider in code?
I'm starting to think that using the built-in membership system is overkill and more trouble than it's worth.
Edit
Not sure if it's relevant, but the custom membership provider class is in a class library, not the main WAP project.
Update
Here's the contents of the System.Web.Security.Membership.Provider object as show in the VS2010 command window:
>eval System.Web.Security.Membership.Provider
{Members.Providers.MembersProvider}
[Members.Providers.MembersProvider]: {Members.Providers.MembersProvider}
base {System.Configuration.Provider.ProviderBase}: {Members.Providers.MembersProvider}
ApplicationName: null
EnablePasswordReset: true
EnablePasswordRetrieval: false
MaxInvalidPasswordAttempts: 5
MinRequiredNonAlphanumericCharacters: 0
MinRequiredPasswordLength: 6
PasswordAttemptWindow: 10
PasswordFormat: Function evaluation was aborted.
PasswordStrengthRegularExpression: Cannot evaluate expression because debugging information has been optimized away .
RequiresQuestionAndAnswer: Cannot evaluate expression because debugging information has been optimized away .
RequiresUniqueEmail: Cannot evaluate expression because debugging information has been optimized away .
Update 2
This just randomly started working, which means I changed something but can't remember what it was. Stupid brain. I'll accept the only answer that's been posted and update this if I figure out what the problem was.
I used Membership.Provider.Name to get the correct name parameter
public static MembershipUser GetUserFromEntity(this UserEntity userEntity)
{
return new MembershipUser(
Membership.Provider.Name,
userEntity.Username,
userEntity.PartitionKey,
userEntity.Email,
userEntity.PasswordQuestion,
userEntity.Comment,
userEntity.IsApproved,
userEntity.IsLockedOut,
userEntity.CreationDate,
userEntity.LastLoginDate,
userEntity.LastActivityDate,
userEntity.LastPasswordChangedDate,
userEntity.LastLockedOutDate
);
}
Not the solution yet, but with the two following functions you can at least get an idea what is registered:
Membership.Provider
Membership.Providers
I did inherit my User class from MembershipUser for some reason, but I'm pretty sure I had a good reason for it :-)