mvc5+ef6+Bootstrap 項目心得--身份驗證和權限管理


1.mvc5+ef6+Bootstrap 項目心得--創立之初

2.mvc5+ef6+Bootstrap 項目心得--身份驗證和權限管理

3.mvc5+ef6+Bootstrap 項目心得--WebGrid

最近和朋友完成了一個大單子架構是mvc5+ef6+Bootstrap,用的是vs2015,數據庫是sql server2014。朋友做的架構,項目完成后覺得很多值得我學習,在這里總結下一些心得。先說明,以下方法是創建項目時選擇MVC,而不是Empty。所以有許多多余的東西,如果選擇Empty創建項目,請看目錄1

創建項目一開始刪掉App_Start目錄下的IdentityConfig.cs和Startup.Auth.cs文件;清空Modle文件夾,Controller文件夾和相應的View; 刪除目錄下的ApplicationInsights.config文件和Startup.cs文件。(不使用自帶的Identity,太多內容不需要)

修改web.config文件(添加<add key="owin:AutomaticAppStartup" value="false"/>不使用Startup.cs文件來啟動項目)

<appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    <add key="owin:AutomaticAppStartup" value="false"/> <!--去掉創建項目初的Startup.cs文件的設置-->
  </appSettings>
<modules>
      <remove name="FormsAuthentication"/>
    </modules>
這句在web.config里面必須去掉,不然User.Identity不起作用

 

(不用他們是因為自帶的這些內容太冗余)

 

1.首先介紹數據庫這一塊,數據庫我們是配置的可以使用NuGet命令手動生成和修改的。在項目目錄想創建Migrations文件夾,里面添加Configuration.cs文件

(也可以使用NuGet命令開啟Code First Migrations功能

Enable-Migrations -ContextTypeName EFTrain.Models.EFTrainContext(命名空間.文件名)
internal sealed class Configuration : DbMigrationsConfiguration<AccountContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
            ContextKey = "UserProject.DAL.AccountContext";
        }
        protected override void Seed(AccountContext context)
        {
            //base.Seed(context);
        }
    }

在Model文件夾下添加AccountContext.cs文件

public class AccountContext:DbContext
    {
        public AccountContext():base("AccountContext") {

        }

        public DbSet<User> Users { get; set; }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }
    }
<connectionStrings>
    <add name="AccountContext" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\UserProject.mdf;Initial Catalog=UserProject;Integrated Security=True" providerName="System.Data.SqlClient" />
  </connectionStrings>

然后 使用vs2015里面的工具-NuGet包管理器-程序包管理控制平台

輸入add-migration Initial 按回車,在輸入update-database按回車。在App_Data文件夾下就會看到AccountContext數據庫了。

2.創建測試用的Model

在Model文件夾下添加User.css文件

public class User
    {
        public int ID { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public Role Role { get; set; }
    }
public enum Role//角色枚舉
{ 管理員 = 1, 員工 = 2, 經理 = 3, 總經理 = 4, 董事長 = 5 }

在ViewModel文件夾中添加Account.cs文件

public class Account
    {
        [Required]
        public string Name { get; set; }
        [Required]
        public string Password { get; set; }

        public string RePassword { get; set; }
    }

3.創建測試用到的Controller

這里推薦創建BaseController,之后的Controller就繼承它來使用

public class BaseController : Controller
    {
        public string UserName => User.Identity.Name;
        public AccountContext db = new AccountContext();
        private User _userInfo = null;
        public User CurrentUserInfo
        {
            get
            {
                if (_userInfo == null)
                {
                    var user = db.Users.SingleOrDefault(u => u.UserName == UserName);//此處為了不每次訪問用戶表可以做一個靜態類,里面存放用戶表信息.
                    _userInfo = user == null ? null : new User()
                    {
                        ID = user.ID,
                        UserName = user.UserName,
                        Role = user.Role
                    };
                }
                return _userInfo;
            }
        }
    //驗證角色:獲取Action的CustomAttributes,過濾角色
protected override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); var authRoleAtt = filterContext.ActionDescriptor.GetCustomAttributes(false).SingleOrDefault(att => att is AuthorizeRoleAttribute) as AuthorizeRoleAttribute; if (authRoleAtt == null && CurrentUserInfo != null) return; if (!authRoleAtt.Roles.Contains(CurrentUserInfo.Role)) { filterContext.Result = View("NoPermission", "_Layout", "您沒有權限訪問此功能!"); } }
//這里是記log用
protected override void OnActionExecuted(ActionExecutedContext filterContext) { base.OnActionExecuted(filterContext); var msg = $"用戶: {CurrentUserInfo?.UserName}, 鏈接: {Request.Url}"; if (Request.HttpMethod == "POST") msg += $", 數據: {HttpUtility.UrlDecode(Request.Form.ToString())}"; //Log.Debug(msg); } }
public class AuthorizeRoleAttribute : Attribute
    {
        public List<Role> Roles { get; set; }
        public AuthorizeRoleAttribute(params Role[] roles)
        {
            Roles = new List<Role>(roles);
        }
    }

 

AdminController繼承BaseController

[Authorize]
        public ActionResult Index()
        {
            return View(db.Users.ToList());
        }

        
        [Authorize, AuthorizeRole(Role.管理員)]
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            User user = db.Users.Find(id);
            if (user == null)
            {
                return HttpNotFound();
            }
            return View(user);
        }

 4.創建Action和VIew

登錄頁面:

@model UserProject.ViewModels.Account
@{
    ViewBag.Title = "Login";
}

@using (Html.BeginForm("Login", "Admin",FormMethod.Post, new { @class = "form-horizontal", role = "form" })) {
    @Html.AntiForgeryToken()
    <hr />
                @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                <div class="form-group">
                    @Html.LabelFor(m => m.Name, new { @class = "col-md-2 control-label" })
                    <div class="col-md-10">
                        @Html.TextBoxFor(m => m.Name, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.Name, "", 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">
                        <input type="submit" value="登錄" class="btn btn-primary" />
                    </div>
                </div>
}

登錄的Action:

[AllowAnonymous]
        public ActionResult Login()
        {

            return View();
        }

        [HttpPost, AllowAnonymous]
        public ActionResult Login(Account model)
        {
            if (ModelState.IsValid)
            {
                var user = db.Users.SingleOrDefault(t => t.UserName == model.Name && t.Password == model.Password);
                if (user != null)
                {
                    FormsAuthentication.SetAuthCookie(model.Name, false);//將用戶名放入Cookie中

                    return RedirectToAction("Index");
                }
                else
                {
                    ModelState.AddModelError("Name", "用戶名不存在!");
                }
            }
            return View(model);
        }

        public ActionResult LogOff()
        {
            FormsAuthentication.SignOut();
            return RedirectToAction("Login");
        }

 

通過以上方式就完成了用戶的登錄和權限的控制, 訪問Details這個Action的時候必須是管理員角色。

如果需要多個角色使用Action可以:[Authorize, AuthorizeRole(Role.管理員,Role.經理)]

使用此方法登錄的用戶保存在Cookie里面 :FormsAuthentication.SetAuthCookie(model.Name, false);
在Controller和View里面直接使用User.Identity得到用戶名

此僅僅是測試項目,作為完成私活的部分知識點的總結。
 

 


免責聲明!

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



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