解开EAS权限与角色之迷

2007年11月29日 星期四 下午 02:23

前些时间做了个EAS的项目,里面用到了很多高深的东西,如:面象服务的开发,框架等,最近看了下其中的权限,发现这种权限其实我也用过的,不过EAS里面用得更好,体现得更加的完美,以下对这一块作出分析.

在项目中,访问某一个页面的时候是有权限验证的,当然权限肯定是开发完成后固定的,不然的话肯定是无法控制的,而角色是可变的,在项目中通过角色对应不同的权限,而用户属于某一个角色,这样来控制登录系统的每一个用户的访问权限,并且,当须要特定的权限集合时,可以增加一个角色,把相应的用户归属到这个角色就完成了,原理就是这样.

其中有几个对象要注意一下:用户,角色,权限;用户和角色关系,角色和权限关系;以下分别说明:

用户属性:

Oid 主键

UserName 用户名

DisplayName 显示名

Password 密码

IsValid 是否有效

其它不相关属性就不列举了,

角色属性;

Oid 主键.

RoleName 角色名称

权限属性:

Oid 主键

Code 权限代码

PermissionName 权限名称

Description 描述

用户和角色关系:

Oid 主键

RoleOid 角色ID

UserOid 用户ID

角色和权限关系:

Oid 主键

RoleOid 角色ID

PermissionOid 权限ID

几者之间的关系就是这样,最先完善的是权限表,把项目各个模块要用到的权限写成类,每一个权限可写成常量,这样方便使用,如:

public class HRMPermissions
    {
        public const string LandingHRM = "EAS.HRM.Landing";

        public const string ViewEmployee = "EAS.HRM.ViewEmployee";
        public const string CreateEmployee = "EAS.HRM.ViewEmployee.Create";
        public const string UpdateEmployee = "EAS.HRM.ViewEmployee.Update";
        public const string DeleteEmployee = "EAS.HRM.ViewEmployee.Delete";

}

完成之后,再到权限表里添加相应的权限,可以直接写SQL,这里要注意.要把权限代码写进数据库,其实这样只是为了表示方便而已,没什么特殊的意义,

这时,当添加一个角色,就要做几件事,

1)、在角色表添加一条数据,

2)、为角色分配下属用户(如已存在用户),逻辑中在用户和角色表中添加数据,当然用户可同时属于多个角色;

3)、为角色分配权限,逻辑操作角色和权限表,存入角色ID和权限ID,完事。

这样,在页面中,通过一个用户的信息,可以取出它所属的角色,通过这个角色,进一步获取它对应的权限,这样就可以判断当前用户能否访问这样页面了,

但是,传统的做法是把用户的信息存在一个Session里面,在判断用户的时候,是先把这个Session转为一个自定义的对象,再去验证这个用户的信息,如:用户没登录就转到登录页,登录后再转回来,这样的话就要在每个页面中对Session进行操作,实在是有些不方便,在EAS项目中解决了这个问题,方法如下:

一、解决起始页问题:大意就是没有登录的用户是不能打开除登录页之外的页面的,登录之后,再转到这个页面去,做法:在配置文件中加两个配置节点:

1)、<authentication mode="Forms">
      <forms loginUrl="~/NewFolder1/Default.aspx" protection="All" defaultUrl="~/NewFolder2/MemberPages.aspx" timeout="30"></forms>
    </authentication>

这里是Login的地址、保护内容、默认页,模式为Forms模式,loginUrl是默认的登录页,在没登录之前,试图打开页面时,都会转到这里来,protection是保护内容,这里一般设为All,defaultUrl一般设为系统的主页,

2)、<!-- 授权信息-->
    <authorization>
      <!-- 设置需要进行授权的用户为所有用户 -->
            <!--<allow users="?"/>-->
      <deny users="?"/>
    </authorization>

这里的allow 表示允许绕过登录验证的用户,?表示只要是非匿名的都可以,*表示全部用户,deny 表示未经登录验证不能进入系统的用户,?表示匿名用户不能进,*表示所有用户都不能进

关于这两个节点的详细使用,我也是个菜鸟,只知其中皮毛,有请高手指点!!谢谢!!

写完之后,可以试一下,当打开每一个页面时,都会自动转到loginUrl来,并且你可以看到URL上还有一个参数returnUrl,它表示了你当前打开的页面;这时候,要想通过什么方法来登录进入下一个页面呢?

这里就要用到页面User这个东西了,很多人可能都注意到了,在每一个aspx的页面里,都有一个this.User,但是它是只读的,里面有几个方法,详细我也不会~~怎么能给它付值呢,直接付是不可能的了,研究了下EAS,发现过程是这样的:

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket("userName", true, 100000);

这是一个窗体票据验证,userName可以换成用户的ID比较好,时间是这个验证的有效时间,

string encrytTicket = FormsAuthentication.Encrypt(ticket);
        HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encrytTicket);
        this.Response.Cookies.Add(authCookie);

这里加密这个票据并放到Cookies里面,但是不知道为什么,在另一个页面中是取不到这个Cookies的,

通过这样几行简单的代码,就可以发现User里有值了,Name就是userName,那么在页面上就可以不用Session而用this.User了,这里补充几行代码:

string url = string.Empty;
        url = this.Request.QueryString["returnUrl"];
        if (string.IsNullOrEmpty(url))
        {
            Response.Redirect(FormsAuthentication.DefaultUrl);//转到系统主页,配置文件中的defaultUrl
        }
        else
        {
            Response.Redirect(url);
        }

User.Identity.IsAuthenticated,表示用户的登录状态,BOOL型

到这里,页面上可以取到登录的用户了,也可以通过权限集合类的常量取到权限代码了,接下来就是怎么进行验证,这里EAS的架构师写了一个类(为了方便,只写接口):

bool HasPermission(IPrincipal user, string permissionCode)//传入this.User,权限代码

MyUser CurrentUser(IPrincipal user) //获取当前自定义用户

这样就可以通过HasPermission方法处理一堆的逻辑(略),来判断用户是否拥有这个权限了,

注意:这里的权限验证类最好是用单列模式,保证其全局性,

private readonly static Security instance = new Security();

public static Security Instance
        {
            get
            {
                return instance;
            }
        }

以上是我个人心得和体会,关于其中知识点的不足之处请指点,

posted @ 2008-02-01 10:54  point.deng  阅读(716)  评论(1编辑  收藏  举报