ASP.NET MVC 5 安全性和創建用戶角色


本文將介紹如何在 ASP.NET MVC 5 應用程序 中使用 ASP.NET Identity 創建和使用角色、擴展用戶屬性及相關知識。

主要內容包括:

  • 創建管理員角色和超級用戶
  • 用戶注冊時選擇角色
  • 使用用戶名進行登錄
  • 角色管理
  • 擴展用戶屬性
  • 針對Controller或Action的授權

准備工作

在 Visual Studio 2017 中 創建 ASP.NET Web 應用程序(.NET Framework),我們將應用程序命名為“UserRoleDemo”,在創建應用程序時更改身份驗證方式為“個人用戶賬戶”,其他均為默認設置。

創建管理員角色和超級用戶

修改 Startup.cs 文件,在 Configuration 方法中調用自定義的CreateRolesandUsers() 方法來創建默認角色和管理員用戶。

在CreateRolesandUsers() 方法中將檢查管理員角色(命名為“Admin”)是否已被創建,如果名稱為“Admin”的角色沒有創建,則創建一個名稱為“Admin”的新角色和一個超級用戶(命名為“sa”),並將該用戶的角色設置為“Admin”。

Startup.cs

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.Owin;
using Owin;
using UserRoleDemo.Models;

[assembly: OwinStartup(typeof(UserRoleDemo.Startup))]
namespace UserRoleDemo
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
            CreateRolesAndUsers();
        }


        // 創建管理員角色和超級用戶    
        private void CreateRolesAndUsers()
        {
            ApplicationDbContext context = new ApplicationDbContext();

            var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
            var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));

            // 判斷管理員角色是否存在     
            if (!roleManager.RoleExists("Admin"))
            {
                // 創建角色 - Admin
                var role = new IdentityRole
                {
                    Name = "Admin"
                };
                roleManager.Create(role);

                // 創建超級用戶 - sa
                var user = new ApplicationUser
                {
                    UserName = "sa",
                    Email = "sa@mercator.asia"
                };

                string userPWD = "Mercator.asia";

                var chkUser = userManager.Create(user, userPWD);

                // 指定超級用戶的角色    
                if (chkUser.Succeeded)
                {
                    var result1 = userManager.AddToRole(user.Id, "Admin");
                }
            }

            // 創建角色 - Manager
            if (!roleManager.RoleExists("Manager"))
            {
                var role = new IdentityRole
                {
                    Name = "Manager"
                };
                roleManager.Create(role);
            }

            // 創建角色 - Employee
            if (!roleManager.RoleExists("Employee"))
            {
                var role = new IdentityRole
                {
                    Name = "Employee"
                };
                roleManager.Create(role);
            }
        }
    }
}

用戶注冊時選擇角色

通過 ASP.NET Web 應用程序(.NET Framework) 模板創建的應用程序在用戶注冊時默認只能輸入郵箱和密碼,下面我們將實現在用戶注冊時選擇角色。

模板程序默認是以郵箱作為用戶名,在實現選擇角色功能時我們也會增加輸入獨立的用戶名的功能。

視圖部分

修改Register.cshtml文件,在其中添加用戶名行和角色行。

Views/Account/Register.cshtml

@model UserRoleDemo.Models.RegisterViewModel
@{
    ViewBag.Title = "注冊";
}

<h2>@ViewBag.Title。</h2>

