I have just switch to .Net membership provider to manage my users. I have a table relating to the Users table called UserGroupDetails. I would like to add a row to this table when Membership.CreateUser is called. If adding the user fails i would like to make sure that the record in UserGroupDetails is removed or not added and if adding the record to UserGroupDetails fails i would like the Membership.CreateUser to fail and the user to not be added.
I am not really interested in using the SqlProfileProvider and i have not found any information about overriding or modify the Membership.CreateUser to perform this additional insert.
Is it possible and if so could someone point me to a good resource on how to accomplish this?
Also, i do not want to rewrite the whole Membership.CreateUser method. Rather i would like to simple add to it. I have looked at http://msdn.microsoft.com/en-us/library/ms366730.aspx but this seems to be rebuilding the wheel.
Thanks,
D
You would build a custom provider
I've done this! I start by creating my aspnet user first. Here's what I'm doing.
1) I added this to my web.config:
<system.web>
<membership>
<providers>
<clear/>
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices"
enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
applicationName="[ApplicationName]" />
</providers>
</membership>
<machineKey validationKey="[]" decryptionKey="[]" decryption="3DES" validation="SHA1" />
<connectionStrings>
<add name="ApplicationServices" connectionString="Data Source=(local);Initial Catalog=[DataBaseName];User ID=[UserName];Password=Password" providerName="System.Data.SqlClient" />
</connectionStrings>
</system.web>
2) I then use this to create my user table
var user = Membership.CreateUser(request.UserName, request.Password, request.Email);
3) Finally I grab my aspnet user id I just created and relate it in my custom user
user.ProviderUserKey.ToString();
You could create some logic to delete the aspnet user if insert into UserGroupDetails fails.
You don't need to build a custom provider. Just add your code to hookup your UserGroupDetails table after you call CreateUser.
Unfortunately, you can't use a TransactionScope to rollback the transaction if something fails because the CreateUsre will use a seperate database connection from your code, and this will require promoting the transaction to a distrivuted transaction, which is a pain to configure and setup.
The easiest solution is just check for failure of the CreateUser, and don't execute the second bit of code if it fails, and deleting the created user if your second bit fails. However, this is not foolproof as there are situations where you might have an orphaned record.
In order to do this in a single transaction, then the only solution is a custom provider, but I personally don't think it's worth the effort.
Create a custom provider that inherits membershiprovider. Override the create user method to extend the functionality. Call base.CreteUser and then add your code for adding the additional records to your custom table.
UPDATE:
Here's what your custom provider would look like
using System.Web.Security;
namespace YourNameSpace
{
public class CustomSqlMembershipProvider : SqlMembershipProvider
{
public bool CreateUser(//list of parameters)
{
bool UserCreated = false;
MembershipCreateStatus status;
//provide the required parameters
base.CreateUser(//list of parameters);
if (status == 0)//user was successfully created
{
//perform your custom code
//if success
UserCreated = true;
}
return UserCreated
}
}
}
Make sure you reference your new custom provider in your Web.config file
<membership defaultProvider="CustomMembeshipProvider">
<providers>
<clear/>
<add connectionStringName="Your connection string name" name="CustomMembeshipProvider"
type="YourNameSpace.CustomSqlMembershipProvider" />
</providers>
</membership>
Related
Side note: I am using vs2013 express and have installed nothing else.
I am building an intranet site with the following authentication/authorisation goals:
Custom roles using the Roles class
No need for logging in, if you are signed into windows, then you're allowed to see the app
Be able to use [Authorise(Roles="Admin")] kind of attributes
Be able to manage the Users (Create/Delete/List/Edit) from a UserManagement page.
I have been following this: http://weblogs.asp.net/scottgu/archive/2006/07/23/Recipe_3A00_-Implementing-Role-Based-Security-with-ASP.NET-using-Windows-Authentication-and-SQL-Server.aspx
but i'm not sure how to Create / List out the users... this is what I have so far:
I have added a user and assigned him to a role, when i use Membership.GetAllUsers() it returns none
Web.config bits:
<authentication mode="Windows"></authentication>
<authorization>
<deny users="?" />
</authorization>
<roleManager enabled="true" defaultProvider="SqlRoleManager">
<providers>
<clear/>
<add name="SqlRoleManager"
type="System.Web.Security.SqlRoleProvider"
connectionStringName="EFDbContext"
applicationName="TEST" />
</providers>
</roleManager>
<membership defaultProvider="SqlProvider"
userIsOnlineTimeWindow="15">
<providers>
<add
name="SqlProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="EFDbContext"
applicationName="TEST"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
passwordAttemptWindow="10" />
</providers>
</membership>
I added my first user in Global.asax like this:
if(!Roles.RoleExists("Admin"))
{
Roles.CreateRole("Admin");
Roles.AddUserToRole(#"JIMMYT1988\jimmyt1988", "Admin");
}
The user and role is working because if I block access to Admin, I'm allowed in.. whereas if I created the user without adding the role, he wasn't allowed access... so that's all good and working.
this is me blocking access to only role of Admin:
[Authorize(Roles = "Admin")]
public class UserController : Controller
{
private IUserRepository repository;
public UserController(IUserRepository repo)
{
repository = repo;
}
public PartialViewResult List()
{
IEnumerable<User> users = repository.Users;
UserListViewModel viewModel = new UserListViewModel();
viewModel.Users = users;
viewModel.TotalUsers = Membership.GetNumberOfUsersOnline().ToString();
return PartialView(viewModel);
}
}
So I am assuming the user and role of admin are working correctly and I can see the entires in the database... The above controller is part of an abstract -> concrete mapping for specifically membershipprovider users... but I have debugged on the GetAllUsers line and that actually returns the empty list, it's not the mapping going wrong.
Finally I call this:
MembershipUserCollection users = Membership.GetAllUsers();
which returns no users.
Any idea?
First you need to create your user using the static Membership.CreateUser method:
MembershipUser newUser = Membership.CreateUser(#"JIMMYT1988\jimmyt1988", "password");
And then you can add that user to the role.
Regarding your comment:
How do I go about creating a user that doesn't need a password and yet
still be able to list the users out?
I'm not positive, but I think you can set the password related Membership properties to have "0" be the "required length" of a password.
You can add this to the membership section of your web.config:
minRequiredPasswordLength="0"
Up to now, I can create Custom Membership Provider and Custom Role Provider, but I have problem with Custom Profile Provider. After looking at some demo, I've found out that they use web.config to define the schema for the Profile. For example, in the tag <profile>:
<properties>
<add name="AddressName"/>
<add name="AddressStreet"/>
<add name="AddressCity"/>
<add name="AddressState"/>
<add name="AddressZipCode"/>
<add name="AddressCountry"/>
</properties>
To access that field, they use Profile.AddressName, Profile.AddressStreet, etc...
My question is: is that the only way to define the profile schema? If I want to use my UserProfile table in my database, what should I do? I need the way to read I write the data.
Thanks for your help.
Probably not much of use to the original poster, but it looks like you can do as described in this blog post. The gist is that you let the generated profile class inherit your own class which in turn inherits from ProfileBase, and finally override ProfileProvider:
<profile inherits="Acme.MyApplication.ProfileCommon,MyApplication" defaultProvider="EfTableProfileProvider">
<providers>
<clear />
<add name="EfTableProfileProvider" type="Acme.MyApplication.EfTableProfileProvider,Facade" connectionStringName="ApplicationServices" applicationName="/MyApplication"/>
</providers>
</profile>
I read a couple of pages about "Membership" class and "Membership Provider" but I am not sure if I understand it.
From all that I've read, I understand that if I want to use the "Membership" class I must initialize membership provider in web.config. This Membership class works with the "type" attribute in provider in this case with "System.Web.Security.SqlMembershipProvider". Am I right ? I need some simple and good explanation about Membership class, the name "AspNetSqlMembershipProvider"(in providers in membership) and System.Web.Security.SqlMembershipProvider.
(In this example I use the Database from file "aspnet_regsql.exe")
Example:
<connectionStrings>
<add name="UsersConnectionString" providerName="System.Data.SqlClient"
connectionString="Data Source=OWNER;Initial Catalog=LoginsDB;Integrated Security=True" />
<membership>
<providers>
<clear />
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="UsersConnectionString"
enablePasswordRetrieval="false" enablePasswordReset="true"
requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
maxInvalidPasswordAttempts="5" minRequiredPasswordLength="3"
minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
applicationName="/" />
</providers>
</membership>
1.How Membership class work and know where to put information in specific fields in database ?(For example if I use "Membership.CreateUser("admin", "admin")")
2.Why when I change the name in "add name="AspNetSqlMembershipProvider"" the application doesn't want to work. Is this some unique name ?
3.What is "System.Web.Security.SqlMembershipProvider" ? Is this class works in conjuction with "Membership class"
4.What is this database which is generated from "aspnet_regsql.exe" file ? is it prefer to use it when creating registration page ?
1.How Membership class work and know where to put information in specific fields in database ?(For example if I use "Membership.CreateUser("admin", "admin")")
The concrete class System.Web.Security.SqlMembershipProvider, which inherits from System.Web.Security.MembershipProvider overrides MembershipProvider methods and properties with implementations which target a specific database schema (namely LoginsDB's schema )
2.Why when I change the name in "add name="AspNetSqlMembershipProvider"" the application doesn't want to work. Is this some unique name ?
I guess so. I must confess I never tried that. I am using CustomMemberShipProvider, and never noticed a problem with the name.
3.What is "System.Web.Security.SqlMembershipProvider" ? Is this class works in conjuction with "Membership class"
It is an implementation of the abstract class System.Web.Security.MembershipProvider
4.What is this database which is generated from "aspnet_regsql.exe" file ? is it prefer to use it when creating registration page ?
If you use SqlMemberShipProvider, you don't really have any choice.
Depending on you framework version, you may also find give a look SimpleMemberShipProvider :
http://msdn.microsoft.com/fr-fr/library/webmatrix.webdata.simplemembershipprovider%28v=vs.111%29.aspx
using System.Web.Security;
I'm creating a resetPassword form in MVC4:
using System.Web.Security;
[HttpPost]
[AllowAnonymous]
public ActionResult ResetPassword(ResetPasswordModel model)
{
MembershipUser u = Membership.GetUser(model.Username);
if (HashResetParams(u.UserName, u.ProviderUserKey.ToString()) == model.Key)
{
string resetCode = u.ResetPassword();
u.ChangePassword(resetCode, model.Password);
}
return View("ChangePasswordSuccess");
}
Any idea why I'm getting a "ResetPassword- Specified Method not supported" error when I hit the line:
string resetCode = u.ResetPassword();
I wonder if it has something to do with MVC4 projects defaulting to use the SimpleMembership implementation.
Also, I've seen various approaches on how to reset passwords in ASP.NET Membership, perhaps there's a better way?
try to use:
string token = WebSecurity.GeneratePasswordResetToken(userName);
WebSecurity.ResetPassword(token, newPassword);
If you are using the SimpleMembershipProvider then yes:
By design, the SimpleMembershipProvider class does not implement the
full range of functionality that is possible in ASP.NET membership
providers, as defined in the MembershipProvider class that is used by
all ASP.NET membership providers. Some members are available in the
class because they are inherited from the base class, but will throw
an exception if you access them.
The alternative would be to use the SqlMembershipProvider
You should have something similar to this in your web.config:
<membership defaultProvider="SqlProvider"
userIsOnlineTimeWindow="15">
<providers>
<add
name="SqlProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="SqlServices"
applicationName="MyApplication"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
passwordAttemptWindow="10" />
</providers>
</membership>
I am using ASP.net membership, but I want to store additional information for client while registration instead of default columns as membership provider does, so how can I customize the dbo.aspnet_Users table and change the code so that it doesn't affect the other functionality and works fine?
Could somebody suggest me on it how can I achieve this?
Use an ASP.NET Profile-Provider.
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 currect application to let the user chose his startpage self.
Therefor i only 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.