RyanDing

用编码抒写未来

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  41 随笔 :: 0 文章 :: 1243 评论 :: 52万 阅读

      本文是续上篇 使用MvcHandler设计自定义系统权限<上> 的下篇。通过本篇,我将在MVC2.0中提出一个系统权限的解决方案,如存在不足的地方,希望您能够指出。谢谢!

 

      一、回顾上篇中的内容:


       重点回顾一下上篇的3.2中的MyHandler类,该类继承MVC2.0的MvcHandler类。代码如下:

1
2
3
4
5
6
7
8
9
10
protected override System.IAsyncResult BeginProcessRequest(System.Web.HttpContext httpContext, System.AsyncCallback callback, object state)
          {
              if (1 == 1) //系统权限的入口
              {
                  //当条件满足时可以跳转到一个自定义的httphandler,比如(Error.aspx)等。
                  httpContext.Response.Redirect("http://www.cnblogs.com/ryanding");
                  return null;
              }
              return base.BeginProcessRequest(httpContext, callback, state);
          }

贴出以上代码,着重想讲解的就是我们的权限判断应该注入在第11行,这个if语句内。将权限注入在第11行,个人认为这个权限是建立在MVC整个框架外的。效率应该会更高,而且随着未来Asp.net MVC版本的升级换代。这种权限结构在一定程度上是不受MVC框架的制约的,总比继承AuthorizeAttribute特性来控制权限高明一些吧?否则那些“反reflection派”又开始出来用效率说事。

 

     二、切入正题,将权限功能注入系统


     先看以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
protected override System.IAsyncResult BeginProcessRequest(System.Web.HttpContext httpContext, System.AsyncCallback callback, object state)
       {
 
           //使用系统System.Security.Principal保存登录后的用户名
           //示例代码此处userName赋值不够严谨,请注意对象空引用
           string userName = httpContext.User.Identity.Name;
 
           if (string.Compare(userName, "admin", true) == 0)
           {
               //当条件满足时可以跳转到一个自定义的httphandler,比如(Error.aspx)等。
               httpContext.Response.Redirect("http://www.cnblogs.com/ryanding");
               return null;
           }
           return base.BeginProcessRequest(httpContext, callback, state);
       }

这里我们还是使用.NET经典的System.Security.Principal类库。从httpContext.User.Identity 获取到登录的用户名符串(从Name属性获取值)。在Login这个View内保存登录成功的用户信息,Login View 这个登录页面不需要对权限进行处理,everyone 都可以打开。后台代码如下:

1
2
FormsAuthenticationService auth = new FormsAuthenticationService();
auth.SignIn("admin", false);

假设admin就是当前用户,这里的admin硬编码了,应该从UI获取。

 

  三、具体的实现思路


     在MVC2.0中如果通过Action进行判断的话,难免要考虑到Area机制。因为在不同的Area中,可能会出现相同的Controller和Action。所以在权限判断时还需要将Area加入到逻辑中一起判断。这样就可以精确的控制所有的MVC的URL。比如我们通过 AreaName + ControllerName + ActionName 这样判断就可以对系统具体的URL进行唯一标识,同时也方便处理权限了。我们将BeginProcessRequest方法重新改造如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
protected override System.IAsyncResult BeginProcessRequest(System.Web.HttpContext httpContext, System.AsyncCallback callback, object state)
       {
 
           //使用系统System.Security.Principal保存登录后的用户名
           //示例代码此处userName赋值不够严谨,请注意对象空引用
           string userName = httpContext.User.Identity.Name;
 
           //"admin"
           string strAreaName = base.RequestContext.RouteData.DataTokens["area"] == null ?
                                 "" : base.RequestContext.RouteData.DataTokens["area"].ToString();
 
           //"TestMvc.Areas.admin.Controllers"
           string strNameSpaces = base.RequestContext.RouteData.DataTokens["namespaces"] == null ?
                                   "" : base.RequestContext.RouteData.DataTokens["namespaces"].ToString();
           //"index"
           string strAction = base.RequestContext.RouteData.Values["action"].ToString();
           //"home1"
           string strController = base.RequestContext.RouteData.Values["controller"].ToString();
 
           //TODO:将area + action + controller 参与到权限判断中来
           if (string.Compare(userName, "admin", true) == 0)
           {
               //当条件满足时可以跳转到一个自定义的httphandler,比如(Error.aspx)等。
               httpContext.Response.Redirect("http://www.cnblogs.com/ryanding");
               return null;
           }
 
           return base.BeginProcessRequest(httpContext, callback, state);
       }

从MVC RouteData 的 DataTokens得到area相关信息;Values得到action与controller相关信息,最后将获取的值再参与具体的权限判断。

  

   四、注意事项


    在整个调试的过程中,发现只有一个地方让我调试了半天:MyHandler不能控制area的内部的Action。后来查阅相关资料,原来是在AreaRegistration(MVC2.0新增Area后自动生成的类)中设置问题。贴出代码,供参考:

1
2
3
4
5
6
7
8
public override void RegisterArea(AreaRegistrationContext context)
    {
        context.Routes.Add(new Route("{area}/{controller}/{action}/{id}"
                           , new RouteValueDictionary(new { area = "admin", controller = "Home1", action = "Index", id = "" })
                           , new RouteValueDictionary(new { area = "admin" })
                           , new RouteValueDictionary(new {area = "admin",  Namespaces = "TestMvc.Areas.admin.Controllers" })
                           , new HelloWorldHandler()));
    }

新增的area结构如下:

 

至此,您可以在MVC2.0中加入权限机制了。我相信通过这种方式注入自定义的权限结构到MVC程序中,总比用HttpModule来的强一些,因为客户端请求CSS/JS时,不需要再过滤这类的URL。代码看起会更舒服点,判断也就更简单点。

 

希望本篇文章可以给您带来帮助,如有不足之处欢迎指出,谢谢!

posted on   ryanding  阅读(2579)  评论(12编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示