@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>創建新帳戶。</h4>
    <hr />
    @Html.ValidationSummary("", new { @class = "text-danger" })
    <!--用戶名-->
    <div class="form-group">
        @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
        </div>
    </div>
    <!--角色-->
    <div class="form-group">
        @Html.Label("user Role", new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.DropDownList("UserRoles", (SelectList)ViewBag.Name, " ")
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" class="btn btn-default" value="注冊" />
        </div>
    </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

模型部分

修改 Models/AccountViewModel.cs 文件,在 RegisterViewModel 中添加 UserRoles 和 UserName 等兩個屬性。

Models/AccountViewModel.cs(局部)

    public class RegisterViewModel
    {
        [Required]
        [Display(Name = "所屬角色")]
        public string UserRoles { get; set; }

        [Required]
        [Display(Name = "用戶名")]
        public string UserName { get; set; }

        [Required]
        [EmailAddress]
        [Display(Name = "電子郵件")]
        public string Email { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "{0} 必須至少包含 {2} 個字符。", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "密碼")]
        public string Password { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = "確認密碼")]
        [Compare("Password", ErrorMessage = "密碼和確認密碼不匹配。")]
        public string ConfirmPassword { get; set; }
    }

控制器部分

修改 Controllers/AccountController.cs 文件,把除“Admin”外的所有角色名稱顯示在下拉框中,並在注冊按鈕的點擊事件中實現寫入用戶名和角色屬性的功能。

首先創建一個 ApplicationDBContext 對象。(ApplicationDBContext 是一個用於實現ASP.NET Identity 數據庫讀寫功能的類,例如創建用戶、角色等)

為AccountController類添加一個私有成員:

Controllers/AccountController.cs(局部)

        private readonly ApplicationDbContext context;

修改AccountController的構造函數以初始化context對象:

Controllers/AccountController.cs(局部)

        public AccountController()
        {
            context = new ApplicationDbContext();
        }

通過 ApplicationDBContext 對象我們可以獲取數據庫中的所有角色。用戶注冊時我們不允許選擇“Admin”角色,因此,在Register ActionResult 中查詢所有非“Admin”角色用於在視圖的角色下拉框中顯示。

Controllers/AccountController.cs(局部)

        //
        // GET: /Account/Register
        [AllowAnonymous]
        public ActionResult Register()
        {
            ViewBag.Name = new SelectList(context.Roles.Where(u => !u.Name.Contains("Admin"))
                                    .ToList(), "Name", "Name");
            return View();
        }

在AspNetUsers數據表中默認是將Email作為用戶名來存儲的,這里我們改為直接存儲用戶輸入的用戶名。

用戶創建成功后,通過調用 UserManager.AddToRoleAsync 方法為用戶設置其選擇的角色。

Controllers/AccountController.cs(局部)

        //
        // POST: /Account/Register
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Register(RegisterViewModel model)
        {
            if (ModelState.IsValid)
            {
                // 將UserName = model.Email替換為UserName = model.UserName
                var user = new ApplicationUser { UserName = model.UserName, Email = model.Email };
                var result = await UserManager.CreateAsync(user, model.Password);
                if (result.Succeeded)
                {
                    await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);

                    // 有關如何啟用帳戶確認和密碼重置的詳細信息,請訪問 https://go.microsoft.com/fwlink/?LinkID=320771
                    // 發送包含此鏈接的電子郵件
                    // string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
                    // var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
                    // await UserManager.SendEmailAsync(user.Id, "確認你的帳戶", "請通過單擊 <a href=\"" + callbackUrl + "\">這裏</a>來確認你的帳戶");

                    // 設置創建的新用戶添加到其選擇的角色
                    await UserManager.AddToRoleAsync(user.Id, model.UserRoles);

                    return RedirectToAction("Index", "Home");
                }

                // 返回注冊頁面時列出所有非“Admin”角色
                ViewBag.Name = new SelectList(context.Roles.Where(u => !u.Name.Contains("Admin"))
                                  .ToList(), "Name", "Name");

                AddErrors(result);
            }

            // 如果我們進行到這一步時某個地方出錯,則重新顯示表單
            return View(model);
        }

使用用戶名進行登錄

和用戶注冊時一樣,我們通過輸入用戶名來替代默認輸入Email的方式進行登錄操作。

視圖部分

修改Views/Account/Login.cshtml文件,將模型的Email屬性替換為UserName屬性。

Views/Account/Login.cshtml

