通过建立自己的AuthorizeAttribute实现网站的权限管理

news/2024/5/20 13:20:47/文章来源:https://blog.csdn.net/weixin_34209406/article/details/92213207

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

当我们用.net MVC构建网站平台的时候,势必会对网站平台的安全性和用户的使用权限进行一个统一的构建,首先在.net MVC 架构中,系统已经将权限管理分为三个层面来进行管理,第一层面是 登录管理,也就是说在这个层面上完成用户口令的验证,即完成用户的登录,系统保存用户的登录记录。第二层面是授权,即赋予用户是否具备使用权限,是通过 AuthorizeAttribute 的特性来进行控制和管理的。第三个层面是是凭据缓存机制,系统建立System.Security.Claims.Claim来实现的,一旦登录成功系统就会在Cookies里面缓存给用户一个Claim,这样完成了用户登录信息的缓存。

那么如果对某一个模块具体进行权限控制呢?为了建立一个更加灵活的管理机制,我们采用了建立自己的 AuthorizeAttribute 来完成。首先我们来对需求进行一个简单的分析,如下图所示:一个功能模块我们可以通过指定用户,或指定权限来完成,也可能在使用时,通过角色和权限的控制来完成。

105013_h2K3_2308182.png也就是说用户可以通过用户,也可以通过角色来进行控制,也可以在运行期通过角色和功能模块的指定来进行。

针对这个需求,我们建立了如下数据结构:

105450_56Ln_2308182.png

人员和角色是通过用户归属角色表进行关联的,而“功能权限控制”是功能直接和用户还是角色关联控制的。

为了实现这个功能设计,首先我们先在Models中建立四个基础信息类

