TheBeerHouse网站项目学习笔记(4)----安全管理(下)

TheBeerHouse网站项目学习笔记(4)----安全管理(下)

摘要: 安全管理是网站设计不可回避的问题,也是网站设计的重用组成部分.这些组成部分都需要对不 同的用户进行识别,检查用户是否有权限对那些受限制的网页进行访问,这种方法称为认证 (authentication).决定用户可以对哪些内容进行访问,这种方法称为授权(authorization).这两个概念容 易弄混淆,那么可以这么来理解: 认证---你是谁?  授权---我已经知道你是谁,你可以做什么?认证和授 权是网站成员权限管理的一部分,包括创建新用户,用户证书管理(包括密码保护机制,例如为遗忘密码的用 户进行密码恢复)以及与账户关联的角色管理.通过MS为我们提供的内置权限管理,我们可以快速建立整套 网站的权限管理系统.上篇主要讨论"你是谁",下篇主要讨论"我已经知道你是谁,你可以做什么"

那么此下篇主要从以下三个个方面讨论权限问题,其实这些问题都是一些现象,通过这些现象查看后面 的本质:

1. 不同角色的用户可以看到不同的菜单项目

2. 各个页面都有自己可以被访问的角色设置

3. 某个权限和另一个权限的角色之间的界限 / 不同的角色用户对同一个页面具有的操作项目不同

其实上面的三个部分都是对你可以干什么进行讨论.

一. 不同角色的用户可以看到不同的菜单项目

讨论这个现象假定我们已经熟悉如下知识点:导航控件Menu的使用,网站地图的格式以及两者之间的关 系

这个现象就是匿名用户或非管理员一般用户登录后,只能看到如下菜单:

TheBeerHouse网站项目学习笔记(4)----安全管理(下)

而如果以超级用户Admin登录,发现多了一项后台管理的菜单:

TheBeerHouse网站项目学习笔记(4)----安全管理(下)

TheBeerHouse网站项目学习笔记(4)----安全管理(下)

上述功能其实就只需两处设置,当然也离不开内置权限管理的知识:

1. 网站地图部分代码:

Web.sitemap

1<?xml version="1.0" encoding="utf-8" ?>
 2<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" enableLocalization ="true" >
 3  <siteMapNode title="Home" url="~/Default.aspx">
 4    
 5    <siteMapNode title="Articles" url="~/ShowCategories.aspx">
 6      <siteMapNode title="Browse" url="~/BrowseArticles.aspx" />
 7    </siteMapNode>
 8
 9    <siteMapNode title="Admin" url="~/Admin/Default.aspx" roles="Administrators">
10      <siteMapNode title="Manage Users" url="~/Admin/ManageUsers.aspx" >
11        <siteMapNode title="Edit User" url="~/Admin/EditUser.aspx" />
12      </siteMapNode>
13    </siteMapNode>
14    
15  </siteMapNode>
16</siteMap>

如上图9-13行代码. title="Admin" 用于显示菜单的文字,url="~/Admin/Default.aspx" 指向该菜单 的超链接的相对地址,此时已经进入了后台管理的目录Admin目录了.roles="Administrators"是控制角色 访问的关键,即该菜单选项只能由角色Administrator访问,又如上面的菜单Articles节点说明(第5行)中就 没有Roles的说明,表明此页所有人都可以访问,实践证明,Articles菜单匿名,非匿名,管理员等角色都可以 点击访问的. 上面代码中的10行,11行的作用是在"面包屑"导航菜单中显示导航名和链接的地址,如下 图:

TheBeerHouse网站项目学习笔记(4)----安全管理(下)

有了上述知识点后,我们再做一个设置就搞定了,去Web.config的<system.web>配置节里看 看:

<system.web>
  .........
  <siteMap defaultProvider="TBH_SiteMapProvider" enabled="true">
   <providers>
      <add name="TBH_SiteMapProvider" type="System.Web.XmlSiteMapProvider"
          securityTrimmingEnabled="true" siteMapFile="web.sitemap"/>
    </providers>
   </siteMap>
  
  ...........
  