@using UserRoleDemo.Models
@model LoginViewModel
@{
    ViewBag.Title = "登錄";
}

<h2>@ViewBag.Title。</h2>
<div class="row">
    <div class="col-md-8">
        <section id="loginForm">
            @using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
            {
                @Html.AntiForgeryToken()
                <h4>使用本地帳戶登錄。</h4>
                <hr />
                @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                <!--替換Email為UserName-->
                <div class="form-group">
                    @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
                    <div class="col-md-10">
                        @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.UserName, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="form-group">
                    @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
                    <div class="col-md-10">
                        @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <div class="checkbox">
                            @Html.CheckBoxFor(m => m.RememberMe)
                            @Html.LabelFor(m => m.RememberMe)
                        </div>
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <input type="submit" value="登錄" class="btn btn-default" />
                    </div>
                </div>
                <p>
                    @Html.ActionLink("注冊為新用戶", "Register")
                </p>
                @* 在為密碼重置功能啟用帳戶確認后啟用此項
                    <p>
                        @Html.ActionLink("忘記了密碼?", "ForgotPassword")
                    </p>*@
            }
        </section>
    </div>
    <div class="col-md-4">
        <section id="socialLoginForm">
            @Html.Partial("_ExternalLoginsListPartial", new ExternalLoginListViewModel { ReturnUrl = ViewBag.ReturnUrl })
        </section>
    </div>
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

模型部分

和用戶注冊一樣,在 AccountViewModel 中找到 LoginViewModel 並把 Email 替換為 UserName。

Models/AccountViewModels.cs(局部)

    public class LoginViewModel
    {
        [Required]
        [Display(Name = "用戶名")]
        public string UserName { get; set; }

        [Required]
        [DataType(DataType.Password)]
        [Display(Name = "密碼")]
        public string Password { get; set; }

        [Display(Name = "記住我?")]
        public bool RememberMe { get; set; }
    }

控制器部分

在登錄按鈕的點擊事件中我們同樣需要把Email屬性替換為 UserName來進行數據庫認證。

Controllers/AccountController.cs(局部)

        //
        // POST: /Account/Login
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }

            // 這不會計入到為執行帳戶鎖定而統計的登錄失敗次數中
            // 若要在多次輸入錯誤密碼的情況下觸發帳戶鎖定,請更改為 shouldLockout: true
            // 替換Email為UserName
            var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
            switch (result)
            {
                case SignInStatus.Success:
                    return RedirectToLocal(returnUrl);
                case SignInStatus.LockedOut:
                    return View("Lockout");
                case SignInStatus.RequiresVerification:
                    return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
                case SignInStatus.Failure:
                default:
                    ModelState.AddModelError("", "無效的登錄嘗試。");
                    return View(model);
            }
        }

角色管理

角色模型為Microsoft.AspNet.Identity.EntityFramework.IdentityRole,本文中,我們使用ASP.NET Identity中的RoleManager對象進行角色管理。

控制器部分

首先,我們添加一個空的MVC5 控制器,命名為RoleController。

修改Controllers/RoleController.cs文件,增加Index、Create、Edit和Delete等ActionResult。

Controllers/RoleController.cs

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using UserRoleDemo.Models;

namespace UserRoleDemo.Controllers
{
    public class RoleController : Controller
    {
        private ApplicationDbContext context = new ApplicationDbContext();

        // GET: Role
        public ActionResult Index()
        {
            return View(context.Roles.ToList());
        }

        // GET: Role/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: Role/Create
        // 為了防止“過多發布”攻擊,請啟用要綁定到的特定屬性,有關 
        // 詳細信息,請參閱 https://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "Id,Name")] IdentityRole identityRole)
        {
            if (ModelState.IsValid)
            {
                var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
                roleManager.Create(identityRole);

                return RedirectToAction("Index");
            }

            return View(identityRole);
        }

