码迷,mamicode.com
首页 > Web开发 > 详细

MVC身份验证及权限管理

时间:2018-09-22 00:54:55      阅读:265      评论:0      收藏:0      [点我收藏+]

标签:compose   size   默认   models   问题   name   ber   +=   经验   

本文旨在简单介绍mvc的权限验证。

一、Forms认证

1、首先是建一个asp.net web应用程序

技术分享图片

 

为了实现身份验证,所以必须要添加一个登陆页面,同时还需要有对应的用户类型,所以添加了以下代码

IUserDb接口。其实这个接口可以不用,但是在这里我用的是MEF组件来实现依赖注入。所以有了这个接口
namespace QuanXianYanZheng.Interface
{
    interface IUserDb
    {
        bool ValidateUser(string userName, string password);
        string[] GetRoles(string userName);
        Models.User GetByNameAndPassword(string name, string password);
    }
}

UserDb,这个类实际上是模拟数据库操作的。export是MEF组件实现依赖注入的,可以看看前一篇随笔了解。
namespace QuanXianYanZheng.DB
{
    [Export("UserDb",typeof(IUserDb))]
    public class UserDb: IUserDb
    {
        //模拟数据库,用户表
        private static User[] usersForTest = new[]{
            new User{ ID = 1, Name = "bob", Password = "bob", Roles = new []{"employee"}},
            new User{ ID = 2, Name = "tom", Password = "tom", Roles = new []{"manager"}},
            new User{ ID = 3, Name = "admin", Password = "admin", Roles = new[]{"admin"}},
            };
        /// <summary>
        /// 验证用户密码
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public bool ValidateUser(string userName, string password)
        {
            return usersForTest
                .Any(u => u.Name == userName && u.Password == password);
        }
        /// <summary>
        /// 获取用户的角色
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public string[] GetRoles(string userName)
        {
            return usersForTest
                .Where(u => u.Name == userName)
                .Select(u => u.Roles)
                .FirstOrDefault();
        }
        /// <summary>
        /// 获取用户
        /// </summary>
        /// <param name="name"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public User GetByNameAndPassword(string name, string password)
        {
            return usersForTest
                .FirstOrDefault(u => u.Name == name && u.Password == password);
        }
    }
}

User,用户模型

namespace QuanXianYanZheng.Models
{
    public class User
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Password { get; set; }
        public string[] Roles { get; set; }
    }
}
AccountController 登陆页面的控制器
namespace QuanXianYanZheng.Controllers
{
    public class AccountController : Controller
    {
        [Import("UserDb")]
        private IUserDb Repository { set; get; }


        public ActionResult LogOn()
        {
            return View();
        }
        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                if(null==Repository) CustomTool.Compose(this);
                if (Repository.ValidateUser(model.UserName, model.Password))
                {
                    //将用户信息保存到cookie,如果不能使用cookie则添加到URL
                    FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                    if (!String.IsNullOrEmpty(returnUrl)) return Redirect(returnUrl);
                    else return RedirectToAction("Index", "Home");
                }
                else
                    ModelState.AddModelError("", "用户名或密码不正确!");
            }
            return View(model);
        }

    }
}
Compose,这个是为了实现依赖注入来实例化对象专门写的一段公共代码,如果不用这种方式来实例化对象,可以不要这段。
namespace QuanXianYanZheng
{
    public class CustomTool
    {
        /// <summary>
        /// 这个是为了实现依赖注入的方式来实例化对象而必须要执行的一段代码
        /// </summary>
        /// <param name="o"></param>
        public static void Compose(object o)
        {
            var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            CompositionContainer container = new CompositionContainer(catalog);
            container.ComposeParts(o);
        }
    }
}

LogOnModel类太简单了,就不贴代码了。然后创建登陆页面,就两个文本框一个登陆按钮,也没什么难度了。然后就是Global.asax,在类MvcApplication中添加一个构造函数,代码如下:

     [Import("UserDb")]
        private IUserDb Repository { set; get; }
        /// <summary>
        /// 添加构造函数
        /// </summary>
        public MvcApplication()
        {
            AuthorizeRequest += new EventHandler(MvcApplication_AuthorizeRequest);
        }
        void MvcApplication_AuthorizeRequest(object sender, EventArgs e)
        {
            IIdentity id = Context.User.Identity;
            if(null== Repository) CustomTool.Compose(this);//这个是为了实现依赖注入的方式而调用的
            if (id.IsAuthenticated)//这里判断访问者是否成功进行了身份验证
            {
                var roles = Repository.GetRoles(id.Name);
                Context.User = new GenericPrincipal(id, roles);
            }            
        }

至此,代码基本写好了,然后运行程序,将断点打在此处:

技术分享图片

会发现程序每次进入后台控制器之前,都会经过这里,不管你有没有进行成功的登录,这个if语句的判断条件都是false。这很显然不符合我的要求,我要的是在成功登录后,这个判断是true。之所以出现现在的情况,是因为配置文件还没有相关的配置:

技术分享图片

有了这段配置之后,再次运行程序。默认还是进入了home/index页面,这与我的要求是有出入的,我要求在用户没登陆的情况下,默认进入登陆页面。这个问题先放着,后面会解决。这里之所以进入的是home/index页面,是因为路由的配置是这样的,没什么可说的。

运行程序后,在没有登录的情况下,上面的断点一直是false,但如果登录成功后,就会变成true了。有这样的变化,是因为执行了下面这条语句

技术分享图片

现在来处理刚才提到的在没有登录的时候默认进入了home/index页面的问题,解决这个问题不需要去修改路由的配置,只需要在HomeController的index方法上添加特性 [Authorize]即可。

 技术分享图片

再次运行程序之前记得清空浏览器缓存,因为刚才已经成功登陆过了,使得上面断点的地方判断的是true,默认的是已经验证过了,因此还是会进入home/index页面,所以必须清空缓存。这样就可以看到再次默认进入的是登陆页面了。

 未完待续....

 

MVC身份验证及权限管理

标签:compose   size   默认   models   问题   name   ber   +=   经验   

原文地址:https://www.cnblogs.com/jin-/p/9688732.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!