</system.web>

securityTrimmingEnabled 获取一个布尔值,该值指示站点地图提供程序是否根据用户的角色筛选站 点地图节点。详细说明请见MS的说明.

那么通过上面两步设置,第一个现象--不同角色的用户可以看到不同的菜单项目 就分析完了.

在此有一个题外话的思考:记得 ASP.NET 1.x 下做上述功能时,是非常麻烦的,需要建立菜单选项的表, 还要和权限表关联等,还得用比较复杂的API来完成,但到了现在我们几乎没有编写任何代码,MS都为我们集 成好了,那么对于一个开发人员来说,这是好还是坏呢? 我本人觉得坏处当然是有的,那就是生疏了以前比 较熟练的API语法,好处是节约了开发时间,我们就可以把主要精力放在网站的结构类图或总体架构的思考 上,从总体上分析此网站的时间就可以更多些,这也就是目前有架构师这个职业的一个缘由吧.    

二. 各个页面都有自己可以被访问的角色设置

先看一个代码片段:

Web.Config

<system.web>
      <authorization>
         <allow roles="Administrators,Editors" />
         <deny users="*" />
      </authorization>
   </system.web>
   <location path="Default.aspx">
      <system.web>
         <authorization>
            <allow 

roles="Administrators,Editors,Contributors,Moderators,StoreKeepers" />
            <deny users="*" />
         </authorization>
      </system.web>
   </location>
   <location path="AddEditProduct.aspx">
      <system.web>
         <authorization>
            <allow roles="Administrators,StoreKeepers" />
            <deny users="*" />
         </authorization>
      </system.web>
   </location>

此代码截取自Admin目录,即管理员目录下的配置文件Web.Config前几行, authorization 配置节表明 本目录中的所有网页拒绝任何匿名访问,允许具有Administrators 和 Editors 角色的登录用户访问,这个 设定相当于对整个目录的全局设定. 但如果有部分网页需要局部修改这个设定,那么就用自己的配置节来 解决,如是上面的一个个 <location...> 配置节,就是对各个需要局部修改访问权限的网页进行设 定,但他们应该有一个共同的前提,那就是拒绝所有匿名用户:

<deny users="*" />.如此一来,该目录中所有网页在访问时都会检查是否具有角色权限再呈现 出来.

三. 某个权限和另一个权限的角色之间的界限 / 不同的角色用户对同一个页面具有的操作项目不同

之所以把两个论点放在一起讲就是因为,角色之间的界限直接导致用户的操作权限的不同

先来看一个现象 :

TheBeerHouse网站项目学习笔记(4)----安全管理(下)

匿名方式打开网站,并点击Articles菜单后再点击Photo Gallary分类,发现此分类下的文章右方都有钥 匙标志,表明此文章需要一定权限才能看到,那么我们用已注册的一个普通用户Roger1进入系统后,此标志 消失,表明此文章可以浏览了,但当我们注销后,并再次用Admin管理员身份进入,由于此时权限比较大了,那 么这些文章都可以编辑了,文章右方又出现了如下所示的标志了:          

TheBeerHouse网站项目学习笔记(4)----安全管理(下)

那么此时用户的权限发生了平滑的转移.

下面简要分析一下,BrowseArticles.aspx页面用来显示文章的控件是调用的一个用户控件,名为 ArticleListing.ascx,那么我们打开此页面的前台部分,这里可以看到在一个GridView控件中加入了一个 模板列,此模板中画入了如上图格式的一个表格,那么我们找关于钥匙的图片部分代码,请看如下部分:

      <asp:Image runat="server" ID="imgKey" ImageUrl="~/Images/key.gif" 

AlternateText="Requires login"
         Visible='<%# (bool)Eval("OnlyForMembers") && !

Page.User.Identity.IsAuthenticated %>' />

