In the previous chapters we know that you can use the [authorize] feature in an MVC application to restrict the user's access to certain URLs (Controller/Controller methods), but this is after authenticating the user, and the user's authentication is still the authentication mechanism using the ASP.
Asp. NET provides Windows and forms two authentication, the former is mainly used in the intranet domain environment, the latter is more applied to the Internet, here we only discuss the latter. Starting with the simplest example, we'll configure the Forms authentication method in Web. config:
Here to set the authentication method for forms, the user login address is ~/account/login, we use the simplest way to create user information, in the credentials section directly set the user name/password. Before creating a page, we create a collection of user names and passwords in the model class:
Using System.componentmodel.dataannotations;namespace SportsStore.WebUI.Models {public class Loginviewmodel { [Required] public string UserName {get; set;} [Required] [DataType (Datatype.password)] public string Password {get; set;}} }
Create a view to collect user names and information:
@model sportsstore.webui.models.loginviewmodel@{ viewbag.title = "Admin:log in"; Layout = "~/views/shared/_adminlayout.cshtml";}
Finally, you need to process user-submitted user names and passwords in the account controller's login action to complete user authentication:
[HttpPost] Public ActionResult Login (Loginviewmodel model) { if (modelstate.isvalid) { bool result = FormsAuthentication.Authenticate (model. UserName, model. Password); if (result) { Formsauthentication.setauthcookie (model. UserName, false); Return Redirect (Url.action ("Index", "Admin")); else { modelstate.addmodelerror ("", "incorrect username or password"); return View (); } } else { return View (); } }
Call FormsAuthentication.Authenticate () to authenticate the user name and password, how to verify success, call Formsauthentication.setauthcookie () to set the cookie for user authentication and return in response , the user is no longer required to log on when the cookie expires.
The above is the simplest forms authentication process, but the actual Internet application user's information is generally stored in the database, through membership provider using the information in the database to authenticate users, MVC4 Microsoft provides us with SQL membership Provider, Universal membership provider and simple membership provider, let's look at how to use them in detail.
SQL Membership ProviderIn. NET 2.0, SQL membership provider already exists, using the empty template in Visual Studio 2012 to create a MVC4 project, Web. config you will not see any membership For provider related information, Windows Authentication is used by default. Open the ASP. NET Configurtion tool under the VS Project menu (remember to compile the project before you open the Configuration tool, otherwise you will be prompted with "a problem with the selected Datastore"), and on the Security tab, click "Select Authentication Type" The configuration tool asks "How do users access your site?", select "Over the Internet", and after clicking "Finish", the Configuration tool will automatically add "<authentication mode=" Forms "/>" in Web. config. The configuration tool still does not add any membership provider information in Web. config, but we go to the "Provider page" of the configuration tool and see that AspNetSqlMembershipProvider is selected by default. The configuration tool also creates a database named Aspnetdb.mdf in the project's App_Data directory, which is a SQL Express database that cannot be opened directly in Visual Studio 2012 (vs is localdb). You can view the service instance attached to SQL Express in SQL Administration tools. Opening the database allows you to see a number of tables and stored procedures in the database that are prefixed with "aspnet_", which are required by SqlMembershipProvider.
What if we were to use a self-built database to save user information? We click on the App_start directory in the solution Exploer, and select Add-Add project in the right-click menu->sql Database to create a LOCALDB database, add the appropriate connection string to the Web. config:
<connectionStrings> <add name= "defaultconnection" connectionstring= "Data source= (localdb) \v11.0; attachdbfilename=| Datadirectory|\mvc4empty.mdf;initial catalog=mvc4empty;integrated security=true " providerName=" System.Data.SqlClient "/> </connectionStrings>
We also need to manually add the SqlMembershipProvider to the Web. config to make it use the database connection above:
<membership defaultprovider= "Mysqlmembershipprovider" > <providers> <clear/> < Add Connectionstringname= "DefaultConnection" enablepasswordretrieval= "false" enablepasswordreset= "true" requires Questionandanswer= "false" Applicationname= "/" requiresuniqueemail= "false" passwordformat= "Hashed" Passwo rdstrengthregularexpression= "" Name= "Mysqlmembershipprovider" type= "System.Web.Security.SqlMembershipProvider"/& Gt </providers> </membership>
Opening the ASP tool again to the security interface will prompt the error "Could not find stored procedure ' dbo.aspnet_checkschemaversion '", the Configuration tool tries to invoke the related stored procedure, But the database was created manually, not including these procedures and data tables. We can use the Aspnet_regsql.exe tool to create related tables and data in our database, C:\Windows\Microsoft.NET\Framework64\v4.0.30319 and C:\Windows\ microsoft.net\framework64\v2.0.50727 has this tool, there is no scrutiny two versions of the different, here use the version of. NET 4.0. In the Aspnet_regsql tool Select Server as "(LocalDB) \v11.0", if you cannot find the newly created database in the database list, you can attach the database in advance after you connect to the service engine (LOCALDB) \v11.0 in SQL Manage studio (Aspnet_reqsql also supports the use of connection strings as parameters, see http://msdn.microsoft.com/en-us/library/ms229862 (v=vs.100). aspx). When you do this, the ASP. NET Configuration tool can create an administrative user in our database.
To prepare the configuration for Forms authentication, we continue to refine the example above, starting with the controller:
Using system;using system.web.mvc;using system.web.security;using sportsstore.webui.models;namespace sportsstore.webui.controllers{public class Accountcontroller:controller {public ViewResult Login (string R Eturnurl = null) {Viewbag.returnurl = RETURNURL; return View (); } [HttpPost] public actionresult Login (Loginviewmodel model, string returnUrl) {if (! Modelstate.isvalid) return View (); var result = Membership.ValidateUser (model. UserName, model. Password); if (result) {Formsauthentication.setauthcookie (model. UserName, false); Return Redirect (returnUrl?? Url.action ("Index", "Home")); } modelstate.addmodelerror ("", "incorrect username or password"); return View (); } public ActionResult Logout (string returnUrl) {formsauthentication.signout (); Return Redirect (returnUrl?? Url.action ("Index", "Home")); } public ViewResult Register () {return View (); } [HttpPost] public ViewResult Register (Loginviewmodel model) {if (! Modelstate.isvalid) return View (model); try {membership.createuser (model. UserName, model. Password); Viewbag.registered = true; } catch (Exception Exception) {modelstate.addmodelerror ("", Exception. Message); } return View (model); } }}
When a user logs on, no longer uses the FormsAuthentication.Authenticate () authentication user, it reads only the contents of the Credentials section in Web. config, and we need to use Membership.ValidateUser ( ) to the user password check. Call FormsAuthentication.SignOut () to log out the user, which clears the authentication-related cookie. Register () action is used to create a user, which calls Membership.CreateUser () to create a user save to the database, corresponding to the Register view:
@model sportsstore.webui.models.loginviewmodel@{ viewbag.title = "User:register"; Layout = "~/views/shared/_adminlayout.cshtml";}
As an example, here is a simple collection of user name and password, after successful registration gives a hint, html.validationsummary () shows that the error occurred, such as the user name already exists. We can create some links in the layout file associated to user registration, logout:
...<div> @if (User.Identity.IsAuthenticated) { <p>current User: @User. identity.name</p > @Html. RouteLink ("Logout", new {controller= "account", action= "Logout", returnurl=request.url.pathandquery} ) } else { <span> @Html. RouteLink ("login", new {controller= "account", action= "login", Returnurl=request.url.pathandquery}) </span> <span> @Html. ActionLink ("register", "register", " Account ") </span> } </div> <div> @if (User.IsInRole (" Admin ")) { @ Html.ActionLink ("Administrate", "Index", "Admin") } </div>
Universal Provider SQL Membership provider requires the use of a fully installed SQL Server, with many tables and stored procedures that are not supported for SQL Server Azure, the SQL Server Compact, and therefore universal Provider appeared and was first released in 2011. We can use the Basic template to create a MVC4 project in VS2012, which is configured to use universal provider by default. We can also search for "universal" in the NuGet Package Manager to find the " Microsoft ASP. Universal Provider " installation, The installation tool modifies the Web. config configuration Defaultmembershipprovider as the default provider; Config Entityframework,universal Provider use EntityFramework to complete the reading and writing of the database; Create a SQL Express database and connection string for universal provider use. Here is some of the content of Web. config:
...<configsections> <!--For more information on Entity Framework configuration, visit http://go.microsoft.com /fwlink/? linkid=237468--<section name= "EntityFramework" type= " System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, version=6.0.0.0, Culture=neutral, publickeytoken=b77a5c561934e089 "requirepermission=" false "/> </configsections>...<profile Defaultprovider= "Defaultprofileprovider" > <providers> <add name= "Defaultprofileprovider" type= "Sys Tem. Web.Providers.DefaultProfileProvider, System.Web.Providers, version=2.0.0.0, Culture=neutral, publickeytoken= 31bf3856ad364e35 "Connectionstringname=" defaultconnection "applicationname="/"/> </providers> </profi le> <membership defaultprovider= "Defaultmembershipprovider" > <providers> <add name= "Defau Ltmembershipprovider "Type=" System.Web.Providers.DefaultMembershipProvider, System.Web.Providers, version=2.0.0.0, Culture=neutral, publickeytoken=31bf3856ad364e35 "connectionstringname=" DefaultConnection " Enablepasswordretrieval= "false" enablepasswordreset= "true" requiresquestionandanswer= "false" requiresuniqueemail= "False" maxinvalidpasswordattempts= "5" minrequiredpasswordlength= "6" minrequirednonalphanumericcharacters= "0" passwordattemptwindow= "Applicationname="/"passwordformat=" Hashed "passwordstrengthregularexpression=" "/> & lt;/providers> </membership> <rolemanager defaultprovider= "Defaultroleprovider" > <PROVIDERS&G T <add name= "Defaultroleprovider" type= "System.Web.Providers.DefaultRoleProvider, System.Web.Providers, version= 2.0.0.0, Culture=neutral, publickeytoken=31bf3856ad364e35 "connectionstringname=" DefaultConnection " Applicationname= "/"/> </providers> </roleManager> <!--If You is deploying to a Cloud environment that have multiple Web server instances, you should change sessIon state mode from ' InProc ' to ' Custom '. In addition, change the connection string named "DefaultConnection" to connect to an instance of SQL Server (including SQL Azure and SQL Compact) instead of to SQL Server Express. --<sessionstate mode= "InProc" customprovider= "Defaultsessionprovider" > <providers> <add Name= "Defaultsessionprovider" type= "System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, version=2.0.0.0, Culture=neutral, publickeytoken=31bf3856ad364e35 "connectionstringname=" DefaultConnection "/> & lt;/providers> </sessionState>....<entityFramework> <defaultconnectionfactory type= " System.Data.Entity.Infrastructure.SqlConnectionFactory, entityframework "/> <providers> <provider Inva Riantname= "System.Data.SqlClient" type= "System.Data.Entity.SqlServer.SqlProviderServices, Entityframework.sqlserver "/> </providers> </entityframework>...
Open the ASP. NET Configuration tool, you can see that the membership provider has AspNetSqlMembershipProvider and Defaultmembershipprovider to choose, the former is SQL membership provider, We select it at this time and the Config tool will change the membership to:
<membership>
The defaultprovider feature is removed without any features, which requires special attention.
View the database generated by the universal provider, which contains only the users, Roles, Profiles, memberships, usersinroles, applications tables, and there are no stored procedures. There is a lot of simplification in the database model, no longer using stored procedures to manipulate data, and therefore more SQL service types are supported. The NuGet package Installation tool automatically creates a database for us, what if we want to use the original database? We only need to change the corresponding connection string, compile and start the ASP. NET Configuration tool, which will create several tables in our original database.
SQL Membership Provider Example of the controller/view we do not need any changes can be switched to universal provider after the normal operation, The call to the membership method is transferred internally by System.Web.Providers.DefaultProfileProvider in MVC, and there is no difference in how we write the program. It seems that universal provider does not bring much benefit, in fact, with the simplification of the database structure, we have great convenience to extend the profile, which is no longer discussed in depth.
Simple providerSimple provider is released with WebMatrix in the VS SP1, and universal provider uses the Entrity framework to manipulate the user information database, but the structure of the database is simpler and more flexible to configure. In VS2012 we use an Internet template to create a MVC4 project, and the project is configured to use simple provider. Only <authentication mode= "Forms" in Web. config, no longer contains membership provider information, Membership processing is handled directly in the controller using WebMatrix.WebData.WebSecurity. The Internet template creates code with full user functionality, which is not listed here.
The Internet template creates a filter named Initializesimplemembershipattribute, which is called once each time the application starts:
Websecurity.initializedatabaseconnection ("DefaultConnection", "UserProfile", "UserId", "UserName", Autocreatetables:true);
This method causes the database connection to initialize the user information, defaultconnection the connection string for the database, userpofile as the table name, UserID, and username respectively as the name of the field in the table for the user ID and user name, In other words, we only need one of the simplest tables with a user ID and a name of two fields, which can be set dynamically in any database, so the ASP. NET Configuration tool cannot be used to configure simple provider.
The Internet template creates the account controller, which contains a number of action methods to provide user registration, login, logout, and password change, basically called websecurity related methods to implement, such as the login call is Websecurity.login (). On the basis of the Internet template, we can easily customize profile, roles, and so on, here is no further, there is a very good article on how simple provider work, you can see http://weblogs.asp.net/ jgalloway/archive/2012/08/29/ Simplemembership-membership-providers-universal-providers-and-the-new-asp-net-4-5-web-forms-and-asp-net-mvc-4-templates.a Spx.
MVC5 has been released with VS2013 in 20,130 months, with a number of changes relative to MVC4, including the safety certifications described here. This article ends MVC4 and begins the journey of MVC5.
ASP. NET MVC 4 (13) forms-based authentication