namespace VonPortal.Web.Models
{/// <summary>人员基本信息 信息类</summary>public class UserInfo : IUser<int>{public int Id{get { return ID; }}#region "Public Properties"/// <summary>序号</summary>[Required][Display(Name = "序号")]public int ID { get; set; }/// <summary>登录名</summary>[Required][Display(Name = "登录名")]public string UserName { get; set; }/// <summary>姓氏</summary>[Display(Name = "姓氏")]public string FirstName { get; set; }/// <summary>名字</summary>[Display(Name = "名字")]public string LastName { get; set; }/// <summary>显示名称</summary>[Display(Name = "显示名称")]public string DisplayName { get; set; }/// <summary>称谓</summary>[Display(Name = "称谓")]public string Title { get; set; }/// <summary>简称</summary>[Required][Display(Name = "简称")]public string ShortName { get; set; }/// <summary>电子邮箱</summary>[Required][Display(Name = "电子邮箱")]public string EMail { get; set; }/// <summary>登录口令</summary>[Display(Name = "登录口令")]public string Password { get { return _Password; } set { _Password = UserCtrl.CryptPassword(value); } }internal string _Password = "";/// <summary>创建时间</summary>[Display(Name = "创建时间")]public DateTime CreateDate { get; set; }/// <summary>最后访问时间</summary>[Display(Name = "最后访问时间")]public DateTime LastAccess { get; set; }#endregion}
}
#region "角色信息信息类声明"
namespace VonPortal.Web.Models
{/// <summary>角色信息 信息类</summary>public class RoleInfo : IRole<int>{public int Id{get{return ID;}}public string Name{get{return RoleName;}set{RoleName = value;}}#region "Constructors"/// <summary>/// 构造函数/// </summary>public RoleInfo(){}/// <summary>/// 含初始化构造函数/// </summary>/// <param name="ID">序号</param>/// <param name="GroupName">组名称</param>/// <param name="RoleName">角色名称</param>/// <param name="SiteIdx">站点序号</param>/// <param name="ParentIdx">上级节点</param>/// <param name="InheritKind">继承关系</param>/// <param name="Description">角色说明</param>public RoleInfo(int ID, string GroupName, string RoleName, int SiteIdx, int ParentIdx, int InheritKind, string Description){this.ID = ID;this.GroupName = GroupName;this.RoleName = RoleName;this.SiteIdx = SiteIdx;this.ParentIdx = ParentIdx;this.InheritKind = InheritKind;this.Description = Description;}#endregion#region "Public Properties"/// <summary>序号</summary>[Required][Display(Name = "序号")]public int ID { get; set; }/// <summary>组名称</summary>[Display(Name = "组名称")]public string GroupName { get; set; }/// <summary>角色名称</summary>[Display(Name = "角色名称")]public string RoleName { get; set; }/// <summary>站点序号</summary>[Required][Display(Name = "站点序号")]public int SiteIdx { get; set; }/// <summary>上级节点</summary>[Required][Display(Name = "上级节点")]public int ParentIdx { get; set; }/// <summary>继承关系</summary>[Display(Name = "继承关系")]public int InheritKind { get; set; }/// <summary>角色说明</summary>[Display(Name = "角色说明")]public string Description { get; set; }#endregion}
}
#endregion
//功能权限控制(PTL_ActionRight)
#region "功能权限控制信息类声明"
namespace VonPortal.Web.Models
{/// <summary>功能权限控制 信息类</summary>public class ActionRightInfo{#region "Constructors"/// <summary>/// 构造函数/// </summary>public ActionRightInfo(){}/// <summary>/// 含初始化构造函数/// </summary>/// <param name="ID">序号</param>/// <param name="SiteIdx">站点序号</param>/// <param name="RightName">功能名称</param>/// <param name="RoleOrUser">角色或用户序号</param>/// <param name="SrcIdx">控制源序号</param>public ActionRightInfo(int ID, int SiteIdx, string RightName, bool RoleOrUser, int SrcIdx){this.ID = ID;this.SiteIdx = SiteIdx;this.RightName = RightName;this.RoleOrUser = RoleOrUser;this.SrcIdx = SrcIdx;}#endregion#region "Public Properties"/// <summary>序号</summary>[Required][Display(Name = "序号")]public int ID { get; set; }/// <summary>站点序号</summary>[Required][Display(Name = "站点序号")]public int SiteIdx { get; set; }/// <summary>功能名称</summary>[Display(Name = "功能名称")]public string RightName { get; set; }/// <summary>角色或用户序号</summary>[Required][Display(Name = "角色或用户序号")]public bool RoleOrUser { get; set; }/// <summary>控制源序号</summary>[Required][Display(Name = "控制源序号")]public int SrcIdx { get; set; }#endregion}
}
#endregion

其控制与数据库存储的类,这里就省略了,首先大家知道,要实现这个方案,作为基础的信息基类,就是这三个类即,UserInfo、RoleInfo、ActionRightInfo。

我们下面就进入今天的主题,如何通过建立自己的AuthorizeAttribute特性来实现角色控制。

我们先来分析一下AuthorizeAttribute的执行过程。在特性指定到系统的某一个模块上时,即为某一个 Controller 指定一个我们自己的权限认证特性,指定后,当系统执行时,系统就会调用 AuthorizeAttribute 中的 OnAuthorization 函数来完成,在 OnAuthorization 函数的执行过程中,系统会调用 bool AuthorizeCore(HttpContextBase httpContext) 函数完成具体的验证过程,如果失败了,系统会调用 void HandleUnauthorizedRequest(AuthorizationContext context)来进行处理,由此我们就可以建立一个自己的 AuthorizeAttribute 