其是否可见的属性直接由OnlyForMembers(只对成员可见字段)和 Page.User.Identity.IsAuthenticated(是否登录) 决定

那么当用户由普通用户迁移到管理员后,编辑和删除按钮出现的原理是个比较有用的技巧,见如下分 析:

首先 ArticleListing.ascx 前台的模板列的表格中放入了一个 Panel 控件,此面板中放入了一些管理 员需要操作的一些按钮图标--编辑和删除:

<asp:Panel runat="server" ID="panEditArticle" Visible='<%# UserCanEdit %>'>
<asp:ImageButton runat="server" ID="btnApprove" ImageUrl="~/Images/Ok.gif"
CommandName="Approve" CommandArgument='<%# Eval("ID") %>' AlternateText="Approve article"
Visible='<%# !(bool)Eval("Approved") %>'
OnClientClick="if (confirm('Are you sure you want to approve this article?') == false) return false;" />
&nbsp;&nbsp;
<asp:HyperLink runat="server" ID="lnkEdit" ToolTip="Edit article"
NavigateUrl='<%# "~/Admin/AddEditArticle.aspx?ID=" + Eval("ID") % >' ImageUrl="~/Images/Edit.gif" />
&nbsp;&nbsp;
<asp:ImageButton runat="server" ID="btnDelete" ImageUrl="~/Images/Delete.gif"
CommandName="Delete" AlternateText="Delete article"
OnClientClick="if (confirm('Are you sure you want to delete this article?') == false) return false;" />
</asp:Panel>

请注意上述代码的蓝色部分,此面板是否可见直接受控于后台的一个属性-- UserCanEdit 在 ArticleListing.ascx.cs 这个后台类中定义了这个属性---UserCanEdit :

private bool _userCanEdit = false;
protected bool UserCanEdit
{
get { return _userCanEdit; }
set { _userCanEdit = value; }
}

这个属性在此类中是自定义的,并不是来自某个表中某个字段,那么下面自然就该探讨一些这个属性是 怎么控制,怎么被赋值的,下面仍然看ArticleListing.ascx.cs这个后台代码的一个事件:

protected void Page_Init(object sender, EventArgs e)
        {
            //调用 Page 上的 RegisterRequiresControlState 方法,以指示自定义控件使用控件状态

。
            this.Page.RegisterRequiresControlState(this);
            this.UserCanEdit = (this.Page.User.Identity.IsAuthenticated &&
               (this.Page.User.IsInRole("Administrators") || 

this.Page.User.IsInRole("Editors")));
            try
            {
                if (this.Page.User.Identity.IsAuthenticated)
                {
                    _userCountry = this.Profile.Address.Country.ToLower();
                    _userState = this.Profile.Address.State.ToLower();
                    _userCity = this.Profile.Address.City.ToLower();
                }
            }
            catch (Exception) { }
        }

那么黄色高亮部分代码就是在页面最终呈现出来之前做了这个属性的赋值操作,很明显,这个属性受两 个因素的影响:1. 是否登录-- IsAuthenticated

2. 角色控制 -- Page.User.IsInRole(".....") .

所以,界面上编辑,删除按钮是否出现,而且根据权限的不同是否出现就圆满解决了.这就是为什么由 Roger1这个用户迁移到Administrator后,该编辑,删除按钮就出现的原因,那是因为虽然两者都 IsAuthenticated ,但Roger1的角色不是Administrators,也不是Editors,他就当然看不到这些按钮 了.

到此,我们分两篇文章讨论了这个网站的验证和授权的问题,其实这些问题遍布很多网页,不过其处理的 过程都是一样的.

其实,通过上面三篇对 TheBeerHouse 网站的介绍文章来看,我们基本都是在讨论一些设计问题,那么对 于网站的架构和类图分析以及整体后台逻辑流程的分析我们会在后续文章中讨论,可以这么说,下面我们将 踏入对这个网站分析的深水区,也是核心的API代码部分了.