I know how to create users and assign them to roles etc, but when I tried to dig a bit deeper into how roles and membership tables are able to establish a relationship between each other, I got totally lost ( BTW – I do know how foreign/primary keys work ;) )
BTW - I've created tables in databases using aspnet_sqlreg wizard
Q1 - Both SqlRolesProvider and SqlMemebershipProvider have a property ApplicationName. I thought that in order for the two providers to be able to create association between their users and roles, they would both have to use same value for ApplicationName property. But that doesn’t seem to be the case.
A) Anyways, I assume that SqlRolesProvider.ApplicationName property is only used to distinguish between table entries belonging to different role providers, but they don’t use that property in order to associate their roles only with membership providers with the same ApplicationName value?!
B) But wouldn’t it be most practical if roles providers could only be associated with membership providers with the same ApplicationName value ( thus where SqlRolesProvider.ApplicationName == SqlMemebershipProvider.ApplicationName)?!
Q2 - I was also curios whether roles and users could be associated if roles provider was connected to DB1, while membership provider was connected to DB2. Somehow I was still able to assign users to different roles, even though roles were defined in different database.
A) But why is that? Namely, if SqlRolesProvider.ApplicationName = “rolesP” ( ApplicationID=10 ) and SqlMembershipProvider.ApplicationName = “membership” ( ApplicationID=100 ), then in order for the table in DB1 to have relationship with table in DB2, the two would have to reference each other via ApplicationName entry ( actually via ApplicationID), which would act as foreign/primary key.
But the thing is, none of the foreign key fields in DB1’s tables holds a value equal to SqlMembershipProvider.ApplicationID = 100, which would suggests that there is no relationship established between tables in DB1 and DB2 ( I know that is not the case, since I’m able to assign users to roles ). So what am I missing?
thanx
EDIT:
Uh, don't know if anybody will still be reading this, but I did some more digging and got even more confused:
If both roles (with applicationName=R1 and applicationID=10)and membership provider(with applicationName=M1 and with ApplicationID=100) are in same DB, then creating a new user causes aspnet_Users table two create two entries for same user name– one with ApplicationID=10 and other with ApplicationID=100. As far as I know, when new user is created, only one field ( with ApplicationID=100 )should be added to aspnet_Users. Uh?!
Have you looked at the aspnet_UsersInRoles Table. This is the table that links the user to the role. The RoleProvider is designed to be separate from the MembershipProvider so that you can have them in separate DB's. Additionally it allows for you to set up roles for one application name and re-use those roles in two separate applications that each have a different application name for the membership provider. Don't get stuck in the mentality that you have to have the same application name for both providers or that your application name needs to match the running application. You don't need to have any name at all if you don't want to. I hope that this helps.
I had a hard time following what you were saying...
Anyway... you seem to be looking at the database too much. Have you configured the web.config for your membership providers and were you able to query "Membership" using C# and NOT SQL queries?
Related
I'm having problems making a test user account access the database for a new app we're writing. Whenever I try to run the app I get the following error:
"The underlying provider failed on Open. Login failed for user OURDOMAIN\App.Test_User"
In trying to figure out what's wrong and looking for answers I came across this question posted here: ADO.NET Connection String. I then checked the database and found that every one of us on the development team's default schema is our own domain login (not sure what that does) and the database role we're all in adds us to db_owner. Seems to me like we'd have a pass on everything, whereas the user's default schema is dbo. They should at least also have access to the additional schemas our database and app uses. But that referenced article says that the connection string cannot specify the schema. So I'm no sure how we'd get to it using EF. What am I missing here?
It looks like you have Windows Authentication. This means, that a user logged into Windows is automatically logged into the database. But this does not mean that this user is automatically allowed to do things in the db. He also must have rights granted.
You can use default roles for this or create your own roles (and attribute them to the users) for more sophisticated scenarios. If you create your own roles, you must grant them rights for all objects these users can use. Example:
GRANT SELECT, INSERT, UPDATE, DELETE ON MyTable TO AdvancedUserRole;
GRANT SELECT ON CustomersView TO AdvancedUserRole;
GRANT SELECT ON MyTable TO SimpleUserRole;
GRANT SELECT ON CustomersView TO SimpleUserRole;
If you are using default roles, users that are not db_owner need to be at least db_reader and possibly also db_writer if they are allowed to insert/update data.
When you create a new ASP.NET internet application, you get the built in membership tables and controllers etc. There are 5 tables created:
UserProfile
webpages_Membership
webpages_OAuthMembership
webpages_Roles
webpages_UsersInRoles
I understand the basic concept of how all these work but I have a question on why is a UserProfile create along with the webpages_Membership? Can't these 2 tables practically be combined together? If that's not how it works, can you explain to me why the 2 files were created.
No, they cannot be combined, because a user profile has nothing to do with membership. Membership is about your user id, password, and authentication. User Profile is about things like name, address, etc..
It's designed this way so that you can extend the user profile to include whatever information you want. While the Membership tables do not change, because those are "hard wired" into the provider.
MembershipProvider has methods
public abstract MembershipUser GetUser(
Object providerUserKey,
bool userIsOnline
)
to look up users by their unique identifier. This is useful if you want to have you own database and associate some objects of yours to certain memberships.
Can you do the same with RoleProvider ? There doesn't seem to be any methods to map roles to their unique identifier or vice versa.
As a side note is it a good idea to just add your own tables to the asp.net sql database or is it better to have a separate database for your own objects and have foreign keys into the asp.net sql membership table.
There is no way within the API to return a role from an ID - you can get all roles via
Roles.GetAllRoles();
Or you can get all roles for a user by
Roles.GetRolesForUser(userName);
But not a single role.
I would guess the reason for this is that roles on there own are probably not that useful (at least as far as Microsoft are concerned).
Of course roles are just a table within the database so you can easily add this functionality yourself with some straight SQL - it will just take a little more work.
In terms of additional data - I normally create my own tables within the same database with foreign keys as you have suggested above. Although if you have not heard of Profile Provider (http://msdn.microsoft.com/en-us/library/0580x1f5.aspx) you may want to look into that as well.
There's no such thing as an "asp.net sql database". There's simply the default database that asp.net creates for you if you haven't specified one. There is no reason to use this default database seperately from your regular database. This is why it has a connection string.
The whole point of membership is that it's flexible, to use as you see fit.
On a login page, the Page.User variable is still set to anonymous. If you'd like to verify roles before login, you can construct your own GenerpicPrincial like:
var principal = new GenericPrincipal(
new GenericIdentity(username),
Roles.GetRolesForUser(username));
I am using the ASP membership services to create and manage users. I notice that on user account registration everything works fine... Until I call Roles.AddUserToRole, and suddenly I get a second user account created in the aspnet_users table. Can someone explain this? I am quite certain that I should only ever have one user account in the database per registered user...
Roles and membership are separate concerns, e.g. do not depend on one another, so the multiple records in aspnet_Users do indicate that you may want to examine your configuration and ensure that your membership and roleManager elements either:
both have NO applicationName defined (default '/') or
both have the SAME applicationName defined
http://weblogs.asp.net/gurusarkar/archive/2010/01/09/asp-net-mebership-creates-two-users-in-aspnet-users-table.aspx
I am going to use forms authentication but I want to be able to link the asp.net users to some tables in the db for example
If I have a class and students (as roles) I'll have a class students table.
I'm planning to put in a Users table containing a simple int userid and ASP.NET username in there and put userid wherever I want to link the users.
Does that sound good? any other options of modeling this? it does sound a bit convoluted?
Basically, the ASP.NET membership service creates a GUID per User, so if you need to have a foreign key of the user in a table, then this is what you should use. As such, you will not need the mapping table of a username to a userid as you already have a unique identifier per user (the aforementioned GUID)
If your looking to extend the amount of information one can store against a user, then this link has all the details regarding that.
If you're going to use ASP.NET membership, you should create the users with the ASP.Net Membership classes and database tables. This will create a user in the dbo.aspnet_Membership with the appropriate roles set for that user, upon successful insertion into this table, you can get the UserId from the dbo.aspnet_Membership table.
In YOUR Users table create a table with an int(auto-incrementing) ID, and also create a membershipID field in your table(rather than username) of type uniqueidentifier called say, membershipID. This is where you would store the value from the aspnet_Membership table to link the two together. You should also put a foreign key relationship on your membershipID field for referential integrity.
EDIT: Just to clarify with the other posts, id is of type GUID in your ASP.NET code, and of type uniqueidentifier in your SQLServer database.
We did this for a system where we retro-fitted forms authentication into a system using another authentication system. We added a column to our existing user account table. We added a GUID column, since this is what the aspnet_xxxx tables use, and filled it with the GUID from the aspnet tables. We then wrapped creation of our entry in our table into a transaction dependant upon the success of account creation using the asp.net membership calls. It's very important to make sure you sync the tables together with a transaction or something to make you don't have entries in one system and not in the other.
I'm not 100% sure, but I think that usernames can change so you shouldn't use that to link your systems. Use the GUID.
Hope this helps