• [转]mvc5+ef6+Bootstrap 项目心得--身份验证和权限管理


    本文转自:http://www.cnblogs.com/shootingstar/p/5629668.html

    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文件

    复制代码
    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得到用户名
  • 相关阅读:
    OutputStream (字节流写出)
    Reader(字符流读取)
    InputStream (字节流读取)
    File
    IO简介
    BigDecimal
    SimpleDateFormat
    Date和Calendar
    包装类
    本地与远程对应分支,本地建立分支,修改代码, 上传到远程对应的分支
  • 原文地址:https://www.cnblogs.com/freeliver54/p/6427486.html
Copyright © 2020-2023  润新知