/******************************************************************************************************************
* 权限验证单元
*   RightAuthorizeAttribute 是继承 AuthorizeAttribute 的权限控制属性,他是基于功能的权限认证模式,即采用功能名称
*   进行认证,认证过程基于 AuthorizeAttribute 进行,首先系统会调用 OnAuthorization 进行验证,在这里我们主要进行
*   验证前准备,
****************************************************************************************************************/
using System;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web;
using System.Collections.Generic;
using VonPortal.Web.Operators;namespace VonPortal.Web.Models
{/// <summary>/// 权限控制单元/// </summary>public class RightAuthorizeAttribute : AuthorizeAttribute{/// <summary>/// 功能名称/// </summary>public string ActionNames { get; set; }private string moduleName = "";public override void OnAuthorization(AuthorizationContext filterContext){string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;string actionName = filterContext.ActionDescriptor.ActionName;moduleName = controllerName + '/' + actionName;base.OnAuthorization(filterContext);}protected override bool AuthorizeCore(HttpContextBase httpContext){bool result = false;if (httpContext == null)throw new ArgumentNullException("HttpContext");if (!httpContext.User.Identity.IsAuthenticated)return false;// 得到用户的唯一序号int userIdx = httpContext.User.Identity.GetUserId<int>();List<int> roles = (new UserRoleCtrl(null)).ListByROLE_REF_USER(userIdx);#region "检测 Roles 即,检测指定的 Role 是否存在,如果设定了,但不存在则表明无权访问。"if (Roles != null && Roles.Length > 0){string authRole = "," + Roles.ToLower() + ",";result = false;foreach (int roleIdx in roles){RoleInfo role = (new RoleCtrl(null)).GetByRole(roleIdx);result = role != null && authRole.IndexOf("," + role.RoleName.ToLower() + ",") >= 0;if (result) break;}if (!result) return false;}#endregion#region "检测 Users 即,检测指定的 Users 是否存在,如果设定了,但不存在则表明无权访问。"string userName = httpContext.User.Identity.GetUserName();if (Users != null && Users.Length > 0){if (("," + Users.ToLower() + ",").IndexOf("," + userName.ToLower() + ",") < 0)return false;result = true;}#endregion#region "检测 ActionNames 即,检测指定的 ActionNames 是否存在,如果设定了,但不存在则表明无权访问。"if (ActionNames != null && ActionNames.Length > 0){string authAction = "," + ActionNames.ToLower() + ","; // 检测用户本身是否具备该功能的权限foreach (ActionRightInfo right in (new ActionRightCtrl(null)).ListBySrcIdx(true, userIdx)){if (ActionNames.IndexOf("," + right.RightName + ",") >= 0) return true;}// 检测用户拥有的角色本身是否具备该功能的权限foreach (int roleIdx in roles){foreach (ActionRightInfo right in (new ActionRightCtrl(null)).ListBySrcIdx(false, roleIdx)){if (ActionNames.IndexOf("," + right.RightName + ",") >= 0) return true;}}}else if (!result){string authAction = "," + moduleName.ToLower() + ",";// 检测用户本身是否具备该功能的权限foreach (ActionRightInfo right in (new ActionRightCtrl(null)).ListBySrcIdx(true, userIdx)){if (ActionNames.IndexOf("," + right.RightName + ",") >= 0) return true;}// 检测用户拥有的角色本身是否具备该功能的权限foreach (int roleIdx in roles){foreach (ActionRightInfo right in (new ActionRightCtrl(null)).ListBySrcIdx(false, roleIdx)){if (ActionNames.IndexOf("," + right.RightName + ",") >= 0) return true;}}}#endregionreturn result;}protected override void HandleUnauthorizedRequest(AuthorizationContext context){if (context == null){throw new ArgumentNullException("filterContext");}else{string path = context.HttpContext.Request.Path;string strUrl = "/Account/Login?returnUrl={0}";context.HttpContext.Response.Redirect(string.Format(strUrl, HttpUtility.UrlEncode(path)), true);}}}
}

使用方法:

在Controller中的Action使用前增加我们的RightAuthorize的特性就可以了。

1、指定功能名称验证用户权限:

        [RightAuthorize(ActionNames = "UserManager")]

        public ActionResult UserList(...){...}

2、指定角色名称证用户权限:

        [RightAuthorize(Roles = "Admin")]

        public ActionResult UserDetails(...){...}

3、指定用户名称证用户权限:

        [RightAuthorize(Users = "Administrator,Host")]

        public ActionResult UserEdit(...){...}

4、默认通过Controller+Action来验证用户权限:默认的功能名称是ControllerName/ActionName

        [RightAuthorize()]

        public ActionResult UserDelete(...){...}


转载于:https://my.oschina.net/u/2308182/blog/659217

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_754197.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

