从零开始搭建前后端分离的NetCore2.2(EF Core CodeFirst+Autofac)+Vue的项目框架之九如何进行用户权限控制

  在一般的前后端分离的web系统开发中,在服务端除了对用户数据的缓存之外,往往在某些接口上,还涉及到对用户权限的限制,有的接口只能让具有特定权限的人员才可以访问

  这样以来就可以加强系统的安全性,在前面章节中简单讲了 MemoryCache与redis缓存的使用 ,方便将用户数据缓存到服务器上在需要的时候快速取出使用与验证,

  下面我们就讲讲如何进行用户权限的验证,以下将是一个简单的示例,可以根据需求自行调节,权限组也可以根据数据库配置实现等等

  在前面已经有 Token 验证 以及 用户数据 缓存的情况下,新建 用户验证 的 过滤器 类  UserAuthorize  继承  ActionFilterAttribute 属性  

    /// <summary>
    /// 用户权限验证
    /// </summary>
    public class UserAuthorize : ActionFilterAttribute
    {
        public UserAuthorize()
        {
        }
        public List<long> Popedoms { get; set; }//驼峰命名   首字母大写


        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="popedom">权限组</param>
        public UserAuthorize(params long[] popedom)
        {
            Popedoms = popedom.ToList();
        }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //整个类是否设置了都可以访问
            if (filterContext.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
            {
                var isDefined = controllerActionDescriptor.MethodInfo.GetCustomAttributes(true)
                    .Any(a => a.GetType() == typeof(AllowAnonymousAttribute));
                if (isDefined)
                {
                    return;
                }
            }

            var user = UserCache.GetCurrentUser();//获取当前用户
            if (user != null && Popedoms?.Contains(user.PopedomId) == true)
            {
                return;
            }

            if (user == null)
            {
                filterContext.Result = new CustomHttpStatusCodeResult(200, 401, "授权已失效请重新登录");
            }
            else
            {
                filterContext.Result = new CustomHttpStatusCodeResult(200, 402, "您无权进行该操作,请联系管理员!");
            }

        }
    }

  涉及到的相关代码  在之前添加的  UserCache  类中添加代码如下:  完整代码,文章最下面有GitHub 地址

        /// <summary>
        /// 获取当前用户
        /// </summary>
        /// <returns></returns>
        internal static UserDto GetCurrentUser()
        {
            var key = DemoWeb.HttpContext.Request.Headers["sid"];
            if (string.IsNullOrEmpty(key))
            {
                return null;
            }
            var user = Get(key);
            if (string.IsNullOrEmpty(user))
            {
                return null;
            }
            return user.ToNetType<UserDto>();
        }

  接下来 我们添加登录测试伪代码 然后将用户数据存进缓存 再调用添加了权限验证的接口,来验证权限验证是否可用,

  新建用户相关控制器  UserController ,继承之前的用户基础控制器 BaseUserController ,要有权限验证,肯定得先登录,示例代码如下:

    [Route("api/[controller]")]
    public class UserController : BaseUserController
    {
        [HttpPost, Route("login"),AllowAnonymous]//AllowAnonymous加上这一句 为任何用户可访问,在基础控制器中有设置
        public ActionResult Login()
        {
            //调用登录方法进行登录 在业务层处理  将登录成功的用户信息缓存 以及生成token
            //此处示例 为了方便就直接在控制器中编写
            var token = TokenManager.GenerateToken("测试token的生成");
            Response.Headers["token"] = token;
            //Response.Headers["Access-Control-Expose-Headers"] = "token"; //需要同时设置 不然后者会冲突掉前者
            var user = new UserDto()
            {
                UserName = "Levy",
                Email = "levy_w_wang@qq.com",
                Age = 23,
                PopedomId = 999
            };
            var sessionId = Guid.NewGuid().ToString("N");
            DemoWeb.HttpContext.Response.Headers["sid"] = sessionId;
            UserCache.Set(sessionId,user.ToJson());
            DemoWeb.HttpContext.Response.Headers["Access-Control-Expose-Headers"] = "token,sid";//前后端分离 跨域的情况下  加上这句 前端才能拿到 sid 字段对应值 多个用英文逗号分隔
            return Succeed(user);
        }

        /// <summary>
        /// 用户权限为888 或者为 999 的才能访问
        /// </summary>
        /// <returns></returns>
        [HttpPost,Route("popedom"),UserAuthorize(888,999)]
        public ActionResult PopedomTest()
        {
            return Succeed("成功访问");
        }
    }

  运行程序,打开接口测试工具,先访问登录接口,然后将得到的 Token 和 sid 拿来 调用 权限测试接口 我们就可以得到如下结果:截图如下:

再然后调试登录,把登录的权限改为不在权限控制的值之类,再次拿着返回的sid 及 Token 来访问权限测试接口,就会得到如下结果:

这里只是做了一个简单权限验证测试,灵活运用需结合数据库及缓存,也可以根据权限设置好响应的过滤器等等方式。

 

有需要源码的可通过此 GitHub 链接拉取 觉得还可以的给个 start 和点个 下方的推荐哦~~谢谢!

下一篇可能会讲到如何将数据库访问封装基础方法来方便使用或者常用加密等~

posted @ 2019-11-10 00:09  Levy-伟  阅读(1557)  评论(0编辑  收藏  举报