first of all I wanna say that I know there are many topics about this and I'm also searching the web to understand the whole concept that mvc deals with the security and keeping user information etc, but I wanted to get some advises, ideas from pros while I'm reading about this, so I'm gonna explain my situation and I'm thankful for the helps.
lets say I have a custom table called "Users"
public class Users : KySerializableObject
{
[required]
public virtual string Email { get; set; }
[required]
public virtual string userName {get; set; }
public virtual UserType UserType { get; set; }
[Required]
[ForeignKey("UserType")]
public virtual int UserTypeID { get; set; }
}
now what I know is that mvc provides a simpleMembership which works for a simple situations, but since I'm having different types of users and additional information for my User, what I'm wondering is how can I take a use of [authorize] tag for my user with different roles which I prefer to use my own roles table and also how can I deal with the login process ? I mean the part that I should use FormsAuthentication, or I'm not even sure I should use that or not, I'm really lost and I'd love to hear some advises from you guys. I'm not asking for codes or anything, any link to a good guidance that explains my situation would be awesome.
Thanks again
i have same situation and i am following a procedure for
Authentication FORMS Authentication
Authorization i write my own wrapper class to RoleProvider. with this you can directly use like
[Authorize (Rules = "Admin,Users")]
if your problem is authentication/authorization it will helps you perfectly.
Please take a look at this forum discussion in the ASP.Net forum
If you know your way around authentication, you should have nailed the code in here. But, for your requirement, please take a close look at this bit of code
string[] roles = //you add your custom roles for the current user to this string list
GenericPrincipal userPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name),
roles);//then you create a Generic principle
Context.User = userPrinciple;
remember, if you are putting this code outside of Global.asax file, then Context is the HttpContext.Current
Now you can use [Authorize(Roles = "yourRole1, yourRole2")]
Hope that helps.
Related
I'm using ASP.NET Core MVC 2. I need to operator can change some elements of Models or view codes. How I can code or design for it.
For example: I have a "news" model and I want to operator (final user of website, who can't code or access to visual studio) can add this to "news" model:
public string ImageUrl { get; set; }
and also can change the database without coding.
Thanks
If you want to design a completely extensible model, you could use something called Entity–attribute–value model (EAV).
Your model might have a couple common attributes like Title and Summary. Then you might have a list of Custom Fields, the first of which could be ImageUrl. You could create your own class called CustomField or something similar, which would have properties such as FieldName, and DataType.
public string Title { get; set; }
public string Summary { get; set; }
public List<CustomField> CustomFields { get; set; }
You would then have a table full of custom field values and the tables they belong to. It gets pretty complex.
When you want to automatically reflect your model changes to the database, you will need an ORM framework like EF (Entity Framework). You can check more here.
In order for your case to happen is to build your own configuration platform that may use several tools and mechanincs that will allow you to generate code and then compile it. Such as T4 and more.
In general, this is a very hard task to accomplish and even big experienced teams would have troubles to build something similar.
I can not post any code, as this would only seem a desperate approach.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I am trying to create a permissions system in an ASP.NET MVC Application. I have been learning the newest Identity framework - here are my requirements:
A set of Hierarchical Roles for each set of functionality. So, for instance, there might be the following roles:
Inherit
Reader
Editor
Manager
Administrator
Each user would have one of those roles for each module (e.g. Events, Pages, etc.)
Users can be members of a security group. Each security group can be assigned a role directly and then all users in that group (who have not been explicitly assigned that permission) will inherit that role.
Multi-tenant site: each user has a set of sites which they are a member of. In the context of each site, they have a complete set of permissions which can be assigned by the site admin.
Through extending ASP.NET Identity, is it going to be possible for me to accomplish all of this? Or should I be building something custom from the ground-up?
9,999 times out of 10,000 implementing your own authentication system is the wrong way to go. Anything is easier than that, and it's a deceptively difficult thing to do right. ASP.NET Identity is actually pretty customizable, as it was created specifically for that purpose. You might need to do quite a bit to bootstrap your custom requirements fully, but it'll almost certainly be quicker and more secure using ASP.NET Identity.
UPDATE
UserManager's constructor takes an implementation of IUserStore. When working with Entity Framework, you typically just feed it Microsoft.AspNet.Identity.EntityFramework.UserStore, but this is your tie in point for extensibility. So, you can simply subclass UserStore and then override something like GetRolesAsync to do whatever custom role logic you need to implement. Then you'd just feed UserManager your subclass.
In version 1.0 of ASP.NET Membership, the IRole interface must have a string primary key. However in version 2.0, released March 2014, they added an IRole<TKey> that allows you to specify a role's primary key, as long as TKey implements IEquatable<TKey>.
That said, out of the box MVC integration points for authorization still depend on roles being ID'd by a single string. So if you are going to do authorization there, via attributes like Authorize, then you may need to write your own custom authorization attributes.
One way to achieve hierarchical roles would be to handle it in your application instead of in the model. I assume by hierarchical, you mean that Administrators have all the privileges of Managers, Managers have all the same privileges as Editors, and so on. You could achieve this by adding users to multiple roles, instead of having to walk through a modeled role hierarchy. Something like a db trigger could do it, but you can model it as a business rule in code too. Then if you restrict a page to Editor, Admins & Mgrs would have access to it as well.
Another way would be to just authorize certain actions for multiple roles:
[Authorize(Roles = "Administrator, Manager, Editor")]
public ActionResult Edit()
[Authorize(Roles = "Administrator, Manager")]
public ActionResult Manage()
[Authorize(Roles = "Administrator")]
public ActionResult Admin()
I disagree though that you would want to id roles on a composite key. If you want to protect MVC actions using the Authorize attribute, the ID of the role needs to be a constant value, like a string literal, int or Enum value, etc. If you keyed role on more than one of its properties, the number of properties you need to set on the attribute multiplies by the number of values in each component of the id. You would have Manager/SiteA, Manager/SiteB, and so on.
Instead, it sounds like it might be a good idea to just add properties to the gerund that tracks users in roles (the in-between table in a many-to-many relationship). To do this, you wouldn't be able to simply override and extend methods in the UserManager class as #Chris Pratt suggested. But that doesn't mean you have to throw out the baby with the bathwater. You can still use Microsoft.AspNet.Identity for authentication, and just write your own methods for role management, augmenting them to take an additional parameter:
AddToRoleAsync(TUser user, string roleName, string siteId);
public class Role : IRole<int>
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<UserInRole> Authorizes { get; set; }
}
public class UserInRole
{
public int RoleId { get; set; } // part of composite primary key
public int UserId { get; set; } // part of composite primary key
public string SiteId { get; set; } // part of composite primary key
public virtual Role Role { get; set; }
public virtual User User { get; set; }
}
public class User : IUser<int>
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<UserInRole> Authorized { get; set; }
}
Given the above, say your URL's look something like this:
/sites/site-a/admin
/sites/site-b/manage
/sites/site-c/edit
/sites/{siteId}/do
...you could write a custom authorization attribute that checks the URL and authorizes the principal both against the role name in the attribute and the siteId in the URL. To get access to the db from the attribute, if you are using IoC for EntityFramework, you can property inject an instance of your DbContext (or whatever interface you have wrapping it).
Following steps can solve your problem
Create granular level of roles...typically for each action
Group them up into GroupRoles...so that admin can easily manage it
Add individual level claims to user for specific permission
Some good examples of the same are below
http://www.3pillarglobal.com/insights/granular-level-user-and-role-management-using-asp-net-identity
http://bitoftech.net/2015/03/11/asp-net-identity-2-1-roles-based-authorization-authentication-asp-net-web-api/
Hope this solves your problem
I read this q/a Real example of TryUpdateModel, ASP .NET MVC 3 and was really interested on #ben-foster response.
I started doing a comment on that answer but got quite long, so started a new Question.
Having ViewModels for everything approach (which i like a lot) get me into some 'weird scenarios' that i want advice in how should I do.
Imagine this structure :
public class ProductListEditableViewModel {
List<ProductEditViewModel> products {get;set;}
}
public class ProductEditViewModel {
List<PriceViewModel> prices {get;set;}
}
public class PriceViewModel {
CurrencyViewModel currency {get;set;}
}
and so on ... ? do you really make one view model for each inner class? how then you map all that to the Model Object?
Also, that covers the Edit, but I have an Add, a send via email, and potentially more Views so more ViewModels!! should i end like something :
AddCurrencyViewModel
QuickAddCurrencyViewModel
EditCurrencyViewModel
ListCurrencyViewModel
DeleteCurrencyViewModel
ShareCurrencyViewModel
all having the 'almost same' properties ?
Should all those be packed into one file ?
Also do i need all this all viewModels or a inheritance approach might be better?
If you can, I´ll appreciate elaborate on complex scenarios
Also, I use a DTO approach to expose some of the model objects into web service / apis, so I already have some form of mapping already in place where this DTO are not exactly my ViewModels, should I remove one of them? what´s the suggestion in this scenario ?
I´m using entity framework but i think the question is (or should be) ORM agnostic.
Not using UoW pattern (will this helps?) as looks it´s gets more complicated as the depth of the object increases.
Thanks a lot!
We typically have a view model per view so yes, if you have lots of views you will have lots of view models.
In typical CRUD applications we often have very similar views, for example Add and Update. In these cases, yes we use inheritance rather than writing duplicate code - usually Add subclasses Update.
public class AddFoo : UpdateFoo {
public AddFoo() {
// set up defaults for new Foo
}
}
public class UpdateFoo {
public string Name { get; set; }
// etc.
}
We attempted to "share" view models between views in the past and normally ended up in a world of pain.
With regard to your "weird scenario" - this does look weird indeed, but perhaps because I don't understand your application.
The goal of your view model is to provide the information to the view that is needed and ideally to flatten any complex objects so they are easier to work with. You shouldn't split your view models up like your example unless it makes sense to do so.
Let's say I wanted to a create a view where the customer could change their contact details. Taking the following domain object:
public class Customer {
public string FirstName { get; set; }
public string LastName { get;set; }
public Address Address { get; set; }
}
I'd probably flatten this to a view model like so:
public class UpdateAddressModel {
public string FirstName { get; set; }
public string LastName { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressCity { get; set; }
// etc.
}
Of course there will be occasions where it doesn't make sense to do this, for example a dashboard view in an online store where you have a list of products going out of stock and a list of recent orders - these two things are unrelated but are required by your view:
public class DashboardModel {
public List<Product> ProductsGoingOutOfStock { get; set; }
public List<Order> NewOrders { get; set; }
}
how then you map all that to the Model Object?
I'm assuming by Model Object you mean your data/domain model. The key takeaway here is that the view model you use to render your view is unlikely to be the same as the "models" you POST to the server and if they are, you're probably over-POSTing or you have some crazy enter-everything data capture screen that will make your eyes bleed.
I find it helps to think of what you send to your server as Commands and what you use to render your views as view models.
So the answer to your question - how do you map your complex view model to your data model? - Quite simply, you don't. You should send commands to the server that perform a specific task e.g. updating an address.
There's no hard and fast rule in how you structure your view models but generally go with what makes sense and if it starts to feel too complicated you're probably trying to do too much with one view.
I hope this helps. You'll find lots of posts relating to this matter on my blog.
I realize this is an old-ish question but I did want to address one of the questions posed by the OP that was not answered.
Should all those [ViewModels] be packed into one file ?
Most of the examples I see put each ViewModel in a separate file, so the dominant convention seems to be one file per viewmodel, but I found in practice that this seems to be overkill. Instead I put all viewmodels for a particular controller in one file with multiple viewmodels in it. So for example if User is my Controller and I have several viewmodels associated with this controller such as UserAddViewModel, UserEditViewModel, UserDeleteViewModel I put all of the viewmodels for User in one file called UserViewModels.cs
The reason I need a role-based system:
Restrict access to pages.
Restrict access to certain features on pages.
Check/validation inside service layer.
So I'm guessing, I can just create an enum and if I need a new role, just add it to the app code (the app would change anyways so requires a recompile).
So right now I have
public class User
{
/* .. */
public virtual ICollection<UserRole> Roles {get; set;}
}
public enum UserRoleType
{
Administrator,
User
}
public class UserRole
{
public int UserRoleId { get; set; }
public int RoleTypeValue { get; set; }
public UserRoleType RoleType
{
get { return (UserRoleType)RoleTypeValue; }
set { RoleTypeValue = (int)value; }
}
public virtual User User { get; set; }
}
This is a 1 to many. The pros I see for this is that instead of a many-many, there is a 1-many and joins are less. The application already knows what the role is based on what the int resolves the enum to.
Are there any flaws in the way Im doing this? Is there anything you have met in your experience that would require me to store the actual values in the database?
To be clear, you are suggesting that you don't need an actual lookup table in the database for Roles? Instead, they just have an int that is not a foreign key to anything--it is simply a representation of the enum in the application?
It's impossible to answer definitively without knowing all the details of your application. That disclaimer aside, I see nothing inherently problematic about it. It would certainly work fine for some systems.
Possible downsides:
There is no source of valid values enforced on the database side via referential integrity. What is to stop someone from entering "12452" for the RoleId in the database column? There are other ways around this like using check constraints, but they are not necessarily easier to maintain than a lookup table.
There is no way to effectively query the user/roles tables and have a human-readable representation of roles without knowing what the RoleIds represent (you will have to have the enum in front of you to make sense of the query result).
If the database is used for other applications, the roles will need to be represented (and maintained) in that application as well.
I am in the planning phase of a new ASP.NET MVC application and one of the requirements is storing some user information that is not part of the standard set found in the User class that comes with ASP.NET MVC. I suppose it comes down to two questions.
1) Can I edit the class that is being used already to store the information that I need?
2) If I roll my own how can I keep things like the Authentication piece that make things so nice when trying to lock down some views using the User.IsAuthenticated method?
Another alternative I have considered is using the User class provided as is, and instead putting the other information into a separate table with the guid userid as the foreign key.
Suggestions?
Profiles are one option as #Burt says, and offers a lot of flexibility.
I had a similar need to track Employee information, but I opted to roll my own Employee class and create a relationship to a standard User. I really like how this has worked out as I can keep any Employee specific business logic separate from the User class Membership system.
Since not every User was going to be bound with an employee, this made more sense for my case. It may not for yours, but it is an alternative.
So, I have something like:
public class Employee
{
public Employee(string name) : this()
{
Name = name;
}
public virtual string Name { get; set; }
public virtual string Title { get; set; }
public virtual decimal Salary { get; set; }
public virtual decimal Hourly { get; set; }
public virtual decimal PerDiem { get; set; }
public virtual string StreetAddress { get; set; }
public virtual Guid UserId { get; set; }
public virtual MembershipUser User {
get
{
// note that I don't have a test for null in here,
// but should in a real case.
return Membership.GetUser(UserId);
}
}
}
See ASP.Net MVC Membership Starter Kit. It provides the Asp.Net MVC controllers, models, and views needed to administer users & roles. It will cut distance in half for you.
Out of the box, the starter kit gives you the following features:
List of Users
List of Roles
User
Account Info
Change Email Address
Change a User's Roles
Look into profiles that are part of the membership functionality provided by MS. They are extendable and pretty flexible.