        // GET: Role/Edit/5
        public ActionResult Edit(string id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            IdentityRole identityRole = context.Roles.Find(id);
            if (identityRole == null)
            {
                return HttpNotFound();
            }
            return View(identityRole);
        }

        // POST: Role/Edit/5
        // 為了防止“過多發布”攻擊,請啟用要綁定到的特定屬性,有關 
        // 詳細信息,請參閱 https://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "Id,Name")] IdentityRole identityRole)
        {
            if (ModelState.IsValid)
            {
                var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
                roleManager.Update(identityRole);

                return RedirectToAction("Index");
            }
            return View(identityRole);
        }

        // GET: Role/Delete/5
        public ActionResult Delete(string id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            IdentityRole identityRole = context.Roles.Find(id);
            if (identityRole == null)
            {
                return HttpNotFound();
            }
            return View(identityRole);
        }

        // POST: Role/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(string id)
        {
            IdentityRole identityRole = context.Roles.Find(id);

            var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
            roleManager.Delete(identityRole);

            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                context.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}

視圖部分

分別在RoleController的ActionResult Index、Create、Edit、Delete上點擊右鍵,選擇 添加視圖。

操作完成后,Views目錄中應該會多出一個Role文件夾,其中包含Index.cshtml、Create.cshtml、Edit.cshtml和Delete.cshtml等4個視圖文件。

Index

修改Views/Role/Index.cshtml,用於列出所有角色。

Views/Role/Index.cshtml

@model IEnumerable<Microsoft.AspNet.Identity.EntityFramework.IdentityRole>
@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
                @Html.ActionLink("Delete", "Delete", new { id = item.Id })
            </td>
        </tr>
    }

</table>

Create

Views/Role/Create.cshtml

@model Microsoft.AspNet.Identity.EntityFramework.IdentityRole
@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>ApplicationUser</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Edit

Views/Role/Edit.cshtml

@model Microsoft.AspNet.Identity.EntityFramework.IdentityRole
@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>ApplicationUser</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.Id)

        <div class="form-group">
            @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Delete

Views/Role/Delete.cshtml

@model Microsoft.AspNet.Identity.EntityFramework.IdentityRole
@{
    ViewBag.Title = "Delete";
}

<h2>Delete</h2>

<h3>Are you sure you want to delete this?</h3>
<div>
    <h4>ApplicationUser</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.Name)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Name)
        </dd>
    </dl>

    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()

        <div class="form-actions no-color">
            <input type="submit" value="Delete" class="btn btn-default" /> |
            @Html.ActionLink("Back to List", "Index")
        </div>
    }
</div>

擴展用戶屬性

啟用 Entity Framework 合並

ASP.NET Identity 使用 Entity Framework Code First 作為基礎框架,擴展用戶屬性就意味着我們需要修改Code First模型,因此,我們需要啟用 Entity Framework 合並。

打開 程序包管理器控制台,在控制台窗口中輸入 Enable-Migrations 並回車。

工具(T) - NuGet 包管理器(N) - 程序包管理器控制台(O)

添加擴展屬性

在本文示例中我們為用戶類新增一個 BirthDate 屬性。

修改 Models\IdentityModels.cs 文件,在ApplicationUser類定義中增加BirthDate屬性。

Models\IdentityModels.cs(局部)

    public class ApplicationUser : IdentityUser
    {
        [Display(Name = "生日")]
        public DateTime BirthDate { get; set; }

使用 Add-Migrations 命令修改數據庫

由於我們為用戶類添加了一個新屬性,因此我們需要更新數據庫來反映這個變化。

這也是EF 合並的真正用處所在。

還是在 程序包管理器控制台 中進行操作,

輸入 Add-Migration "Birthdate"

該指令執行后將在項目中添加一個合並文件。

輸入 Update-Database

該指令將運行所有合並文件並更新數據庫以添加一個BirthDate 列

模型部分

修改Models\AccountViewModels.cs 文件,將 BirthDate 添加到 RegisterViewModel

Models\AccountViewModels.cs

    public class RegisterViewModel
    {
        [Required]
        [Display(Name = "所屬角色")]
        public string UserRoles { get; set; }

        [Required]
        [Display(Name = "用戶名")]
        public string UserName { get; set; }

        [Required]
        [EmailAddress]
        [Display(Name = "電子郵件")]
        public string Email { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "{0} 必須至少包含 {2} 個字符。", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "密碼")]
        public string Password { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = "確認密碼")]
        [Compare("Password", ErrorMessage = "密碼和確認密碼不匹配。")]
        public string ConfirmPassword { get; set; }
        
        [Display(Name = "生日")]
        public DateTime BirthDate { get; set; }
    }