delphi RAD Studio新版本及路线图 及官方网站 官方 版本发布时间

delphi RAD Studio Berlin 10.1 主要是FireMonkey 移动开发的改动&#xff0c;VCL确实没有多大变化。 http://docwiki.embarcadero.com/RADStudio/Berlin/en/Main_Page http://docwiki.embarcadero.com/RADStudio/Berlin/en/Whats_New EMB 官网地址资源 Bug fix list for RAD …

网站调查方法步骤.

1.查看对方网站pr值2.查看对方在搜索引擎快照的新鲜度3.到http://whois.domaintolls.com查看对方域名注册信息4.到http://www.archive.org查看对方的收录历史5.查看对方在搜索引擎的收录数6.查看对方的外部链接数7.查看对方是否被雅虎目录&#xff0c;开放目录dmoz.org,好123收…

大型网站架构演变

初级篇&#xff1a;&#xff08;单机模式&#xff09;假设配置&#xff1a;&#xff08;Dual core 2.0GHz,4GB ram,SSD&#xff09;基础框架&#xff1a;apache(PHP) Mysql / IIS MSSQL&#xff08;最基础框架&#xff0c;处理一般访问请求&#xff09;进阶1&#xff1a;替换…

在线流程图与图表制作网站

现在很多功能网站&#xff0c;最常见的就是图片处理类&#xff0c;不如切图&#xff0c;图片转换&#xff0c;添加效果等。本文收集了国外最常用的流程图与图表制作网站&#xff0c;这些网站功能强大&#xff0c;如果你正好需要制作图表或流程图&#xff0c;而对于软件又不熟悉…

linux条件编译预编译,C语言条件编译_Linux编程_Linux公社-Linux系统门户网站

C语言中的预编译包含三种&#xff1a;1.宏定义2.文件包含3.条件编译&#xff0c;条件编译指的是满足一定条件下才进行编译&#xff0c;它有几种形式&#xff1a;(1)#ifdef标识符//程序#else//程序#endif它的意义为如果定义了标识符&#xff0c;则执行程序段1&#xff0c;否则执…

inputstream怎么写给前端_写给大家看的网站制作教程01了解网站制作流程

