notes : This article is about 【ASP.NET Identity Series of tutorials 】 The second part of . This series of tutorials details 、 complete 、 In depth introduction of Microsoft's ASP.NET Identity technology , Describes how to use ASP.NET Identity Realize the user management of the application , And implementation of application authentication and authorization and other related technologies , The translator hopes that this series of tutorials can become a master ASP.NET Identity A complete and valuable information of Technology . If readers can follow the description of the article , While reading 、 Practice at the same time 、 Understanding , There is bound to be an unexpected harvest ! I hope this series of blog articles can be highly praised by the majority of garden friends recommend .

Hide English
Chinese English control

14 Applying ASP.NET Identity
14 Application ASP.NET Identity

In this chapter, I show you how to apply ASP.NET Identity to authenticate and authorize the user accounts created in the previous chapter. I explain how the ASP.NET platform provides a foundation for authenticating requests and how ASP.NET Identity fits into that foundation to authenticate users and enforce authorization through roles. Table 14-1 summarizes this chapter.
This chapter will demonstrate how to ASP.NET Identity It is used to authenticate and authorize the user account created in the previous chapter . I will explain ASP.NET The platform is the foundation for authentication of requests , And explain ASP.NET Identity How to integrate this foundation to authenticate users , And enhancing authorization through roles . surface 14-1 It describes the outline of this chapter .

Table 14-1.Chapter Summary
surface 14-1. Summary of this chapter
Problem
problem
Solution
Solution
Listing
List number
Prepare an application for user authentication.
Prepare the application for user authentication
Apply the Authorize attribute to restrict access to action methods and define a controller to which users will be redirected to provide credentials.
Application Authorize Annotation properties to restrict access to action methods , And define a controller to redirect users , So that users can provide credentials
1–4
Authenticate a user.
Authenticated user
Check the name and password using the FindAsync method defined by the user manager class and create an implementation of the IIdentity interface using the CreateIdentityMethod. Set an authentication cookie for subsequent requests by calling the SignIn method defined by the authentication manager class.
Use the... Defined by the user manager class FindAsync Method to check the user name and password , And use CreateIdentityMethod Create a IIdentity Interface implementation . By calling the SignIn Method , Set authentication for subsequent requests Cookie.
5
Prepare an application for role-based authorization.
Prepare role based authorization applications
Create a role manager class and register it for instantiation in the OWIN startup class.
Create a role manager class , Register it as OWIN Start instantiation in class
6–8
Create and delete roles.
Create and delete roles
Use the CreateAsync and DeleteAsync methods defined by the role manager class.
Use the... Defined by the role manager class CreateAsync and DeleteAsync Method .
9–12
Manage role membership.
Managing role members
Use the AddToRoleAsync and RemoveFromRoleAsync methods defined by the user manager class.
Use the... Defined by the user manager class AddToRoleAsync and RemoveFromRoleAsync Method
13–15
Use roles for authorization.
Using roles for authorization
Set the Roles property of the Authorize attribute.
Set up Authorize Annotation properties Roles attribute
16–19
Seed the database with initial content.
The content planting database will be initialized
Use the database context initialization class.
Use the initialization class of the database context
20, 21

14.1 Preparing the Example Project
14.1 Prepare sample projects

In this chapter, I am going to continue working on the Users project I created in Chapter 13. No changes to the application components are required.
In this chapter , I intend to continue to use the second 13 Chapter created by Users project , There is no need to modify the components of the application .

14.2 Authenticating Users
14.2 Authenticated user

The most fundamental activity for ASP.NET Identity is to authenticate users, and in this section, I explain and demonstrate how this is done. Table 14-2 puts authentication into context.
ASP.NET Identity The most basic activity is to authenticate users , In this section , I'll explain and demonstrate how it works . surface 14-2 Describes the case of Authentication .

Table 14-2. Putting Authentication in Context
surface 14-2. Authentication situation
Question
problem
Answer
answer
What is it?
What is certification ?
Authentication validates credentials provided by users. Once the user is authenticated, requests that originate from the browser contain a cookie that represents the user identity.
Authentication is to verify the credentials provided by the user . Once the user has been authenticated , The request from the browser will contain a Cookie.
Why should I care?
Why care about it ?
Authentication is how you check the identity of your users and is the first step toward restricting access to sensitive parts of the application.
Authentication is the way you check your user ID , It's also the first step in limiting access to sensitive parts of the application .
How is it used by the MVC framework?
How to be in MVC Use it in the framework ?
Authentication features are accessed through the Authorize attribute, which is applied to controllers and action methods in order to restrict access to authenticated users.
The authentication feature is through Authorize Annotation property , Apply this annotation property to controllers and action methods , The goal is to limit access to authenticated users .

Tip I use names and passwords stored in the ASP.NET Identity database in this chapter. In Chapter 15, I demonstrate how ASP.NET Identity can be used to authenticate users with a service from Google (Identity also supports authentication for Microsoft, Facebook, and Twitter accounts).
Tips : In this chapter, we will use the ASP.NET Identity The user name and password in the database . In the 15 In this chapter, we will demonstrate how to ASP.NET Identity Used for authentication Google Users of the service (Identity Also supports the Microsoft、Facebook as well as Twitter Account authentication ).

14.2.1 Understanding the Authentication/Authorization Process
14.2.1 Understanding Certification / The authorization process

The ASP.NET Identity system integrates into the ASP.NET platform, which means you use the standard MVC framework techniques to control access to action methods, such as the Authorize attribute. In this section, I am going to apply basic restrictions to the Index action method in the Home controller and then implement the features that allow users to identify themselves so they can gain access to it. Listing 14-1 shows how I have applied the Authorize attribute to the Home controller.
ASP.NET Identity The system is integrated into ASP.NET platform , That means you can use standard MVC Framework technology to control access to action methods , For example, using Authorize Annotation Properties . In this section , I plan to Home Under control Index Use basic restrictions on movement methods , And then let users identify themselves , So that they can access . detailed list 14-1 Demonstrates how to put Authorize Annotation properties apply to Home controller .

Listing 14-1. Securing the Home Controller
detailed list 14-1. The implementation of Home The safety of the controller

using System.Web.Mvc;
using System.Collections.Generic;
namespace Users.Controllers {
public class HomeController : Controller {
[Authorize]
public ActionResult Index() {
Dictionary<string, object> data
= new Dictionary<string, object>();
data.Add("Placeholder", "Placeholder");
return View(data);
}
}
}

Using the Authorize attribute in this way is the most general form of authorization and restricts access to the Index action methods to requests that are made by users who have been authenticated by the application.
In this way Authorize Annotation attributes are the most common form of Authorization , It limits the right to Index Access to action methods , The request sent by the user to the action method must be an authenticated user of the application .

If you start the application and request a URL that targets the Index action on the Home controller (/Home/Index, /Home, or just /), you will see the error shown by Figure 14-1.
If you start the application , And ask for Home The controller Index Action oriented URL(/Home/Index、/Home or /), You'll see this 14-1 The error shown .

Figure 14-1. Requesting a protected URL
chart 14-1. Ask for a protected URL

The ASP.NET platform provides some useful information about the user through the HttpContext object, which is used by the Authorize attribute to check the status of the current request and see whether the user has been authenticated. The HttpContext.User property returns an implementation of the IPrincipal interface, which is defined in the System.Security.Principal namespace. The IPrincipal interface defines the property and method shown in Table 14-3.
ASP.NET The platform passes HttpContext Object provides some useful information about the user , The object is created by Authorize Annotation properties use , To check the status of the current request , Check whether the user has been authenticated .HttpContext.User Property returns IPrincipal Interface implementation , The interface is in System.Security.Principal Namespace .IPrincipal The interface is defined as shown in table 14-3 Properties and methods shown in .

Table 14-3. The Members Defined by the IPrincipal Interface
surface 14-3. IPrincipal Members defined by the interface
Name
name
Description
describe
Identity Returns an implementation of the IIdentity interface that describes the user associated with the request.
return IIdentity Interface implementation , It describes the user associated with the request
IsInRole(role) Returns true if the user is a member of the specified role. See the “Authorizing Users with Roles” section for details of managing authorizations with roles.
If the user is a member of a specified role , Then return to true. See “ Authorize users by role ” Section , It describes the details of authorization management by role

The implementation of IIdentity interface returned by the IPrincipal.Identity property provides some basic, but useful, information about the current user through the properties I have described in Table 14-4.
from IPrincipal.Identity Property returns IIdentity The interface implementation provides some basic but useful information about the current user through some attributes , surface 14-4 Describes these properties .

Table 14-4. The Properties Defined by the IIdentity Interface
surface 14-4. IIdentity Interface defined properties
Name
name
Description
describe
AuthenticationType Returns a string that describes the mechanism used to authenticate the user
Returns a string , The mechanism for authenticating users is described
IsAuthenticated Returns true if the user has been authenticated
If the user has been authenticated , return true.
Name Returns the name of the current user
Returns the user name of the current user

Tip In Chapter 15 I describe the implementation class that ASP.NET Identity uses for the IIdentity interface, which is called ClaimsIdentity.
Tips : The first 15 The chapter will describe ASP.NET Identity be used for IIdentity Implementation class of interface , Its name is ClaimsIdentity.

ASP.NET Identity contains a module that handles the AuthenticateRequest life-cycle event, which I described in Chapter 3, and uses the cookies sent by the browser to establish whether the user has been authenticated. I’ll show you how these cookies are created shortly. If the user is authenticated, the ASP.NET framework module sets the value of the IIdentity.IsAuthenticated property to true and otherwise sets it to false. (I have yet to implement the feature that will allow users to authenticate, which means that the value of the IsAuthenticated property is always false in the example application.)
ASP.NET Identity Contains a process AuthenticateRequest Life cycle events ( The first 3 Zhang once described ) Module , And use the browser to send Cookie Confirm whether the user has been authenticated . I'll show you how to create these soon Cookie. If the user has been authenticated , this ASP.NET The framework module will IIdentity.IsAuthenticated Property is set to true, Otherwise set to false.( At the moment, the user authentication feature has not been implemented , This means that in this sample application ,IsAuthenticated The value of the property is always false.)

