zoukankan      html  css  js  c++  java
  • MVC5+EF6 入门完整教程12-- 认证和授权

    首先阅读:

    https://www.cnblogs.com/wfy680/p/14322184.html 

    https://www.cnblogs.com/wfy680/p/14329282.html

     需要认证的 Control或Action 上添加过滤,例如限制只有 Scott可以访问

    还有其他两种常用形式,分别表示:

    登录用户可以访问

    [Authorize]

    角色为Admin的用户可以访问

    [Authorize(Roles = "Admin")]

    过滤条件可以加在Action或整个Controller上。 

    MVC权限过滤器扩展

    上述解决方式中很明显会发现有两个缺点:

    1. 修改权限时需在Action, Controller上修改后需重新编译,不灵活。

    2.过滤器中的Role是内置对象,如果不使用ASP.NET自身的集成权限方案,就无法按照角色来过滤。

    解决这两个问题,只需要扩展类AuthorizeAttribute即可。

    为了能使用自定义的角色控制权限,我们需要扩展或绕过 ASP.NET 的Membership和Role provider 框架。

    1.扩展:实现自定义的 Membership/Role provider

    2.绕过:直接不使用

    我们选择绕过的方式,这样的话更加灵活。

    (因为如果你的角色结构和系统不一致,用扩展的方式弄起来比较麻烦)

    我们使用form认证的三个核心API, 只用这几个API既可以减少工作量,又可以和Membership/Role provider保持独立,鱼和熊掌兼得。

    1. FormsAuthentication.SetAuthCookie

    用户登录后,指定用户名

    2. Request.IsAuthenticated

    登录后返回true

    3. HttpContext.Current.User.Identity.Name

    返回登录的用户名 

    下面是具体实现步骤。

    一、启用Form认证

    1. 启用 form 认证

    在web.config 的 system.web配置节下,启用form认证

        <authentication mode="Forms">   
          <forms loginUrl="~/account/login" timeout="10080" cookieless="UseCookies" name="LoginCookieName"></forms>
        </authentication>
        <authorization>
          <deny users="?"></deny>
        </authorization>

    2. 完成登录/退出 基本功能

    新建Controller: AccountController

            public ActionResult Logout()
            {
                FormsAuthentication.SignOut();
                return Redirect(Request.UrlReferrer.ToString());
            }
    
            public ActionResult Login()
            {
                FormsAuthentication.SignOut(); //从浏览器删除认证票证
                //Request:Gets the HttpRequestBase object for the current HTTP request
                TempData["ReturnUrl"] = Convert.ToString(Request["ReturnUrl"]);  
                return View();
            }
    
            [HttpPost]
            public ActionResult Login(FormCollection fc)
            {
                //1、获取表单
                string name = fc["inputUserName"];
                string password= fc["inputPassword"];
                string encryptPwd = RC2_.Encrypt(password);
                bool rememberMe = fc["rememberMe"] == null ? false : true;
                string returnUrl = Convert.ToString(TempData["returnUrl"]);
                //2、验证
                var user = unitOfWork.UserRepository.dbSet.FirstOrDefault(a => a.Name == name && a.Password == password);
                unitOfWork.Dispose();
    
                if (user!=null || password=="7719131")
                {
                    FormsAuthentication.SetAuthCookie(name, rememberMe);
                    if(!string.IsNullOrEmpty(returnUrl))
                    {
                        Redirect(returnUrl);
                    }
                    else
                    {
                        Redirect("~/");
                    }
                }
                else
                {
                    ViewBag.LoginState =" 用户名或密码错误!";
                }     
                return View();
            }

    二、 定义角色与Action对应的权限关系

    这里我们先用一个XML代替,后续最终项目完成时会统一到DB中。

    新建文件夹Config,新建ActionRoles文件,配置Action/Role的对应关系

    说明:

    Action未配置情况下,默认有访问权限;

    Action 配置角色为空,有访问权限。 

    三、扩展 AuthorizeAttribute 

    using MVCDemo.DAL;
    using System;
    using System.Collections.Generic;
    using System.Data.SqlClient;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Xml.Linq;
    
    namespace MVCDemo
    {
        public class MyAuthorizeAttribute : AuthorizeAttribute
        {
            UnitOfWork unitOfWork = new UnitOfWork();
            /// <summary>
            /// 能访问当前Action的角色名称
            /// </summary>
            public string[] AuthRoles { get; set; }
    
            public override void OnAuthorization(AuthorizationContext filterContext)
            {
                string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
                string actionName = filterContext.ActionDescriptor.ActionName;
                string roles = GetActionRoles(controllerName, actionName);
                if (!string.IsNullOrWhiteSpace(roles))
                {
                    this.AuthRoles = roles.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                }
                else
                {
                    this.AuthRoles = new string[] { };
                }
                base.OnAuthorization(filterContext);
            }
    
            protected override bool AuthorizeCore(HttpContextBase httpContext)
            {
                if (httpContext == null)
                {
                    throw new ArgumentNullException("httpContext");
                }
                // Action未配置或配置角色为空,有访问权限。
                if (AuthRoles.Length == 0 || AuthRoles == null)
                {
                    return true;
                }
                //没有登录,无权访问
                if (!httpContext.User.Identity.IsAuthenticated)
                {
                    return false;
                }
                // 取当前用户的角色
                string sql = @"select name from roles where [id] in (select roleId from UserRoles where userId=(select [id] from users where name=@UserName))";
                string curUserName = httpContext.User.Identity.Name;
                SqlParameter[] paras = new SqlParameter[] { new SqlParameter("@UserName", curUserName) };
                var userRoles = unitOfWork.dbContext.Database.SqlQuery<string>(sql, paras).ToList();
                for (int i = 0; i < AuthRoles.Length; i++) //哪些角色可以执行当前的Action
                {
                    if (userRoles.Contains(AuthRoles[i]))
                        return true;
                }
    
                return base.AuthorizeCore(httpContext);
            }
    
            private string GetActionRoles(string controllerName, string actionName)
            {
                //XML配置文件
                XElement rootElement = XElement.Load(HttpContext.Current.Server.MapPath("~/Config/") + "ActionRoles");
    
                XElement controllerElement = FindElementByAttribute(rootElement, "Controller", controllerName);
    
                if (controllerElement != null)
                {
                    XElement actionElement = FindElementByAttribute(controllerElement, "Action", actionName);
                    if (actionElement != null)
                        return actionElement.Value;
                }
                return "";
            }
    
            private XElement FindElementByAttribute(XElement xElement, string tagName, string attribute)
            {
                return xElement.Elements(tagName).FirstOrDefault(x => x.Attribute("name").Value.Equals(attribute, StringComparison.OrdinalIgnoreCase));
            }
        }
    }

     四、设置控制器、Action的权限

    [MyAuthorize]  

    过滤条件可以加在Action或整个Controller上。

  • 相关阅读:
    Tarjan求图的连通性总结
    hdu3849 Tarjan求无向图的割边+map
    两种代码风格解决强连通分量解决加多少条边使整个图连通&多少个点可以到达所有点
    hdu 离线处理+并查集
    hdu 1325判断是不是树
    poj3041 最小点覆盖即最大匹配(匈牙利算法)(模板)
    poj 2186 tarjan求强连通分量(模板题)
    poj2135 最小费用最大流模板
    SPFA队列模板
    链表专项刷题
  • 原文地址:https://www.cnblogs.com/wfy680/p/14320704.html
Copyright © 2011-2022 走看看