作者 | 杨小二来源 | web前端开发(ID&#xff1a;webqdkf)前言这些年里&#xff0c;被读者和周围朋友以及一些认识的人&#xff0c;问的最多的问题&#xff0c;就是&#xff0c;怎么做一个自己的网站&#xff1f;这个难不难学呀&#xff1f;其实&#xff0c;我知道&#xff0c;…

Web层框架对网站中所有异常的统一处理

一个网站的异常信息作为专业的人士&#xff0c;是不会轻易暴露给用户的&#xff0c;因为那样狠不安全&#xff0c;显得你漏是一回事&#xff0c;只要还是考虑到网站的数据安全问题&#xff0c;下面给大家分享一下一些常见的web层框架是如何处理统一的异常。 之前都是在Struts2…

修改网站自动关闭时间timeout_centos7修改网卡名称为ethX

测试平台VMWARE WORKSTATION 15 虚拟机系统Centos7centos7网卡的随机名给自动化运维带来混乱&#xff0c;那么我们把网卡名重新配置为ethX一、在安装系统的时候配置&#xff1a;修改内核选项&#xff1a;net.ifnames0 biosdevname0二、已安装系统修改方法像我的虚拟机&#xff…

旧版ios软件网站_ios旧版软件抓包

大家好&#xff0c;这里是小虾虾科技屋——————————————————————有时候&#xff0c;某个软件随着更新&#xff0c;会带走许多历史的痕迹&#xff0c;于是有的人就想尝试复原那些软件&#xff0c;所以产生了今天为大家分享的工具。iTunes旧版软件抓包神器&a…

seo按天扣费系统源码_企业SEO外包,这样选靠谱!

原标题&#xff1a;企业SEO外包&#xff0c;这样选靠谱&#xff01;一般在选择企业SEO外包的时候&#xff0c;需要注意什么点?一、清晰企业网站SEO优化定位清晰企业网站SEO优化定位对于企业的的目标定位&#xff0c;大家说法不一&#xff0c;但是总体上作为企业的负责任你需要…

突发!32TB Windows 10核心数据泄漏,被人上传至第三方公开网站

本文讲的是突发&#xff01;32TB Windows 10核心数据泄漏&#xff0c;被人上传至第三方公开网站&#xff0c;据外媒The Register报道&#xff0c;微软Windows操作系统内部大量组件和核心代码泄漏&#xff0c;正在网络上传播。 这些泄漏的数据多达32TB&#xff0c;包括微软未公开…

Python Django搭建网站流程图解

更多编程教程请到&#xff1a;菜鸟教程 https://www.piaodoo.com/ 友情链接&#xff1a; 高州阳光论坛https://www.hnthzk.com/人人影视http://www.sfkyty.com/1. 创建Django REST framework工程 1.1手动创建工程文件夹 1.2进去工程文件夹内&#xff0c;执行命令&#xff1…

前台页面当前时间_wordpress网站开发中,怎样不同页面调用不同的标题?2招帮你搞定...

一个wordpress网站&#xff0c;它的前台页面是千变万化的&#xff0c;不同的页面肯定有不同的内容和标题。如果一个wordpress网站&#xff0c;所有的页面都是同一个标题&#xff0c;那对于搜索引擎来说&#xff0c;是非常不友好的。那么&#xff0c;在wordpress网站主题模板开发…

xml能存图片吗_robots文件只能放在网站根目录吗?

要使得网站能被百度收录特定页面&#xff0c;robots文件发挥着重要作用&#xff0c;甚至一定层面上影响着网站优化和SEO策略。那么robots文件是不是一定要放在网站的根目录下面呢&#xff1f;【Robots文件的作用】一般搜索引擎蜘蛛会优先访问网站内部的robots文件&#xff0c;根…

Windows 服务器配置、运行、图文流程(新手必备!) - IIS建站配置一条龙

Window 2008 服务器的配置教程本文提供全流程&#xff0c;中文翻译。 Chinar 坚持将简单的生活方式&#xff0c;带给世人&#xff01;&#xff08;拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例&#xff09; Chinar —— 心分享、心创新&#xff01;助力快…

百度搜索结果 转换_百度继续调整搜索结果页面 恢复原本被隐藏的网站地址

来源&#xff1a;蓝点网网址是用户分辨是否是百家号内容的关键参考因素&#xff0c;因此百度这次调整也继续被用户炮轰认为百度居心不良。现在百度再次调整搜索结果页将网站的网址恢复显示&#xff0c;如果本身已关联百度百家或者熊账号则显示媒体名称。部分关键词搜索结果如下…

简单的物流管理网站制作源码_这个网站可以免费DIY专属的圣诞老人问候视频,效果不错制作简单!...

圣诞节快到了&#xff0c;过节气氛越来越浓。。。圣诞节是孩子们最喜爱的节日之一&#xff0c;除了收到圣诞老人送的礼物&#xff0c;如果还能收到来自圣诞老人的专属祝福视频也会是一件能让孩子们非常开心的事情&#xff01;今天给大家推荐的这个网站&#xff0c;可以在家免费…

e3d教程做logo教程_企业官网网站SEO优化怎么做-技巧教程

企业网站推广是中小企业都面临的难题。百度竞价成本太大&#xff0c;做SEO优化又难上排名。企业网站SEO优化教程&#xff0c;搜索引擎优化核心在于目标关键词&#xff0c;目标关键词站外因素是外链即锚文本建设&#xff0c;SEO优化关键词排名的着陆页通常是网站首页。利用首页做…

c++builder 运行网站的api_TensorFlow2.x目标检测API安装配置步骤详细教程

TensorFlow Object Detection API支持TensorFlow2.x版本已经有一段时间了&#xff0c;这里对安装配置步骤做详细说明。安装步骤也可以参考如下两个链接&#xff1a;https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/tf2.mdhttps://tensorflo…