The Authorize module checks the value of the IsAuthenticated property and, finding that the user isn’t authenticated, sets the result status code to 401 and terminates the request. At this point, the ASP.NET Identity module intercepts the request and redirects the user to the /Account/Login URL. This is the URL that I defined in the IdentityConfig class, which I specified in Chapter 13 as the OWIN startup class, like this:
Authorize Module check IsAuthenticated The value of the property , You will find that the user is not authenticated , So set the result status code to 401( unauthorized ), And terminate the request . But at this point ( Here is ASP.NET Identity The entry point in the request lifecycle —— translator's note ),ASP.NET Identity The module intercepts the request , And redirect the user to /Account/Login URL. I am here IdentityConfig This... Is already defined in the class URL,IdentityConfig It's No 13 Chapter 2 OWIN Start class , As shown below :

using Microsoft.AspNet.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;
using Users.Infrastructure;
namespace Users {
public class IdentityConfig {
public void Configuration(IAppBuilder app) {
app.CreatePerOwinContext<AppUserManager>(AppUserManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions {
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
});
}
}
}

The browser requests the /Account/Login URL, but since it doesn’t correspond to any controller or action in the example project, the server returns a 404 – Not Found response, leading to the error message shown in Figure 14-1.
Browser request /Account/Login when , But because there is no corresponding controller or action in the sample project , The server returned “404 – Not found ” Respond to , This leads to 14-1 Error message shown in .

14.2.2 Preparing to Implement Authentication
14.2.2 Preparation for certification

Even though the request ends in an error message, the request in the previous section illustrates how the ASP.NET Identity system fits into the standard ASP.NET request life cycle. The next step is to implement a controller that will receive requests for the /Account/Login URL and authenticate the user. I started by adding a new model class to the UserViewModels.cs file, as shown in Listing 14-2.
Although the request ended with an error message , But the request in the previous section has outlined ASP.NET Identity How the system cuts into the standard ASP.NET Request lifecycle . The next step is to implement a controller , Use it to receive information about /Account/Login URL Request , And authenticate users . I first in UserViewModels.cs A model class is added to the file , Like the list 14-2 Shown .

Listing 14-2. Adding a New Model Class to the UserViewModels.cs File
detailed list 14-2. stay UserViewModels.cs Add a new model class to the file

using System.ComponentModel.DataAnnotations; 
namespace Users.Models {
public class CreateModel {
[Required]
public string Name { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string Password { get; set; }
}
public class LoginModel {
[Required]
public string Name { get; set; }
[Required]
public string Password { get; set; }
}

}

The new model has Name and Password properties, both of which are decorated with the Required attribute so that I can use model validation to check that the user has provided values.
The new model has Name and Password attribute , Both use Required Annotation properties are annotated , So that I can use model validation to check whether the user provided the values of these properties .

Tip In a real project, I would use client-side validation to check that the user has provided name and password values before submitting the form to the server, but I am going to keep things focused on identity and the server-side functionality in this chapter. See Pro ASP.NET MVC 5 for details of client-side form validation.
Tips : In a real project , I'll wait until the user delivers the form to the server , Use client authentication to check that the user has provided values for the user name and password , But in this chapter , I'm going to focus on identity and server-side functionality . For details of client form validation, please refer to Pro ASP.NET MVC 5 A Book .

I added an Account controller to the project, as shown in Listing 14-3, with Login action methods to collect and process the user’s credentials. I have not implemented the authentication logic in the listing because I am going to define the view and then walk through the process of validating user credentials and signing users into the application.
I added a Account controller , Like the list 14-3 Shown , It has Login Action method , To collect and process user credentials . The manifest does not yet implement the authentication logic , Because I'm going to define views first , And then implement the process of verifying the user's credentials , And let the user check in the application .

Listing 14-3. The Contents of the AccountController.cs File
detailed list 14-3. AccountController.cs The content of the document

using System.Threading.Tasks;
using System.Web.Mvc;
using Users.Models;
namespace Users.Controllers {
[Authorize]
public class AccountController : Controller {
[AllowAnonymous]
public ActionResult Login(string returnUrl) {
if (ModelState.IsValid) {
}
ViewBag.returnUrl = returnUrl;
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginModel details, string returnUrl) {
return View(details);
}
}
}

Even though it doesn’t authenticate users yet, the Account controller contains some useful infrastructure that I want to explain separately from the ASP.NET Identity code that I’ll add to the Login action method shortly.
Even though it hasn't authenticated users yet , but Account The controller already contains some useful infrastructure , I want to pass. ASP.NET Identity The code interprets these structures separately , It will soon be in Login Add this code to the action method .

First, notice that both versions of the Login action method take an argument called returnUrl. When a user requests a restricted URL, they are redirected to the /Account/Login URL with a query string that specifies the URL that the user should be sent back to once they have been authenticated. You can see this if you start the application and request the /Home/Index URL. Your browser will be redirected, like this:
First of all, pay attention to Login There are two versions of action methods , They all have a name called returnUrl Parameters of . When a user requests a restricted URL when , They were redirected to /Account/Login URL On , With a query string , This string specifies the... That will be returned to the user once the user is authenticated URL, As shown below :

/Account/Login?ReturnUrl=%2FHome%2FIndex

The value of the ReturnUrl query string parameter allows me to redirect the user so that navigating between open and secured parts of the application is a smooth and seamless process.
ReturnUrl Querying the value of the string parameter allows me to redirect users , Make the navigation between the public and private parts of the application a smooth and seamless process .

Next, notice the attributes that I have applied to the Account controller. Controllers that manage user accounts contain functionality that should be available only to authenticated users, such as password reset, for example. To that end, I have applied the Authorize attribute to the controller class and then used the AllowAnonymous attribute on the individual action methods. This restricts action methods to authenticated users by default but allows unauthenticated users to log in to the application.
The next thing to pay attention to is to apply it to Account Annotation properties of the controller . The controller for managing user accounts contains functions that can only be used by authenticated users , For example, password reset . So , I used... In the controller class Authorize Annotation Properties , And then I used it in individual action methods AllowAnonymous Annotation Properties . This limits these action methods to authenticated users by default , But it also allows unauthorized users to log in to the application .

Finally, I have applied the ValidateAntiForgeryToken attribute, which works in conjunction with the Html.AntiForgeryToken helper method in the view and guards against cross-site request forgery. Cross-site forgery exploits the trust that your user has for your application and it is especially important to use the helper and attribute for authentication requests.
Last but not least , I used ValidateAntiForgeryToken Annotation Properties , This property is the same as Html.AntiForgeryToken Auxiliary methods work together , prevent Cross-Site Request Forgery(CSRF, Cross Site Request Forgery ) The attack of .CSRF Will take advantage of the application's trust in users , So using this helper and annotation properties is particularly important for authentication requests .

Tip you can learn more about cross-site request forgery at http://en.wikipedia.org/wiki/Cross-site_request_forgery.
Tips : More about CSRF Information about , see also http://en.wikipedia.org/wiki/Cross-site_request_forgery.

My last preparatory step is to create the view that will be rendered to gather credentials from the user. Listing 14-4 shows the contents of the Views/Account/Login.cshtml file, which I created by right-clicking the Index action method and selecting Add View from the pop-up menu.
The final preparation step is to create a view , To collect credentials from users . detailed list 14-4 Shows Views/Account/Login.cshtml The content of the document , This is by right clicking Index Action method , Then select... From the pop-up menu “Add View( Add view )” And created .

Listing 14-4. The Contents of the Login.cshtml File
detailed list 14-4. Login.cshtml The content of the document

@model Users.Models.LoginModel
@{ ViewBag.Title = "Login";}
<h2>Log In</h2>
@Html.ValidationSummary()
@using (Html.BeginForm()) {
@Html.AntiForgeryToken();
<input type="hidden" name="returnUrl" value="@ViewBag.returnUrl" />
<div class="form-group">
<label>Name</label>
@Html.TextBoxFor(x => x.Name, new { @class = "form-control" })
</div>
<div class="form-group">
<label>Password</label>
@Html.PasswordFor(x => x.Password, new { @class = "form-control" })
</div>
<button class="btn btn-primary" type="submit">Log In</button>
}

The only notable aspects of this view are using the Html.AntiForgeryToken helper and creating a hidden input element to preserve the returnUrl argument. In all other respects, this is a standard Razor view, but it completes the preparations for authentication and demonstrates the way that unauthenticated requests are intercepted and redirected. To test the new controller, start the application and request the /Home/Index URL. You will be redirected to the /Account/Login URL, as shown in Figure 14-2.
The only thing to note about this view is that it uses Html.AntiForgeryToken Auxiliary device , And create a hidden input Elements , To protect returnUrl Parameters . In other ways , It's a standard Razor View , But it does the preparation for certification , And can demonstrate the situation of intercepted and redirected unauthenticated requests . To test this new controller , Start the application , And ask for /Home/Index. You will be redirected to /Account/Login, Pictured 14-2 Shown .

Figure 14-2. Prompting the user for authentication credentials
chart 14-2. Prompt the user to enter authentication credentials

14.2.3 Adding User Authentication
14.2.3 Add user authentication

Requests for protected URLs are being correctly redirected to the Account controller, but the credentials provided by the user are not yet used for authentication. In Listing 14-5, you can see how I have completed the implementation of the Login action.
Send to protected URL Will be correctly redirected to Account controller , But the credentials provided by the user have not yet been used for authentication . From the list 14-5 You can see how to do it Login The realization of action .

Listing 14-5. Adding Authentication to the AccountController.cs File
detailed list 14-5. stay AccountController.cs Add authentication to the file

using System.Threading.Tasks;
using System.Web.Mvc;
using Users.Models;
using Microsoft.Owin.Security;
using System.Security.Claims;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Users.Infrastructure;
using System.Web;

namespace Users.Controllers {
[Authorize]
public class AccountController : Controller {
[AllowAnonymous]
public ActionResult Login(string returnUrl) {
ViewBag.returnUrl = returnUrl;
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginModel details, string returnUrl) {
if (ModelState.IsValid) {
AppUser user = await UserManager.FindAsync(details.Name,
details.Password);
if (user == null) {
ModelState.AddModelError("", "Invalid name or password.");
} else {
ClaimsIdentity ident = await UserManager.CreateIdentityAsync(user,
DefaultAuthenticationTypes.ApplicationCookie);
AuthManager.SignOut();
AuthManager.SignIn(new AuthenticationProperties {
IsPersistent = false}, ident);
return Redirect(returnUrl);
}
}
ViewBag.returnUrl = returnUrl;
return View(details);
}
private IAuthenticationManager AuthManager {
get {
return HttpContext.GetOwinContext().Authentication;
}
}
private AppUserManager UserManager {
get {
return HttpContext.GetOwinContext().GetUserManager<AppUserManager>();
}
}

}
}

The simplest part is checking the credentials, which I do through the FindAsync method of the AppUserManager class, which you will remember as the user manager class from Chapter 13:
The simplest part is checking the credentials , This is through AppUserManager Class FindAsync How to do it , You might remember ,AppUserManager It's No 13 Chapter user manager class .

...
AppUser user = await UserManager.FindAsync(details.Name, details.Password);
...

I will be using the AppUserManager class repeatedly in the Account controller, so I defined a property called UserManager that returns the instance of the class using the GetOwinContext extension method for the HttpContext class, just as I did for the Admin controller in Chapter 13.
I will be in Account Used repeatedly in the controller AppUserManager class , So we define a UserManager attribute , It USES HttpContext Class GetOwinContext Extend the method to return AppUserManager Class .

The FindAsync method takes the account name and password supplied by the user and returns an instance of the user class (AppUser in the example application) if the user account exists and if the password is correct. If there is no such account or the password doesn’t match the one stored in the database, then the FindAsync method returns null, in which case I add an error to the model state that tells the user that something went wrong.
FindAsync Method takes the account name and password provided by the user as parameters , And exists in the user account And When the password is correct , Returns a user class ( In this case AppUser) Example . If you don't have this account , Or it doesn't match what's stored in the database , that FindAsync Method returns null (null), When this happens , I added an error message to the model state , Tell the user that something may have gone wrong .

If the FindAsync method does return an AppUser object, then I need to create the cookie that the browser will send in subsequent requests to show they are authenticated. Here are the relevant statements:
If FindAsync Method does return AppUser object , Then you need to create Cookie, The browser will send this in subsequent requests Cookie, Show that they are certified . Here are the sentences :

...
ClaimsIdentity ident = await UserManager.CreateIdentityAsync(user,
DefaultAuthenticationTypes.ApplicationCookie);
AuthManager.SignOut();
AuthManager.SignIn(new AuthenticationProperties {IsPersistent = false}, ident);
return Redirect(returnUrl);
...

The first step is to create a ClaimsIdentity object that identifies the user. The ClaimsIdentity class is the ASP.NET Identity implementation of the IIdentity interface that I described in Table 14-4 and that you can see used in the “Using Roles for Authorization” section later in this chapter.
The first step is to create a user ID ClaimsIdentity object .ClaimsIdentity Classes are tables 14-4 Described as IIdentity Interface ASP.NET Identity Realization , You can see later in this chapter “ Use role authorization ” See its use in the section .

Tip Don’t worry about why the class is called ClaimsIdentity at the moment. I explain what claims are and how they can be used in Chapter 15.
Tips : You don't have to worry about why this class calls ClaimsIdentity, The first 15 The chapter will explain what a statement is (Claims), And how to use them .

Instances of ClaimsIdentity are created by calling the user manager CreateIdentityAsync method, passing in a user object and a value from the DefaultAuthenticationTypes enumeration. The ApplicationCookie value is used when working with individual user accounts.
ClaimsIdentity The instance of is calling the user manager CreateIdentityAsync Method , A user object and DefaultAuthenticationTypes Enumeration . When working with individual user accounts , use ApplicationCookie value .

The next step is to invalidate any existing authentication cookies and create the new one. I defined the AuthManager property in the controller because I’ll need access to the object it provides repeatedly as I build the functionality in this chapter. The property returns an implementation of the IAuthenticationManager interface that is responsible for performing common authentication options. I have described the most useful methods provided by the IAuthenticationManager interface in Table 14-5.
The next step is to get the certified Cookie invalid , And create a new Cookie. I defined in this controller AuthManager attribute , Because in the process of establishing the function of this chapter , You need to repeatedly access the objects it provides . This property returns IAuthenticationManager Interface implementation , It's responsible for performing the normal authentication options . surface 14-5 Described in IAuthenticationManager The most useful method provided by the interface .

Table 14-5. The Most Useful Methods Defined by the IAuthenticationManager Interface
surface 14-5. IAuthenticationManager The most useful method of interface definition
Name
name
Description
describe
SignIn(options, identity) Signs the user in, which generally means creating the cookie that identifies authenticated requests
Check in users , This usually means creating a Cookie
SignOut() Signs the user out, which generally means invalidating the cookie that identifies authenticated requests
Check out the user , This usually means making the identification of the authenticated user Cookie invalid

The arguments to the SignIn method are an AuthenticationProperties object that configures the authentication process and the ClaimsIdentity object. I set the IsPersistent property defined by the AuthenticationProperties object to true to make the authentication cookie persistent at the browser, meaning that the user doesn’t have to authenticate again when starting a new session. (There are other properties defined by the AuthenticationProperties class, but the IsPersistent property is the only one that is widely used at the moment.)
SignIn The parameter of the method is a AuthenticationProperties object , To configure the authentication process and ClaimsIdentity object . I will AuthenticationProperties Object defined IsPersistent Property is set to true, So that authentication Cookie Persistent in browsers , This means that when a user starts a new session , No need to authenticate again .(AuthenticationProperties Class also defines some other properties , but IsPersistent Attribute is the only one that needs to be widely used at the moment .)

The final step is to redirect the user to the URL they requested before the authentication process started, which I do by calling the Redirect method.
The final step is to redirect the user to what they requested before the authentication process started URL, This is done by calling Redirect Method .

CONSIDERING TWO-FACTOR AUTHENTICATION
Consider two factor authentication

I have performed single-factor authentication in this chapter, which is where the user is able to authenticate using a single piece of information known to them in advance: the password.
In this chapter , I have single factor certification , On this occasion , Users only need to use a single piece of information they foresee : password , Then it can be certified .

ASP.NET Identity also supports two-factor authentication, where the user needs something extra, usually something that is given to the user at the moment they want to authenticate. The most common examples are a value from a SecureID token or an authentication code that is sent as an e-mail or text message (strictly speaking, the two factors can be anything, including fingerprints, iris scans, and voice recognition, although these are options that are rarely required for most web applications).
ASP.NET Identity It also supports two factor authentication , under these circumstances , Users need some additional information , It's usually a message sent to them when they need certification . The most common example is SecureID The value of the token , Or through E-mail Authentication code or text message sent ( Strictly speaking , The second factor can be anything , Including fingerprints 、 Pupil scanning 、 Voice recognition, etc , Although these are in most Web Options rarely used in applications .)

Security is increased because an attacker needs to know the user’s password and have access to whatever provides the second factor, such an e-mail account or cell phone.
This increases security , Because the attacker needs to know the user's password , also Be able to access the client that provides the second factor , Such as E-mail Accounts or mobile phones, etc .

I don’t show two-factor authentication in the book for two reasons. The first is that it requires a lot of preparatory work, such as setting up the infrastructure that distributes the second-factor e-mails and texts and implementing the validation logic, all of which is beyond the scope of this book.
There are two reasons why this chapter does not demonstrate two factor authentication . The first is that it requires a lot of preparation , For example, to build an infrastructure to distribute the second factor's mail and text , And implement verification logic , These are beyond the scope of this book .

The second reason is that two-factor authentication forces the user to remember to jump through an additional hoop to authenticate, such as remembering their phone or keeping a security token nearby, something that isn’t always appropriate for web applications. I carried a SecureID token of one sort or another for more than a decade in various jobs, and I lost count of the number of times that I couldn’t log in to an employer’s system because I left the token at home.
The second reason is that dual factor authentication forces users to remember an additional authentication token , for example , Remember their phone number , Or take a security token with you , This is right Web For applications , It's not always appropriate . I have carried this or that in all kinds of work for more than ten years SecureID token , And I couldn't log in to the employee system countless times , Because I left my token at home .

If you are interested in two-factor security, then I recommend relying on a third-party provider such as Google for authentication, which allows the user to choose whether they want the additional security (and inconvenience) that two-factor authentication provides. I demonstrate third-party authentication in Chapter 15.
If you're interested in two factor security , So I suggest you rely on a third party provider , for example Google authentication , It allows users to choose whether they want to use the additional security provided by two factors ( And it's inconvenient ). The first 15 Chapter will demonstrate third party authentication .

14.2.4 Testing Authentication
14.2.4 Test certification

To test user authentication, start the application and request the /Home/Index URL. When redirected to the /Account/Login URL, enter the details of one of the users I listed at the start of the chapter (for instance, the name joe and the password MySecret). Click the Log In button, and your browser will be redirected back to the /Home/Index URL, but this time it will submit the authentication cookie that grants it access to the action method, as shown in Figure 14-3.
To test user authentication , Start the application , And ask for /Home/Index URL. When redirected to /Account/Login URL when , Enter the details of a user listed at the beginning of this chapter ( for example , The name is joe, The password is MySecret). Click on “Log In( Sign in )” Button , Your browser will be redirected , go back to /Home/Index URL, But this time it will be certified Cookie, Is granted access to the action method , Pictured 14-3 Shown .

Figure 14-3. Authenticating a user
chart 14-3. Authenticated user

Tip You can use the browser F12 tools to see the cookies that are used to identify authenticated requests.
Tips : You can use the browser F12 Tools , See the... Used to identify the authenticated request Cookie.

14.3 Authorizing Users with Roles
14.3 Authorize users by role

In the previous section, I applied the Authorize attribute in its most basic form, which allows any authenticated user to execute the action method. In this section, I will show you how to refine authorization to give finer-grained control over which users can perform which actions. Table 14-6 puts authorization in context.
The last section uses... In its most basic form Authorize Annotation Properties , This allows any authenticated user to perform action methods . In this section , We'll show you how to refine Authorization , In order to have more fine-grained control over the actions that users can perform . surface 14-6 Describes the authorization situation .

Table 14-6. Putting Authorization in Context
surface 16-4. Authorization situation
Question
problem
Answer
answer
What is it?
What is Authorization ?
Authorization is the process of granting access to controllers and action methods to certain users, generally based on role membership.
Authorization is to limit the permitted access of controllers and actions to specific users , Usually role based members
Why should I care?
Why care about it ?
Without roles, you can differentiate only between users who are authenticated and those who are not. Most applications will have different types of users, such as customers and administrators.
No role , You can only distinguish between authenticated users and non authenticated users . Most applications have different types of users , For example, customers and administrators
How is it used by the MVC framework?
How to be in MVC Use it in the framework ?
Roles are used to enforce authorization through the Authorize attribute, which is applied to controllers and action methods.
The character passes through Authorize Annotation properties can be used to enforce Authorization ,Authorize It can be used in controller and action method

Tip In Chapter 15, I show you a different approach to authorization using claims, which are an advanced ASP.NET Identity feature.
Tips : The first 15 The chapter will use Claims( Statement ) To demonstrate different authorization methods ,Claims It's a kind of advanced ASP.NET Identity characteristic .

14.3.1 Adding Support for Roles
14.3.1 Add role support

ASP.NET Identity provides a strongly typed base class for accessing and managing roles called RoleManager<T> , where T is the implementation of the IRole interface supported by the storage mechanism used to represent roles. The Entity Framework uses a class called IdentityRole to implement the IRole interface, which defines the properties shown in Table 14-7.
ASP.NET Identity Provides a strongly typed base class for accessing and managing roles , be called RoleManager<T> , among T yes IRole Interface implementation , This implementation is supported by the storage mechanism used to represent roles .Entity Framework Realized IRole Interface , Using a name called IdentityRole Class , It defines as shown in table 14-7 Properties shown .

Table 14-7. The Properties Defined by the IdentityRole Class
surface 14-7. IdentityRole Class
Name
name
Description
describe
Id Defines the unique identifier for the role
Define the unique identifier of the role
Name Defines the name of the role
Define the role name
Users Returns a collection of IdentityUserRole objects that represents the members of the role
Returns a... Representing a member of a role IdentityUserRole A collection of objects

I don’t want to leak references to the IdentityRole class throughout my application because it ties me to the Entity Framework for storing role data, so I start by creating an application-specific role class that is derived from IdentityRole. I added a class file called AppRole.cs to the Models folder and used it to define the class shown in Listing 14-6.
I don't want to expose the whole app to IdentityRole Class reference , Because it's for storing character data , Bind me to Entity Framework. So , I first created an application specific role class , It was born. IdentityRole. I am here Models A class file has been added to the folder , The name is AppRole.cs, And use it to define this class , Like the list 14-6 Shown .

Listing 14-6. The Contents of the AppRole.cs File
detailed list 14-6. AppRole The content of the document

using Microsoft.AspNet.Identity.EntityFramework; 
namespace Users.Models {
public class AppRole : IdentityRole {
public AppRole() : base() {}
public AppRole(string name) : base(name) { }
}
}

The RoleManager<T> class operates on instances of the IRole implementation class through the methods and properties shown in Table 14-8.
RoleManager<T> Class through table 14-8 The methods and properties shown in are for IRole Implement the instance of the class to operate .

Table 14-8. The Members Defined by the RoleManager<T> Class
surface 14-8. RoleManager<T> Members of a class definition
Name
name
Description
describe
CreateAsync(role) Creates a new role
Create a new character
DeleteAsync(role) Deletes the specified role
Delete the specified role
FindByIdAsync(id) Finds a role by its ID
Find the specified ID Role
FindByNameAsync(name) Finds a role by its name
Find the role with the specified name
RoleExistsAsync(name) Returns true if a role with the specified name exists
If there is a role with the specified name , return true
UpdateAsync(role) Stores changes to the specified role
Store changes to specified roles
Roles Returns an enumeration of the roles that have been defined
Returns an enumeration of defined roles

These methods follow the same basic pattern of theUserManager<T> class that I described in Chapter 13. Following the pattern I used for managing users, I added a class file called AppRoleManager.cs to the Infrastructure folder and used it to define the class shown in Listing 14-7.
These methods are the same as the second 13 Chapter one describes UserManager<T> Classes have the same basic pattern . According to the model adopted for managing users , I am here Infrastructure A class file has been added to the folder , The name is AppRoleManager.cs, It's used to define things like listing 14-7 The class shown in .

Listing 14-7. The Contents of the AppRoleManager.cs File
detailed list 14-7. AppRoleManager.cs The content of the document

using System;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin; using Users.Models;
namespace Users.Infrastructure {
public class AppRoleManager : RoleManager<AppRole>, IDisposable {
public AppRoleManager(RoleStore<AppRole> store) : base(store) { }
public static AppRoleManager Create(
IdentityFactoryOptions<AppRoleManager> options,
IOwinContext context) {
return new AppRoleManager(new
RoleStore<AppRole>(context.Get<AppIdentityDbContext>()));
}
}
}

This class defines a Create method that will allow the OWIN start class to create instances for each request where Identity data is accessed, which means I don’t have to disseminate details of how role data is stored throughout the application. I can just obtain and operate on instances of the AppRoleManager class. You can see how I have registered the role manager class with the OWIN start class, IdentityConfig, in Listing 14-8. This ensures that instances of the AppRoleManager class are created using the same Entity Framework database context that is used for the AppUserManager class.
This class defines a Create Method , It makes OWIN The startup class can be used for every access Identity Data requests create instances , This means that throughout the application , I don't have to spread the details of how to store character data , But you can get AppRoleManager Class , And operate on it . In the list 14-8 You can see how to use OWIN Start class (IdentityConfig) To register the role manager class . This ensures that , Can be used with AppUserManager Class uses the same Entity Framework Database context , To create AppRoleManager Class .

Listing 14-8. Creating Instances of the AppRoleManager Class in the IdentityConfig.cs File
detailed list 14-8. stay IdentityConfig.cs Create in file AppRoleManager Class

using Microsoft.AspNet.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;
using Users.Infrastructure;
namespace Users {
public class IdentityConfig {
public void Configuration(IAppBuilder app) {
app.CreatePerOwinContext<AppIdentityDbContext>(AppIdentityDbContext.Create);
app.CreatePerOwinContext<AppUserManager>(AppUserManager.Create);
app.CreatePerOwinContext<AppRoleManager>(AppRoleManager.Create);

app.UseCookieAuthentication(new CookieAuthenticationOptions {
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
});
}
}
}

14.3.2 Creating and Deleting Roles
14.3.2 Create and delete roles

Having prepared the application for working with roles, I am going to create an administration tool for managing them. I will start the basics and define action methods and views that allow roles to be created and deleted. I added a controller called RoleAdmin to the project, which you can see in Listing 14-9.
Now you're ready for the application to use roles , I'm going to create a management tool to manage roles . Start with the basics , Define action methods and views that can create and delete characters . I added a controller to the project , The name is RoleAdmin, Like the list 14-9 Shown .

Listing 14-9. The Contents of the RoleAdminController.cs File
detailed list 14-9. RoleAdminController.cs The content of the document

using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Threading.Tasks;
using System.Web; using System.Web.Mvc; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin;
using Users.Infrastructure; using Users.Models;
namespace Users.Controllers {
public class RoleAdminController : Controller {
public ActionResult Index() {
return View(RoleManager.Roles);
}
public ActionResult Create() {
return View();
}
[HttpPost]
public async Task<ActionResult> Create([Required]string name) {
if (ModelState.IsValid) {
IdentityResult result
= await RoleManager.CreateAsync(new AppRole(name));
if (result.Succeeded) {
return RedirectToAction("Index");
} else {
AddErrorsFromResult(result);
}
}
return View(name);
}
[HttpPost]
public async Task<ActionResult> Delete(string id) {
AppRole role = await RoleManager.FindByIdAsync(id);
if (role != null) {
IdentityResult result = await RoleManager.DeleteAsync(role);
if (result.Succeeded) {
return RedirectToAction("Index");
} else {
return View("Error", result.Errors);
}
} else {
return View("Error", new string[] { "Role Not Found" });
}
}
private void AddErrorsFromResult(IdentityResult result) {
foreach (string error in result.Errors) {
ModelState.AddModelError("", error);
}
}
private AppUserManager UserManager {
get {
return HttpContext.GetOwinContext().GetUserManager<AppUserManager>();
}
}
private AppRoleManager RoleManager {
get {
return HttpContext.GetOwinContext().GetUserManager<AppRoleManager>();
}
}
}
}

I have applied many of the same techniques that I used in the Admin controller in Chapter 13, including a UserManager property that obtains an instance of the AppUserManager class and an AddErrorsFromResult method that processes the errors reported in an IdentityResult object and adds them to the model state.
There's a lot of use of 13 In the chapter Admin The same technology used by the controller , Including a UserManager attribute , Used to get AppUserManager Class ; And a AddErrorsFromResult Method , Used for processing IdentityResult Object , And add the message to the model state .

I have also defined a RoleManager property that obtains an instance of the AppRoleManager class, which I used in the action methods to obtain and manipulate the roles in the application. I am not going to describe the action methods in detail because they follow the same pattern I used in Chapter 13, using the AppRoleManager class in place of AppUserManager and calling the methods I described in Table 14-8.
I also defined RoleManager attribute , Used to obtain AppRoleManager Class , Use this instance to obtain and maintain the role of the application in the action method . I'm not going to go into the details of these movements , Because they follow the same rules as 13 The same pattern , In the use of AppUserManager Used in AppRoleManager class , It's the table that's called 14-8 The method in .

14.3.3 Creating the Views
14.3.3 Create view

The views for the RoleAdmin controller are standard HTML and Razor markup, but I have included them in this chapter so that you can re-create the example. I want to display the names of the users who are members of each role. The Entity Framework IdentityRole class defines a Users property that returns a collection of IdentityUserRole user objects representing the members of the role. Each IdentityUserRole object has a UserId property that returns the unique ID of a user, and I want to get the username for each ID. I added a class file called IdentityHelpers.cs to the Infrastructure folder and used it to define the class shown in Listing 14-10.
RoleAdmin The view of the controller is standard HTML and Razor Mark , But I still include them in this chapter , So that you can reconstruct the examples in this chapter . I want to show the user names of the members in each role .Entity Framework Of IdentityRole One is defined in the class Users attribute , It can return... That represents a member of a role IdentityUserRole Collection of user objects . every last IdentityUserRole Objects all have one UserId attribute , It returns a user's unique ID, however , What I hope to get is every ID The corresponding user name . I am here Infrastructure A class file has been added to the folder , The name is IdentityHelpers.cs, It's used to define things like listing 14-10 The class shown in .

Listing 14-10. The Contents of the IdentityHelpers.cs File
detailed list 14-10. IdentityHelpers.cs The content of the document

using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity.Owin;
namespace Users.Infrastructure {
public static class IdentityHelpers {
public static MvcHtmlString GetUserName(this HtmlHelper html, string id) {
AppUserManager mgr
= HttpContext.Current.GetOwinContext().GetUserManager<AppUserManager>();
return new MvcHtmlString(mgr.FindByIdAsync(id).Result.UserName);
}
}
}

Custom HTML helper methods are defined as extensions on the HtmlHelper class. My helper, which is called GetUsername, takes a string argument containing a user ID, obtains an instance of the AppUserManager through the GetOwinContext.GetUserManager method (where GetOwinContext is an extension method on the HttpContext class), and uses the FindByIdAsync method to locate the AppUser instance associated with the ID and to return the value of the UserName property.
This custom HTML Auxiliary method , As a HtmlHelper Class extension . The name of the helper is GetUsername, With a user ID The string of is the parameter , adopt GetOwinContext.GetUserManager Method to get AppUserManager An example of ( among GetOwinContext yes HttpContext Class extension methods ), And use FindByIdAsync Method orientation and ID The associated AppUser example , Then return UserName The value of the property .

Listing 14-11 shows the contents of the Index.cshtml file from the Views/RoleAdmin folder, which I created by right-clicking the Index action method in the code editor and selecting Add View from the pop-up menu.
detailed list 14-11 Shows Views/RoleAdmin In the folder Index.cshtml The content of the document , This is done by right clicking in the code editor Index action , And choose... From the pop-up menu “Add View( Add view )” To create .

Listing 14-11. The Contents of the Index.cshtml File in the Views/RoleAdmin Folder
detailed list 14-11. Views/RoleAdmin In the folder Index.cshtml The content of the document

@using Users.Models
@using Users.Infrastructure
@model IEnumerable<AppRole>
@{ ViewBag.Title = "Roles"; }
<div class="panel panel-primary">
<div class="panel-heading">Roles</div>
<table class="table table-striped">
<tr><th>ID</th><th>Name</th><th>Users</th><th></th></tr>
@if (Model.Count() == 0) {
<tr><td colspan="4" class="text-center">No Roles</td></tr>
} else {
foreach (AppRole role in Model) {
<tr>
<td>@role.Id</td>
<td>@role.Name</td>
<td>
@if (role.Users == null || role.Users.Count == 0) {
@: No Users in Role
} else {
<p>@string.Join(", ", role.Users.Select(x =>
Html.GetUserName(x.UserId)))</p>
}
</td>
<td>
@using (Html.BeginForm("Delete", "RoleAdmin",
new { id = role.Id })) {
@Html.ActionLink("Edit", "Edit", new { id = role.Id },
new { @class = "btn btn-primary btn-xs" })
<button class="btn btn-danger btn-xs"
type="submit">
Delete
</button>
}
</td>
</tr>
}
}
</table>
</div>
@Html.ActionLink("Create", "Create", null, new { @class = "btn btn-primary" })

This view displays a list of the roles defined by the application, along with the users who are members, and I use the GetUserName helper method to get the name for each user.
This view shows a list of roles defined by the application , With member users , I use GetUserName The helper method gets the user name of each user .

Listing 14-12 shows the Views/RoleAdmin/Create.cshtml file, which I created to allow new roles to be created.
detailed list 14-12 Shows Views/RoleAdmin/Create.cshtml file , This is the view to create a new character .

Listing 14-12. The Contents of the Create.cshtml File in the Views/RoleAdmin Folder
detailed list 14-12. Views/RoleAdmin In the folder Create.cshtml The content of the document

@model string
@{ ViewBag.Title = "Create Role";}
<h2>Create Role</h2>
@Html.ValidationSummary(false)
@using (Html.BeginForm()) {
<div class="form-group">
<label>Name</label>
<input name="name" value="@Model" class="form-control" />
</div>
<button type="submit" class="btn btn-primary">Create</button>
@Html.ActionLink("Cancel", "Index", null, new { @class = "btn btn-default" })
}

The only information required to create a new view is a name, which I gather using a standard input element and submit the value to the Create action method.
The only information needed to create this view is the role name , I use standard input Elements are collected , And submit the value to Create Action method .

14.3.4 Testing Creating and Deleting Roles
14.3.4 Creating and deleting test roles

To test the new controller, start the application and navigate to the /RoleAdmin/Index URL. To create a new role, click the Create button, enter a name in the input element, and click the second Create button. The new view will be saved to the database and displayed when the browser is redirected to the Index action, as shown in Figure 14-4. You can remove the role from the application by clicking the Delete button.
To test the new controller , Start the application and navigate to /RoleAdmin/Index URL. To create a new character , Click on “Create” Button , stay input Enter a role name in the element , Then click on the second “Create” Button . The new role will be saved to the database , And is redirected to Index It's displayed in action , Pictured 14-4 Shown . You can click on the “Delete” Button to remove the role from the application .

Figure 14-4. Creating a new role
chart 14-4. Create a new character

14.3.5 Managing Role Memberships
14.3.5 Managing role members

To authorize users, it isn’t enough to just create and delete roles; I also have to be able to manage role memberships, assigning and removing users from the roles that the application defines. This isn’t a complicated process, but it invokes taking the role data from the AppRoleManager class and then calling the methods defined by the AppUserMangager class that associate users with roles.
To empower users , It's not enough just to create and delete roles . You also have to be able to manage role members , Specify and remove users from application defined roles . It's not a complicated process , But it starts with AppRoleManager Class to get role data , Then the user is associated with the role AppUserMangager Class .

I started by defining view models that will let me represent the membership of a role and receive a new set of membership instructions from the user. Listing 14-13 shows the additions I made to the UserViewModels.cs file.
I first defined the view model , This allows me to represent members of a role , And can receive a set of new member's instructions from the user . detailed list 14-13 Displayed in UserViewModels.cs Add to file .

Listing 14-13. Adding View Models to the UserViewModels.cs File
detailed list 14-13. Add to UserViewModels.cs The view model of the file

using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
namespace Users.Models {
public class CreateModel {
[Required]
public string Name { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string Password { get; set; }
}
public class LoginModel {
[Required]
public string Name { get; set; }
[Required]
public string Password { get; set; }
}
public class RoleEditModel {
public AppRole Role { get; set; }
public IEnumerable<AppUser> Members { get; set; }
public IEnumerable<AppUser> NonMembers { get; set; }
}
public class RoleModificationModel {
[Required]
public string RoleName { get; set; }
public string[] IdsToAdd { get; set; }
public string[] IdsToDelete { get; set; }
}

}

The RoleEditModel class will let me pass details of a role and details of the users in the system, categorized by membership. I use AppUser objects in the view model so that I can extract the name and ID for each user in the view that will allow memberships to be edited. The RoleModificationModel class is the one that I will receive from the model binding system when the user submits their changes. It contains arrays of user IDs rather than AppUser objects, which is what I need to change role memberships.
RoleEditModel Class enables me to pass role details and user details through the system , By members . I used... In the view model AppUser object , So that I can extract the user name and ID.RoleModificationModel Class is when users submit their changes , A class received from the model binding system . It contains users ID Array of , instead of AppUser object , This is what is needed to modify the members of the role .

Having defined the view models, I can add the action methods to the controller that will allow role memberships to be defined. Listing 14-14 shows the changes I made to the RoleAdmin controller.
After defining the view model , You can add action methods to the controller , To define role members . detailed list 14-14 It shows that I'm interested in RoleAdmin Changes made by the controller .

Listing 14-14. Adding Action Methods in the RoleAdminController.cs File
detailed list 14-14. stay RoleAdminController.cs Add action methods to the file

using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Users.Infrastructure;
using Users.Models;
using System.Collections.Generic;
namespace Users.Controllers {
public class RoleAdminController : Controller {
// ...other action methods omitted for brevity...
// ... For simplicity , Other action methods are ignored here ...
public async Task<ActionResult> Edit(string id) {
AppRole role = await RoleManager.FindByIdAsync(id);
string[] memberIDs = role.Users.Select(x => x.UserId).ToArray();
IEnumerable<AppUser> members
= UserManager.Users.Where(x => memberIDs.Any(y => y == x.Id));
IEnumerable<AppUser> nonMembers = UserManager.Users.Except(members);
return View(new RoleEditModel {
Role = role,
Members = members,
NonMembers = nonMembers
});
}
[HttpPost]
public async Task<ActionResult> Edit(RoleModificationModel model) {
IdentityResult result;
if (ModelState.IsValid) {
foreach (string userId in model.IdsToAdd ?? new string[] { }) {
result = await UserManager.AddToRoleAsync(userId, model.RoleName);
if (!result.Succeeded) {
return View("Error", result.Errors);
}
}
foreach (string userId in model.IdsToDelete ?? new string[] { }) {
result = await UserManager.RemoveFromRoleAsync(userId,
model.RoleName);
if (!result.Succeeded) {
return View("Error", result.Errors);
}
}
return RedirectToAction("Index");
}
return View("Error", new string[] { "Role Not Found" });
}

private void AddErrorsFromResult(IdentityResult result) {
foreach (string error in result.Errors) {
ModelState.AddModelError("", error);
}
}
private AppUserManager UserManager {
get {
return HttpContext.GetOwinContext().GetUserManager<AppUserManager>();
}
}
private AppRoleManager RoleManager {
get {
return HttpContext.GetOwinContext().GetUserManager<AppRoleManager>();
}
}
}
}

The majority of the code in the GET version of the Edit action method is responsible for generating the sets of members and nonmembers of the selected role, which is done using LINQ. Once I have grouped the users, I call the View method, passing a new instance of the RoleEditModel class I defined in Listing 14-13.
GET edition Edit The main code of the action method is responsible for generating a set of members and non members of the selected role , This is the use of LINQ Accomplished . Once the users are grouped , Then call View Method , A list is passed for it 14-13 Defined by the RoleEditModel class .

The POST version of the Edit method is responsible for adding and removing users to and from roles. The AppUserManager class inherits a number of role-related methods from its base class, which I have described in Table 14-9.
POST Version of Edit The method is responsible for adding and removing users from roles .AppUserManager Class inherits several role related methods from its base class , Described in table 14-9.

Table 14-9. The Role-Related Methods Defined by the UserManager<T> Class
surface 14-9. UserManager<T> Role related methods defined in class
Name
name
Description
describe
AddToRoleAsync(id, name) Adds the user with the specified ID to the role with the specified name
Will specify ID Add users to the specified name Role
GetRolesAsync(id) Returns a list of the names of the roles of which the user with the specified ID is a member
Returns the specified ID List of the role names of the users of
IsInRoleAsync(id, name) Returns true if the user with the specified ID is a member of the role with the specified name
If specified ID The user of is designated name Members of the role , return true
RemoveFromRoleAsync(id, name) Removes the user with the specified ID as a member from the role with the specified name
In the specified name Remove the specified... From the members of the role ID Users of

An oddity of these methods is that the role-related methods operate on user IDs and role names, even though roles also have unique identifiers. It is for this reason that my RoleModificationModel view model class has a RoleName property.
The strange thing about these methods is , The methods related to roles are based on “ user ID” and “ role name( The role of )” To operate , Although roles also have unique identifiers (ID). This is also in the RoleModificationModel View model class RoleName Reason for attribute .

Listing 14-15 shows the view for the Edit.cshtml file, which I added to the Views/RoleAdmin folder and used to define the markup that allows the user to edit role memberships.
detailed list 14-15 Shows Edit.cshtml It also takes up , The view is placed in Views/RoleAdmin In file , Use it to define tags for users to edit role members .

Listing 14-15. The Contents of the Edit.cshtml File in the Views/RoleAdmin Folder
detailed list 14-15. Views/RoleAdmin In the folder Edit.cshtml The content of the document

@using Users.Models
@model RoleEditModel
@{ ViewBag.Title = "Edit Role";}
@Html.ValidationSummary()
@using (Html.BeginForm()) {
<input type="hidden" name="roleName" value="@Model.Role.Name" />
<div class="panel panel-primary">
<div class="panel-heading">Add To @Model.Role.Name</div>
<table class="table table-striped">
@if (Model.NonMembers.Count() == 0) {
<tr><td colspan="2">All Users Are Members</td></tr>
} else {
<tr><td>User ID</td><td>Add To Role</td></tr>
foreach (AppUser user in Model.NonMembers) {
<tr>
<td>@user.UserName</td>
<td>
<input type="checkbox" name="IdsToAdd" value="@user.Id">
</td>
</tr>
}
}
</table>
</div>
<div class="panel panel-primary">
<div class="panel-heading">Remove from @Model.Role.Name</div>
<table class="table table-striped">
@if (Model.Members.Count() == 0) {
<tr><td colspan="2">No Users Are Members</td></tr>
} else {
<tr><td>User ID</td><td>Remove From Role</td></tr>
foreach (AppUser user in Model.Members) {
<tr>
<td>@user.UserName</td>
<td>
<input type="checkbox" name="IdsToDelete" value="@user.Id">
</td>
</tr>
}
}
</table>
</div>
<button type="submit" class="btn btn-primary">Save</button>
@Html.ActionLink("Cancel", "Index", null, new { @class = "btn btn-default" })
}

The view contains two tables: one for users who are not members of the selected role and one for those who are members. Each user’s name is displayed along with a check box that allows the membership to be changed.
This view contains two tables : One for users who are not members of the selected role , One is the user who is a member of the selected role . There is a check box next to each displayed user name , You can modify its membership .

14.3.6 Testing Editing Role Membership
14.3.6 Editing of test role members

Adding the AppRoleManager class to the application causes the Entity Framework to delete the contents of the database and rebuild the schema, which means that any users you created in the previous chapter have been removed. So that there are users to assign to roles, start the application and navigate to the /Admin/Index URL and create users with the details in Table 14-10.
Add... To your application AppRoleManager Class can cause Entity Framework Delete the contents of the database , And rebuild the database architecture , This means that all users created in the previous chapter will be deleted . therefore , In order to have users who can give roles , Start the application and navigate to /Admin/Index URL, First, create some tables 14-10 The user shown .

Table 14-10. The Values for Creating Example User
surface 14-10. Create values for sample users
Name
user name
Email
E-mail
Password
password
Alice alice@example.com MySecret
Bob bob@example.com MySecret
Joe joe@example.com MySecret

Tip deleting the user database is fine for an example application but tends to be a problem in real applications. I show you how to gracefully manage changes to the database schema in Chapter 15.
Tips : Deleting users is no problem for the sample application , But it's a problem for real applications . The first 15 Chapter 2 shows how to modify the database schema gracefully .

To test managing role memberships, navigate to the /RoleAdmin/Index URL and create a role called Users, following the instructions from the “Testing, Creating, and Deleting Roles” section. Click the Edit button and check the boxes so that Alice and Joe are members of the role but Bob is not, as shown in Figure 14-5.
To test the management of role members , Navigate to /RoleAdmin/Index URL, And in accordance with the “ Creating and deleting test roles ” Section description , Create a name Users Role . Click on “Edit” Button , And check the box , send Alice and Joe Become a member of the role , and Bob Don't choose , Pictured 14-5 Shown .

Figure 14-5. Editing role membership
chart 14-5. Edit role members

Tip If you get an error that tells you there is already an open a data reader, then you didn’t set the MultipleActiveResultSets setting to true in the connection string in Chapter 13.
Tips : If something goes wrong , Tell you that , There is already an open data reader , That's because you didn't put the second 13 Chapter connection string in MultipleActiveResultSets Set to true.

Click the Save button, and the controller will update the role memberships and redirect the browser to the Index action. The summary of the Users role will show that Alice and Joe are now members, as illustrated by Figure 14-6.
Click on “Save” Button , The controller then updates the role members , And redirect your browser to Index action .Users A summary of the roles will be displayed Alice and Joe Now it's a member , Pictured 14-6 Shown .

Figure 14-6. The effect of adding users to a role
chart 14-6. The effect of adding users to a role

14.3.7 Using Roles for Authorization
14.3.7 Using roles for authorization

Now that I have the ability to manage roles, I can use them as the basis for authorization through the Authorize attribute. To make it easier to test role-based authorization, I have added a Logout method to the Account controller, as shown in Listing 14-16, which will make it easier to log out and log in again as a different user to see the effect of role membership.
Now you can manage roles , adopt Authorize Annotation Properties , You can also use roles as the basis for authorization . To make it easier to test role-based authorization , I am here Account A... Has been added to the controller Logout Method , Like the list 14-16 Shown , This makes it easy to log off , It's also easy to log in as a different user , To see the effect of character members .

Listing 14-16. Adding a Logout Method to the AccountController.cs File
detailed list 14-16. stay AccountController.cs Add... To the file Logout Method

using System.Threading.Tasks;
using System.Web.Mvc;
using Users.Models;
using Microsoft.Owin.Security;
using System.Security.Claims;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Users.Infrastructure;
using System.Web;
namespace Users.Controllers {
[Authorize]
public class AccountController : Controller {
[AllowAnonymous]
public ActionResult Login(string returnUrl) {
ViewBag.returnUrl = returnUrl;
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginModel details, string returnUrl) {
// ...statements omitted for brevity...
// ... For simplicity , Some statements are ignored ...
}
[Authorize]
public ActionResult Logout() {
AuthManager.SignOut();
return RedirectToAction("Index", "Home");
}

private IAuthenticationManager AuthManager {
get {
return HttpContext.GetOwinContext().Authentication;
}
}
private AppUserManager UserManager {
get {
return HttpContext.GetOwinContext().GetUserManager<AppUserManager>();
}
}
}
}

I have updated the Home controller to add a new action method and pass some information about the authenticated user to the view, as shown in Listing 14-17.
I also updated Home controller , Added a new action method , And pass some information of the authenticated user to the view , Like the list 14-17 Shown .

Listing 14-17. Adding an Action Method and Account Information to the HomeController.cs File
detailed list 14-17. stay HomeController.cs Add action method and account information to the file

using System.Web.Mvc;
using System.Collections.Generic;
using System.Web;
using System.Security.Principal;

namespace Users.Controllers {
public class HomeController : Controller {
[Authorize]
public ActionResult Index() {
return View(GetData("Index"));
}
[Authorize(Roles="Users")]
public ActionResult OtherAction() {
return View("Index", GetData("OtherAction"));
}
private Dictionary<string, object> GetData(string actionName) {
Dictionary<string, object> dict
= new Dictionary<string, object>();
dict.Add("Action", actionName);
dict.Add("User", HttpContext.User.Identity.Name);
dict.Add("Authenticated", HttpContext.User.Identity.IsAuthenticated);
dict.Add("Auth Type", HttpContext.User.Identity.AuthenticationType);
dict.Add("In Users Role", HttpContext.User.IsInRole("Users"));
return dict;

}
}
}

I have left the Authorize attribute unchanged for the Index action method, but I have set the Roles property when applying the attribute to the OtherAction method, specifying that only members of the Users role should be able to access it. I also defined a GetData method, which adds some basic information about the user identity, using the properties available through the HttpContext object. The final change I made was to the Index.cshtml file in the Views/Home folder, which is used by both actions in the Home controller, to add a link that targets the Logout method in the Account controller, as shown in Listing 14-18.
I haven't changed Index In the way of action Authorize Annotation Properties , But apply this property to OtherAction When the method is used , It's set up Roles attribute , Only Users Only members of the role can access it . I also defined a GetData Method , It adds some basic information about user identity , This is through HttpContext Object available properties . The final change is Views/Home In folder Index.cshtml file , It is from Home Two actions in the controller use , I added some to it to Account In the controller Logout Method as the target link , Like the list 14-18 Shown .

Listing 14-18. Adding a Sign-Out Link to the Index.cshtml File in the Views/Home Folder
detailed list 14-18. stay Views/Home In folder Index.cshtml Add... To the file Sign-Out( Check out ) link

@{ ViewBag.Title = "Index"; }
<div class="panel panel-primary">
<div class="panel-heading">User Details</div>
<table class="table table-striped">
@foreach (string key in Model.Keys) {
<tr>
<th>@key</th>
<td>@Model[key]</td>
</tr>
}
</table>
</div>
@Html.ActionLink("Sign Out", "Logout", "Account", null, new {@class = "btn btn-primary"})

Tip the Authorize attribute can also be used to authorize access based on a list of individual usernames. This is an appealing feature for small projects, but it means you have to change the code in your controllers each time the set of users you are authorizing changes, and that usually means having to go through the test-and-deploy cycle again. Using roles for authorization isolates the application from changes in individual user accounts and allows you to control access to the application through the memberships stored by ASP.NET Identity.
Tips :Authorize Annotation properties can also be used to grant access based on individual user names . It's an attractive feature for small projects , But that means , Every time your authorized user set changes , You have to modify the code in the controller , It also means that , To go through the development cycle from testing to deployment again . Use role authorization to isolate applications from modifying individual user accounts , So that you can pass ASP.NET Identity Members of the storage to control access to the application .

To test the authentication, start the application and navigate to the /Home/Index URL. Your browser will be redirected so that you can enter user credentials. It doesn’t matter which of the user details from Table 14-10 you choose to authenticate with because the Authorize attribute applied to the Index action allows access to any authenticated user.
In order to test the certification , Start the application , And navigate to the /Home/Index URL. The browser will be redirected , Let you enter user credentials . Selection table 14-10 It doesn't matter which user details are authenticated in , Because it applies to Index Action Authorize The annotation property allows any authenticated user to access

However, if you now request the /Home/OtherAction URL, the user details you chose from Table 14-10 will make a difference because only Alice and Joe are members of the Users role, which is required to access the OtherAction method.
However , If you ask now /Home/OtherAction URL, From the table 14-10 The selected user details are different , Because only Alice and Joe yes Users Members of the role , This is a visit OtherAction Methods are necessary .

If you log in as Bob, then your browser will be redirected so that you can be prompted for credentials once again.
If the Bob Sign in , Then the browser will be redirected , You may be prompted to enter credentials again .

Redirecting an already authenticated user for more credentials is rarely a useful thing to do, so I have modified the Login action method in the Account controller to check to see whether the user is authenticated and, if so, redirect them to the shared Error view. Listing 14-19 shows the changes.
Redirecting authenticated users to ask for more credentials is almost useless , therefore , I modified Account In the controller Login Action method , Check that the user is authenticated , If it is , Then redirect them to the shared Error View , detailed list 14-19 Shows the changes made .

Listing 14-19. Detecting Already Authenticated Users in the AccountController.cs File
detailed list 14-19. stay AccountController.cs Detect authenticated user in file

using System.Threading.Tasks;
using System.Web.Mvc;
using Users.Models;
using Microsoft.Owin.Security;
using System.Security.Claims;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Users.Infrastructure;
using System.Web;
namespace Users.Controllers {
[Authorize]
public class AccountController : Controller {
[AllowAnonymous]
public ActionResult Login(string returnUrl) {
if (HttpContext.User.Identity.IsAuthenticated) {
return View("Error", new string[] { "Access Denied" });
}
ViewBag.returnUrl = returnUrl;
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginModel details, string returnUrl) {
// ...code omitted for brevity...
// ... For simplicity , Ignoring the code here ...
}
[Authorize]
public ActionResult Logout() {
AuthManager.SignOut();
return RedirectToAction("Index", "Home");
}
private IAuthenticationManager AuthManager {
get {
return HttpContext.GetOwinContext().Authentication;
}
}
private AppUserManager UserManager {
get {
return HttpContext.GetOwinContext().GetUserManager<AppUserManager>();
}
}
}
}

Figure 14-7 shows the responses generated for the user Bob when requesting the /Home/Index and /Home/OtherAction URLs.
chart 14-7 Shows the user Bob In the request /Home/Index and /Home/OtherAction URL Response generated when .

Figure 14-7. Using roles to control access to action methods
chart 14-7. Use roles to control access to action methods

Tip Roles are loaded when the user logs in, which means if you change the roles for the user you are currently authenticated as, the changes won’t take effect until you log out and authenticate.
Tips : The role is loaded when the user logs in , It means , If the role of the current authenticated user is modified , These changes will not take effect , Until they quit and recertify .

14.4 Seeding the Database
14.4 Planting database

One lingering problem in my example project is that access to my Admin and RoleAdmin controllers is not restricted.
One problem that has not been eliminated in the above example project is , Yes Admin and RoleAdmin Access to the controller is unrestricted .

This is a classic chicken-and-egg problem because in order to restrict access, I need to create users and roles, but the Admin and RoleAdmin controllers are the user management tools, and if I protect them with the Authorize attribute, there won’t be any credentials that will grant me access to them, especially when I first deploy the application.
It's a classic chicken and egg problem , because , To restrict access , You need to create some users and roles in advance , but Admin and RoleAdmin The controller is also a user management tool , If you use Authorize Annotation properties to protect them , Then there are no credentials to access them , Especially the first time you deploy an application .

The solution to this problem is to seed the database with some initial data when the Entity Framework Code First feature creates the schema. This allows me to automatically create users and assign them to roles so that there is a base level of content available in the database.
The solution to this problem is , stay Entity Framework Of Code First Feature to create a database schema , Implant some initial data into the database . This will automatically create some users , And give a certain role , To make a base level content available in the database .

The database is seeded by adding statements to the PerformInitialSetup method of the IdentityDbInit class, which is the application-specific Entity Framework database setup class. Listing 14-20 shows the changes I made to create an administration user.
The way to grow a database is in IdentityDbInit Class PerformInitialSetup Method ,IdentityDbInit It's application specific Entity Framework Database settings class . detailed list 14-20 It's about creating and managing user made changes

Listing 14-20. Seeding the Database in the AppIdentityDbContext.cs File
detailed list 14-20. stay AppIdentityDbContext.cs The database in the file

using System.Data.Entity;
using Microsoft.AspNet.Identity.EntityFramework;
using Users.Models;
using Microsoft.AspNet.Identity;
namespace Users.Infrastructure {
public class AppIdentityDbContext : IdentityDbContext<AppUser> {
public AppIdentityDbContext() : base("IdentityDb") { }
static AppIdentityDbContext() {
Database.SetInitializer<AppIdentityDbContext>(new IdentityDbInit());
}
public static AppIdentityDbContext Create() {
return new AppIdentityDbContext();
}
}
public class IdentityDbInit
: DropCreateDatabaseIfModelChanges<AppIdentityDbContext> {
protected override void Seed(AppIdentityDbContext context) {
PerformInitialSetup(context);
base.Seed(context);
}
public void PerformInitialSetup(AppIdentityDbContext context) {
AppUserManager userMgr = new AppUserManager(new UserStore<AppUser>(context));
AppRoleManager roleMgr = new AppRoleManager(new RoleStore<AppRole>(context));
string roleName = "Administrators";
string userName = "Admin";
string password = "MySecret";
string email = "admin@example.com";
if (!roleMgr.RoleExists(roleName)) {
roleMgr.Create(new AppRole(roleName));
}
AppUser user = userMgr.FindByName(userName);
if (user == null) {
userMgr.Create(new AppUser { UserName = userName, Email = email },
password);
user = userMgr.FindByName(userName);
}
if (!userMgr.IsInRole(user.Id, roleName)) {
userMgr.AddToRole(user.Id, roleName);

}
}
}
}

Tip For this example, I used the synchronous extension methods to locate and manage the role and user. As I explained in Chapter 13, I prefer the asynchronous methods by default, but the synchronous methods can be useful when you need to perform a sequence of related operations.
Tips : In the example above , I used the synchronous extension method to locate and manage roles and users . Just like No 13 As the chapter explains , In general, I prefer asynchronous methods , however , When you need to perform a series of related operations , Synchronization methods can be useful .

I have to create instances of AppUserManager and AppRoleManager directly because the PerformInitialSetup method is called before the OWIN configuration is complete. I use the RoleManager and AppManager objects to create a role called Administrators and a user called Admin and add the user to the role.
I have to create it directly AppUserManager and AppRoleManager Example , because PerformInitialSetup The method is in OWIN It is called before the configuration is completed . I use RoleManager and AppManager Object to create an object named Administrators Role , And a Admin Users of , And add this user to the role .

Tip Read Chapter 15 before you add database seeding to your project. I describe database migrations, which allow you to take control of schema changes in the database and which put the seeding logic in a different place.
Tips : Before adding a database to the project , Please read page 15 Chapter . I described database migration in it , This allows you to control architectural changes in the database , And you can put the planting logic in different places .

With this change, I can use the Authorize attribute to protect the Admin and RoleAdmin controllers. Listing 14-21 shows the change I made to the Admin controller.
After this modification , I can use Authorize Annotation properties to protect Admin and RoleAdmin controller . detailed list 14-21 Shows the right Admin Changes made by the controller .

Listing 14-21. Restricting Access in the AdminController.cs File
detailed list 14-21. stay AdminController.cs Restricted access in files

using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity.Owin;
using Users.Infrastructure;
using Users.Models;
using Microsoft.AspNet.Identity;
using System.Threading.Tasks;
namespace Users.Controllers {
[Authorize(Roles = "Administrators")]
public class AdminController : Controller {
// ...statements omitted for brevity...
// ... For simplicity , Ignore the statement here ...
}
}

Listing 14-22 shows the corresponding change I made to the RoleAdmin controller.
detailed list 14-22 It's right RoleAdmin The corresponding modifications made by the controller .

Listing 14-22. Restricting Access in the RoleAdminController.cs File
detailed list 14-22. stay RoleAdminController.cs Restricted access in files

using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Users.Infrastructure;
using Users.Models;
using System.Collections.Generic;
namespace Users.Controllers {
[Authorize(Roles = "Administrators")]
public class RoleAdminController : Controller {
// ...statements omitted for brevity...
// ... For simplicity , Ignore the statement here ...
}
}

The database is seeded only when the schema is created, which means I need to reset the database to complete the process. This isn’t something you would do in a real application, of course, but I wanted to wait until I demonstrated how authentication and authorization worked before creating the administrator account.
The database is planted only when the schema is created , This means that you need to reset the database to complete the process . Of course , This is not something that might be done in a real project , But I hope to wait , Before creating an administrator account , Complete the demonstration of authentication and authorization .

To delete the database, open the Visual Studio SQL Server Object Explorer window and locate and right-click the IdentityDb item. Select Delete from the pop-up menu and check both of the options in the Delete Database dialog window. Click the OK button to delete the database.
To delete the database , Please open the Visual Studio Medium “SQL Server Object explorer ” window , Find and right-click “IdentityDb” entry . Select from the pop-up menu “Delete( Delete )”, And in “Delete Database( Delete database )” Select the two options in the window . Click on “OK” Button , Delete the database .

Now create an empty database to which the schema will be added by right-clicking the Databases item, selecting Add New Database, and entering IdentityDb in the Database Name field. Click OK to create the empty database.
Now? , Right click “Databases( database )” entry , choice “Add New Database( Add a new database )”, And in “Database Name( Database name )” Enter... In the field IdentityDb. Click on OK, Create an empty database .

Tip There are step-by-step instructions with screenshots in Chapter 13 for creating the database.
Tips : The first 13 The chapter has step-by-step instructions and screen shots for creating the database .

Now start the application and request the /Admin/Index or /RoleAdmin/Index URL. There will be a delay while the schema is created and the database is seeded, and then you will be prompted to enter your credentials. Use Admin as the name and MySecret as the password, and you will be granted access to the controllers.
Now? , Start the application , request /Admin/Index or /RoleAdmin/Index URL. There will be a little delay during the creation of the database schema and the implantation of the database , You will then be prompted for credentials . Use Admin As user name ,MySecret As password , Will get access to the controller .

Caution Deleting the database removes the user accounts you created using the details in table 14-10, which is why you would not perform this task on a live database containing user details.
Warning : Delete the database and delete the table you use 14-10 The user account created , That's why , This task is not normally performed in an active database with user details .

14.5 Summary
14.5 Summary

In this chapter, I showed you how to use ASP.NET Identity to authenticate and authorize users. I explained how the ASP.NET life-cycle events provide a foundation for authenticating requests, how to collect and validate credentials users, and how to restrict access to action methods based on the roles that a user is a member of. In the next chapter, I demonstrate some of the advanced features that ASP.NET Identity provides.
In this chapter , I demonstrated how to use ASP.NET Identity User authentication and authorization . Explained ASP.NET How life cycle events provide the basis for authentication , How to collect and verify user credentials , And how to restrict access to action methods according to the user's member role . The next chapter will demonstrate ASP.NET Identity Some of the advanced features provided .

After reading this article, if you feel that something has been gained , Please give me recommend .
Your recommendation is my motivation to continue , It will also bring more people's attention and benefit , It's also your contribution .

【ASP.NET Identity Series of tutorials ( Two )】 Application ASP.NET Identity More articles about

  1. 【ASP.NET Identity Series of tutorials ( 3、 ... and )】Identity advanced technology

    notes : This article is about [ASP.NET Identity Series of tutorials ] The third part of . This series of tutorials details . complete . In depth introduction of Microsoft's ASP.NET Identity technology , Describes how to use ASP.NET Identity Implement the application ...

  2. ASP.NET 5 Series of tutorials ( Two ):Hello World

    The content of this article is relatively basic , Mainly to show you how to create a ASP.NET 5 engineering , The main contents are as follows : establish ASP.NET 5 engineering add to Todo controller install K Version Manager perform ...

  3. ASP.NET Identity Series of tutorials ( Catalog )

    $(document).ready(function(){ $("#hide").click(function(){ $(".en").hide(); }); ...

  4. ASP.NET Identity Series of tutorials ( Catalog ) Reprint

    source :http://www.cnblogs.com/r01cn/p/5179506.html notes : I've seen a lot of introductions of Microsoft recently ASP.NET Identity Technical articles , But it doesn't feel complete enough , I happened to be in A ...

  5. ASP.NET Identity Series of tutorials -1 Catalog

    https://www.cnblogs.com/hao-1234-1234/p/8857437.html ASP.NET Identity Series of tutorials 13 Getting Started with Id ...

  6. ASP.NET 5 Series of tutorials ( Four ): Add services to the view and publish applications to the public cloud

    Add services to the view Now? ,ASP.NET MVC 6 Support class injection into view , and VC Class is different from , Open to classes . There's no limit to being non nested or non abstract . In this case , We created a simple class , It is used to count agent events . The event has been completed ...

  7. ASP.NET 5 Series of tutorials ( 7、 ... and ) Conclusion - Decoding code

    In this paper , We'll look at it together TodoController Class code . [Route] Property defines Controller Of URL Templates : [Route("api/[controller]") ...

  8. ASP.NET 5 Series of tutorials ( 6、 ... and ): stay MVC6 Created in Web API

    ASP.NET 5.0 One of the main goals of the United States is to unify MVC and Web API Framework application . You'll learn about the following in the next few articles : ASP.NET MVC 6 Create a simple web API. How to start from an empty project template ...

  9. ASP.NET MVC3 Series of tutorials - Catalog

    ASP.NET MVC3 Series of tutorials - Catalog   I:ASP.NET MVC3 New features ASP.NET MVC3 Series of tutorials - Razor View engine basic syntax ASP.NET MVC3 Series of tutorials - V ...

Random recommendation

  1. 【Alpha Stage 】 The first online conference

    Conference information Because of the compilation job ddl, There's no big progress for now , No, close Of issue Time :2016.11.07 19:00 Duration :10min place : Discussion groups type : Online meeting NXT:2016.11.08 21:30 ...

  2. 2015 Multi-University Training Contest 2 1002 Buildings

    Buildings Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=5301 Mean: n*m Column grid , Delete a grid x,y, Use a rectangle ...

  3. Tinyxml Simple application of

    Reference article : 1-> http://www.cnblogs.com/phinecos/archive/2008/03/11/1100912.html 2-> http://blog.csdn ...

  4. JqGrid The summary of 【 turn 】

    jqGrid Arrangement   PS:JqGrid official API Am I   My notes : One . jqGrid Loading . 1. Reference related header file introduce CSS: <link href="Scripts/jq ...

  5. sourceTree Code conflict resolution

    1. Submit code , There are conflicts 2. Pull the unsynchronized code , Choose derivative instead of merger . 3. In the working copy , Uncommitted code display 4. Conflict code resolution 5. sourcetree page

  6. Ex 6_19 At most k A coin for a price _ The seventh assignment

    Subproblem definition : Define a two-dimensional array b, among b[i][j] To express with i Can a coin change the price j, It means the first one i The face value of each currency , Recursion : Initial value setting : The order of solution : Solve the array from small to large by subscript b The value of each column , Finally, two-dimensional arrays b Of ...

  7. nginx image_filter Configuration record

    nginx_image_filter http_image_filter_module To configure ---------------------------------- The first one is : // The official configuration locati ...

  8. gispro Set annotation properties font style settings

    In response to the electronic map and satellite image base map , The selection of annotation style is very important . The black and white halo effect is selected . Remember not to set the font outline . Because of the font width ( Coarse character ) Co., LTD. , Setting the outline directly covers the color of the font itself

  9. python pandas Basic understanding

    In fact, every blog I have to use a lot of trivial time segments to learn and write , A little bit at a time , Learn a little when you use it , Learn a little and record a little , It takes several days or even a week or two to feel that the knowledge structure of a certain class is almost complete . Pandas  Is based on  NumPy  Of ...

  10. Share 30 Avenue Redis Interview questions , I found everything the interviewer could ask

    1. What is? Redis? Briefly describe its advantages and disadvantages ? Redis It's essentially a Key-Value Type of in-memory database , It's like memcached, The whole database is loaded in memory for operation , Periodically transfer database data through asynchronous operations flush To ...