问题
"SimpleMembership", we're told, is the future of asp.net membership / role management. The MVC4 "Internet Application" template implements Account management using SimpleMembership. However, the way it is implemented merges all the application tiers into 1.
It kind of shocked me that after all the work they've put into layering apps properly with MVC, we get this shoddy implementation of "the way forward" for Membership with no DI, use of WebMatrix DLLs and complete lack of SoC. Particularly the ActionFilterAttribute for SimpleMembershipInitialization - it inherits from an MVC attribute and makes calls to the EF DBContext directly.
I realise I'm being lazy, but has anyone done a "proper" template using SimpleMembership that means I can have proper separated tiers in my app, and not have EF DBContext references in my MVC app?
回答1:
One of powerful concepts of SimpleMembership is that you can customize the user profile to fit your application needs, as discussed in this article. For example, you may want to add email confirmation to your registration process which will require storing the user's email address in the user profile. In the previous membership/role management for ASP.NET this was very ugly to implement and added properties were stored in a blob. Yuck!
So what does this have to do with your question on making SimpleMembership n-tier friendly? While I agree that what the template generates is not n-tier friendly I would also state that most real MVC applications of any complexity will require customizing SimpleMembership, and therefore will require making a tier or layer that is specific to the application requirements anyway. Stated another way, creating a reusable tier for SimpleMembership would only be useful in the most basic MVC apps.
Personally I have come to the conclusion that what is generated by the Internet template in regards to SimpleMembership will almost always be modified. As the first article I referenced points out the first part of customization is getting rid of the SimplemembershipInitialization attribute, which is just a lazy way of initializing SimpleMembership in the event the developer is not using forms authentication. And often you will want to move the DBContext used by SimpleMembership into the DBContext for the rest of your application. User profiles are often tightly integrated with the rest of the application domain.
And since we are on the subject of SoC and ASP.NET security, I would argue that ASP.NET was never very good at this. For forms authentication you use an Authorize attribute on your controllers and/or actions which takes a role as a parameter. This forces the application developer to think about security design while designing the application domain. You have to determine what roles the application will have up front, and heaven forbid they change later because now you have to go through all of those attributes and update them accordingly. I have started to use a custom authorize attribute that takes as parameters a resource name and an operation type (ex: read, write, execute...). Then I can map roles to resource/operations in a database so that it can change easily, or even allow an administrator to make changes to how roles are implemented in the application. Microsoft is taking the same approach with ClaimsPrincipalPermissionAttribute now that they have incorporated WIF into .NET 4.5.
Updated 3/8/2013
I have created an open source project on CodePlex called SimpleSecurity that decouples SimpleMembership from the MVC application. You can read about it here. I still think developers will most likely want to modify SimpleSecurity but since this is open source they can. We will see if this is something we can evolve to be a reusable and better SimpleMembership.
回答2:
Accepted answer is not correct, that is not N-Tier. The membership data access and business logic are occurring in the same layer. Just because code is in a different assembly doesn't mean it isn't in the same layer.
Without some kind of transport mechanism to the data access layer, this is not N-Tier.
The solution is to inherit and override the WebMatrix SimpleMembershipProvider class such that its data access calls can be performed on a separate host.
I recommend using dotPeek to look at SimpleMembershipProvider so you know what to do in your overrides.
回答3:
I think your question relates more to SoC than n-tier architecture (which is more about physical separation between layers as pointed out by @klatzib).
I would argue that the logic within the membership providers should not be classed as business logic as they do not contain application or client specific code. In fact the idea of the provider model is that it fulfils a generic contract irrespective of the context in which it's used. A common mistake developers make is extending MembershipProvider
and bolting in application specific business logic that should exist in a higher layer. If that's what you want to achieve with a alternative design, then that's the wrong approach. Providers are plugins for the .NET framework, and should be entirely abstracted from code. They certainly shouldn't contain your application domain, and you should very rarely need to extend them.
Addressing your question another way, does the SimpleMembershipProvider
prohibit SoC in application design or even n-tier architecture? No it doesn't. The MVC4 template is built for simplicity, but the ActionFilter
used to initialize the provider is not part of the membership implementation, and you are free to initialize the the provider in any way you see fit (I prefer making this call from a DI container factory method). In fact SimpleMembershipProvider
as no direct dependency on EF at all, so yes it is possible to remove references to EF DbContext in your web app.
回答4:
Exactly what I was looking for (almost). Just wish it wasn't tied into entity frameworks as I was hoping to get Kevin's n-tier solution working with Dapper ORM :(
来源:https://stackoverflow.com/questions/15006532/simplemembership-anyone-made-it-n-tier-friendly