視圖部分

更新 Views\Account\Register.cshtml 文件

Views\Account\Register.cshtml

@model UserRoleDemo.Models.RegisterViewModel
@{
    ViewBag.Title = "注冊";
}

<h2>@ViewBag.Title。</h2>

@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>創建新帳戶。</h4>
    <hr />
    @Html.ValidationSummary("", new { @class = "text-danger" })
    <!--用戶名-->
    <div class="form-group">
        @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
        </div>
    </div>
    <!--角色-->
    <div class="form-group">
        @Html.Label("user Role", new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.DropDownList("UserRoles", (SelectList)ViewBag.Name, " ")
        </div>
    </div>
    <!--生日-->
    <div class="form-group">
        @Html.LabelFor(m => m.BirthDate, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.BirthDate, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" class="btn btn-default" value="注冊" />
        </div>
    </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

控制器部分

更新Controllers\AccountController.cs 文件中的Register Action

Controllers\AccountController.cs(局部)

var user = new ApplicationUser { UserName = model.UserName, Email = model.Email, BirthDate = model.BirthDate };

運行程序,再次注冊用戶時就可以看到BirthDate字段的應用。

針對Controller或Action的授權

ASP.NET Identity使用Authorize特性實現了針對Controller或Action的授權功能,實際上這個特性是MVC功能的一部分,被稱為過濾器(Filter)。

過濾器(Filter)

ASP.NET MVC中把過濾器分為以下幾類:

身份驗證過濾器(IAuthenticationFilter)

這個過濾器是在MVC5中加入的,它是所有過濾器中優先級最高的,使用身份驗證過濾器可以為Action、Controller或者所有的Controller添加身份驗證邏輯。

授權過濾器(IAuthorizationFilter)

授權過濾器用來處理Controller以及Action的訪問限制。

Action方法過濾器(IActionFilter)

Action過濾器可用於在Action方法執行前和執行后添加邏輯。

結果過濾器(IResultFilter)

結果過濾器可以在結果執行前和執行后添加邏輯。

ASP.NET MVC中的Action返回結果為ActionResult類型,該抽象類型定義了一個執行方法ExecuteResult,結果的執行實際上是對返回結果的處理

異常過濾器(IExceptionFilter)

異常過濾器就是Action方法在執行的過程中拋出異常時,用來添加異常處理邏輯的過濾器。

為RoleController設置過濾器

如果我們需要設置RoleController只允許角色為“Admin”的用戶訪問,則需要修改Controller/RoleController.cs文件,為RoleController設置過濾器。

Controller/RoleController.cs(局部)

    [Authorize(Order = 0, Roles = "Admin")]
    public class RoleController : Controller

為RoleController中的Create Action設置過濾器

只允許角色為“Admin”且用戶名為“admin”的用戶訪問。

Controller/RoleController.cs(局部)

        // GET: Role/Create
        [Authorize(Order =1,Roles ="Admin",Users ="admin")]
        public ActionResult Create()
        {
            return View();
        }

結束語

本文僅就 ASP.NET Identity 的一些最為常用的功能進行了介紹,后續將逐步為大家介紹郵箱認證、短信認證、找回密碼、第三方賬號登錄等功能,敬請期待。

參考文章


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM