转贴---》代码阅读总结之ASP.NET StartKit TimeTracker(角色权限

来源:互联网 发布:centos搭建个人网站 编辑:程序博客网 时间:2024/06/10 07:22
最近开始看ASP.NET StartKit TimeTracker中代码,它是一个典型的项目追踪系统。
它比我前几天看的ASP.NET StartKit Commerce复杂了许多。
例如:在ASP.NET StartKit TimeTracker开始有明显的三层结构的设计。PL层,BLL层和DAL层。
同时开始在项目中引进了角色权限管理功能等等。

今天我们先讨论角色权限的实现问题。

让我们先看一角色权限设置的参考资料:
http://www.cnblogs.com/kwklover/archive/2004/06/29/19455.aspx

现在假如我们系统中有3 种角色:Service,Work,Manage

要是我们想在WebForm1.aspx禁止Service,Manage这2类角色的登陆用户访问,我们可以在Web.config文件中做下面设置:

<location path="WebForm1.aspx">
        <system.web>
            <authorization>
             <deny roles="Service,Manage" />
  <deny users="?" />
            </authorization>
        </system.web>
</location>

还有一种方式就是:建立三个文件夹,某一角色的人只能访问某一文件夹里的ASPX.NET文件


假如我有用户a,他有Service,Work这2种角色,假如有页面abc.aspx,它允许Work,Manage这2种角色的用户访问。
个人感觉这样设置的灵活性不好,有没有通过代码控制的方法呢?
我编写了如下代码:实现单用户可以多角色,单页面多角色访问。

 

让我们先看Global.asax.cs中代码,请注意看事件Application_AuthenticateRequest中的代码实现。

using System;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using System.Threading;
using System.Globalization;
using System.Configuration;

namespace BluepieCustomerService 
{
    
/// <summary>
    
/// Global 的摘要说明。
    
/// </summary>

    public class Global : System.Web.HttpApplication
    
{
        
/// <summary>
        
/// 必需的设计器变量。
        
/// </summary>

        private System.ComponentModel.IContainer components = null;
        
        
/// <summary>
        
/// 本系统自定义的角色之一“服务人员”
        
/// </summary>

        public const string ConstUserRoleNameService="Service";

        
/// <summary>
        
/// 本系统自定义的角色之一“普通工作人员”
        
/// </summary>

        public const string ConstUserRoleNameWork="Work";

        
/// <summary>
        
/// 本系统自定义的角色之一“管理人员”
        
/// </summary>

        public const string ConstUserRoleNameManage="Manage";
        
        
/// <summary>
        
/// 逗号字符串
        
/// </summary>

        public const string ConstStringComma=",";

        
/// <summary>
        
/// 百分号字符串
        
/// </summary>

        public const string ConstStringPercent="%";

        
/// <summary>
        
/// char 类型逗号
        
/// </summary>

        public const char ConstCharComma=',';

        
/// <summary>
        
/// char 类型百分号
        
/// </summary>

        public const char ConstCharPercent='%';

        
/// <summary>
        
/// 发生权限访问错误时,转向的错误提示页面
        
/// </summary>

        public const string ConstRoleErrorPageName="RoleError.aspx?Index=-1";
        
        
/// <summary>
        
/// DB的连接字符串
        
/// </summary>

        public const string  ConstWebConfigFileKeyName_ConnectionString="ConnectionString";
                
        
public Global()
        
{
            InitializeComponent();
        }
    
        
        
protected void Application_Start(Object sender, EventArgs e)
        
{
                        
        }

 
        
protected void Session_Start(Object sender, EventArgs e)
        
{
            
        }


        
protected void Application_BeginRequest(Object sender, EventArgs e)
        
{

        }


        
protected void Application_EndRequest(Object sender, EventArgs e)
        
{

        }


        
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
        
{
            
if (HttpContext.Current.User!=null)
            
{    
                
//用户已经通过验证
                if (Request.IsAuthenticated ) 
                
{
                    
//得到用户的角色Cookie的名称
                    string userRolesCookieName=FormsAuthentication.FormsCookieName;
                    
//得到用户的角色Cookie
                    string currentCookieValue=Context.Request.Cookies[userRolesCookieName].Value;
                    
//解密
                    FormsAuthenticationTicket currentFormsAuthenticationTicket = FormsAuthentication.Decrypt(currentCookieValue);

                    
//得到cookie中的用户数据
                    string[] userData = BCSTool.StringToArray(currentFormsAuthenticationTicket.UserData,ConstCharPercent);
                    
                    
//取得用户的个人详细信息数组                
                    int userId=Convert.ToInt32( userData[0]);
                    
string userDisPlayName=userData[1];
                    
string userName=userData[2];
                    
string userEmail=userData[3];
                    
                    
//按当初加入的规则分解为数组
                    string [] roleArray= BCSTool.StringToArray(userData[4],ConstCharComma );

                    
//设置当前 HTTP 安全信息
                    Context.User = new BCSLoginPrincipal(userId,
                                                        userDisPlayName,
                                                        userName,
                                                        userEmail,
                                                        roleArray,
                                                        HttpContext.Current.User.Identity);
                }

            }

        }


        
protected void Application_Error(Object sender, EventArgs e)
        
{

        }


        
protected void Session_End(Object sender, EventArgs e)
        
{

        }


        
protected void Application_End(Object sender, EventArgs e)
        
{

        }

            
        
Web 窗体设计器生成的代码
    }

}



让我们再看类BCSLoginPrincipal
实现了接口:IPrincipal,该接口定义用户对象的基本功能。
该接口有一个属性IIdentity Identity {get;},获取当前用户的标识。
一个方法bool IsInRole(string role),确定当前用户是否属于指定的角色。
using System;
using System.Security.Principal;

namespace BluepieCustomerService
{
    
/// <summary>
    
/// BCSLoginPrincipal 的摘要说明。
    
/// </summary>

    public class BCSLoginPrincipal :System.Security.Principal.IPrincipal 
    
{
        
private string[] _userRole;
        
        
protected IIdentity _iIdentity;

        
int _userId;
        
string    _userDisPlayName;
        
string  _userName;
        
string  _userEmail;
        
        
/// <summary>
        
/// 类BCSLoginPrincipal的有参构造器
        
/// </summary>
        
/// <param name="iIdentity"></param>
        
/// <param name="userRole"></param>

        public BCSLoginPrincipal(int userId,string userDisPlayName,string userName,string userEmail    , string[] userRole,IIdentity iIdentity)
        
{
            
this._userId=userId;
            
this._userDisPlayName=userDisPlayName;
            
this._userName=userName;
            
this._userEmail=userEmail;
            
this._userRole=userRole;
            
this._iIdentity=iIdentity;
        }


        
/// <summary>
        
/// 取得和设置登陆用户的UserID
        
/// </summary>

        public int UserId
        
{
            
get
            
{
                
return _userId;
            }

            
set
            
{
                _userId
=value;
            }

        }


        
/// <summary>
        
/// 取得和设置登陆用户的登陆帐号
        
/// </summary>

        public string UserDisPlayName
        
{
            
get
            
{
                
return _userDisPlayName;
            }

            
set
            
{
                _userDisPlayName
=value;
            }

        }


        
/// <summary>
        
/// 取得和设置登陆用户的真实姓名
        
/// </summary>

        public string UserName
        
{
            
get
            
{
                
return _userName;
            }

            
set
            
{
                _userName
=value;
            }

        }


        
/// <summary>
        
/// 取得和设置登陆用户的Email
        
/// </summary>

        public string UserEmail
        
{
            
get
            
{
                
return _userEmail;
            }

            
set
            
{
                _userEmail
=value;
            }

        }


        
        
/// <summary>
        
/// 取得和设置登陆用户的角色数组
        
/// </summary>

        public string[] UserRole
        
{
            
get 
            
{
                
return _userRole;
            }

            
set 
            
{
                _userRole 
= value; 
            }

        }


        
public IIdentity Identity
        
{
            
get    
            
{
                
return _iIdentity;
            }

            
set    
            
{
                _iIdentity 
= value; 
            }

        }


        
/// <summary>
        
/// 实现接口方法,判断用户的角色是否合法
        
/// </summary>
        
/// <param name="role"></param>
        
/// <returns></returns>

        public bool IsInRole(string role)
        
{
            
//用户传过来的角色字符串有可能包含多个角色,所以我们得先分解为数组
            string [] roleArray = BCSTool.StringToArray(role,Global.ConstCharComma);
            
//取得数组长度
            int roleArrayLength=roleArray.Length;

            
//取出数组中每一个角色与用户的现有角色做比较
            for(int i=0;i<roleArrayLength;i++)
            
{
                
if( isRole( roleArray[i] ) )
                
{
                    
return true;
                }

            }

            
return false;
        }


        
/// <summary>
        
/// 与用户的现有角色做比较
        
/// </summary>
        
/// <param name="str"></param>
        
/// <returns></returns>

        bool isRole(string str)
        
{
            
int arrayLength=_userRole.Length;

            
for(int i=0;i<arrayLength;i++)
            
{
                
if ( _userRole[i]==str )
                
{
                    
return true;
                }

            }

            
return false;
        }


    }

}


工具类,定义了一些常用方法
using System;
using System.Data;
using System.Data.SqlClient;

namespace BluepieCustomerService
{
    
/// <summary>
    
/// 工具类,定义了一些常用方法
    
/// </summary>

    public class BCSTool
    
{
        
        
/// <summary>
        
/// 根据节点名得到WebConfig文件的节点数值
        
/// </summary>
        
/// <param name="keyName"></param>
        
/// <returns></returns>

        public static string GetWebConfigFileKeyValue(string keyName)
        
{
            
return System.Configuration.ConfigurationSettings.AppSettings[keyName];
        }



        
/// <summary>
        
/// 分解字符串为字符串数组,分解字符为参数froamt传入
        
/// </summary>
        
/// <param name="str"></param>
        
/// <returns></returns>

        public static string[] StringToArray(string str,char froamt)
        
{
            
string[] strs=str.Split(new char[]{froamt});
            
return strs;
        }


        
/// <summary>
        
/// 合并字符从字符数组中,合并的格式:每个字符之间用逗号间隔
        
/// </summary>
        
/// <param name="str"></param>
        
/// <returns></returns>

        public static string ArrayToString(string[] stringArray,string format)
        
{
            System.Text.StringBuilder sb
=new System.Text.StringBuilder("");

            
for (int i=0;i<stringArray.Length;i++)
            
{
                sb.Append(stringArray[i]).Append(
",");
            }


            
//去掉字符尾的","
            sb.Remove(sb.Length-1,1);

            
return sb.ToString();
        }


    }

}


登陆用户详细信息类,定义了登陆用户的用户的UserId,用户的真实名称等等
using System;
using System.Collections;

namespace BluepieCustomerService
{
    
/// <summary>
    
/// 用户的属性类
    
/// </summary>

    public class BCSUserDetail
    
{
        
int _userId;
        
string    _userDisPlayName;
        
string  _userName;
        
string  _userEmail;
        
string[] _roleName;
        
        
/// <summary>
        
/// 类BCSUserDetail的构造器
        
/// </summary>
        
/// <param name="userId"></param>
        
/// <param name="userDisPlayName"></param>
        
/// <param name="userName"></param>
        
/// <param name="userEmail"></param>
        
/// <param name="roleName"></param>

        public BCSUserDetail(int userId, string userDisPlayName,string  userName,string  userEmail,string[] roleName)
        
{
            
this._userId=userId;
            
this._userDisPlayName=userDisPlayName;
            
this._userName=userName;
            
this._userEmail=userEmail;
            
this._roleName=roleName;
        }


        
/// <summary>
        
/// 用户的UserId
        
/// </summary>

        public int UserId
        
{
            
get
            
{
                
return _userId;
            }

            
set
            
{
                _userId
=value;
            }

        }


        
/// <summary>
        
/// 登陆用户的昵称,即用户登陆名
        
/// </summary>

        public string UserDisPlayName
        
{
            
get
            
{
                
return _userDisPlayName;
            }

            
set 
            
{
                _userDisPlayName
=value;
            }

        }


        
/// <summary>
        
/// 登陆用户的真实名称
        
/// </summary>

        public string UserName
        
{
            
get
            
{
                
return _userName;
            }

            
set 
            
{
                _userName
=value;
            }

        }


        
/// <summary>
        
/// 登陆用户的Email
        
/// </summary>

        public string UserEmail
        
{
            
get
            
{
                
return _userEmail;
            }

            
set 
            
{
                _userEmail
=value;
            }

        }


        
/// <summary>
        
/// 登陆用户的角色名数组,一个用户可能有多个角色
        
/// </summary>

        public string[] RoleName
        
{
            
get
            
{
                
return _roleName;
            }

            
set 
            
{
                _roleName
=value;
            }

        }



    }

}


最后在登陆事件中,我们进行如下处理:
/// <summary>
        
/// 用户登陆
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void LoginImageButton_Click(object sender, System.Web.UI.ImageClickEventArgs e)
        
{
            
//加密登陆密码
            string encryptPassWord=BluepieCustomerService.BCSSecurity.Encrypt(this.UserPassWordTextBox.Text);
            
string loginUserName=this.UserNameTextBox.Text;

            BCSUser currentLoginUser
=new BCSUser();
            BCSUserDetail currentLoginUserDetail
=null;

            currentLoginUserDetail
=currentLoginUser.Login (loginUserName ,encryptPassWord);

            
if ( currentLoginUserDetail!=null )
            
{
                
//组成用户数据
                
//格式为:UserId%UserDisPlayName%UserName%UserEmail%用户的角色字符串(要是用户的角色为多个,它们之间用逗号分隔)
                
//字符的前半段为用户的个人基本信息,后半段为用户的角色信息
                System.Text.StringBuilder sb=new System.Text.StringBuilder("");
                sb.Append(currentLoginUserDetail.UserId.ToString()).Append(Global.ConstStringPercent );
                sb.Append(currentLoginUserDetail.UserDisPlayName).Append(Global.ConstStringPercent );
                sb.Append(currentLoginUserDetail.UserName).Append(Global.ConstStringPercent );
                sb.Append(currentLoginUserDetail.UserEmail).Append(Global.ConstStringPercent );
                sb.Append(BCSTool.ArrayToString(currentLoginUserDetail.RoleName,Global.ConstStringComma));
                
                
//取得用户数据
                string userData=sb.ToString();

                FormsAuthenticationTicket currentLoginFormsAuthenticationTicket
=new FormsAuthenticationTicket(
                                                                                        
1,                           //版本
                                                                                        loginUserName,              //用户名
                                                                                        DateTime.Now,               //Cookie 的发出时间
                                                                                        DateTime.Now.AddHours(1),  //Cookie 的到期日期,这里设置为1个钟
                                                                                        false,                     //Cookie 是持久的,为 true;否则为 false
                                                                                        userData                   //存储在 Cookie 中的用户定义数据,这里存放的是用户的角色字符串
                                                                                                                    );  
                
//得到加密的票据
                string encrypCurrentLoginFormsAuthenticationTicket=FormsAuthentication.Encrypt(currentLoginFormsAuthenticationTicket);

                
//设置Cookie
                HttpCookie cuurentCookie=new HttpCookie(FormsAuthentication.FormsCookieName,encrypCurrentLoginFormsAuthenticationTicket);
                cuurentCookie.Expires
=DateTime.Now.AddHours(1);
                Response.Cookies.Add(cuurentCookie);

                
string returnUrl = Request.QueryString["ReturnUrl"];
                
if (returnUrl == null
                
{
                    returnUrl 
= "/";
                }


                
//页面转向
                
//不要再调用FormsAuthentication.RedirectFromLoginPage,因为它会替代刚才创建的Cookie
                Response.Redirect(returnUrl);                        
            }

            
else
            
{
                
//登陆失败
                this.ErrorLabel.Text="登陆错误!";
            }

         }

现在可以在任意页面判断角色信息了
例如:页面WebForm1只允许角色Service和Manage访问,那么在其Page_Load事件中,我们写下如下代码:
    private void Page_Load(object sender, System.EventArgs e)
        
{
            
            
if!BCSSecurity.IsInRole(BCSTool.GetWebConfigFileKeyValue("Service,Manage")))
            
{
                
//转到权限出错页面
                Response.Redirect(Global.ConstRoleErrorPageName,true);
            }

            
//验证角色合格,请接着做其他事情
            
        }

这样编写代码实现了角色的灵活控制。

让我们再看类BCSSecurity中代码
我们可以在任何页面使用BCSSecurity.GetUserId();等一系列的方法得到用户的ID,名称,Email等信息,这是不是用户状态保存的又一好办法呢?
using System;
using System.Web;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace BluepieCustomerService
{
    
/// <summary>
    
/// 数据安全类,定义了一些数据安全方法
    
/// </summary>

    public class BCSSecurity
    
{
        
/// <summary>
        
/// 加密一个字符串
        
/// </summary>
        
/// <param name="cleanString"></param>
        
/// <returns></returns>

        public static string Encrypt(string cleanString)
        
{
            Byte[] clearBytes 
= new UnicodeEncoding().GetBytes(cleanString);
            Byte[] hashedBytes 
= ((HashAlgorithm) CryptoConfig.CreateFromName("MD5")).ComputeHash(clearBytes);
            
            
return BitConverter.ToString(hashedBytes);
        }


        
/// <summary>
        
/// 判断该角色用户的访问权
        
/// </summary>
        
/// <param name="role"></param>
        
/// <returns></returns>

        public static bool IsInRole(String role) 
        
{
            
return HttpContext.Current.User.IsInRole(role);
        }


        
/// <summary>
        
/// 用户的UserId
        
/// </summary>
        
/// <returns></returns>

        public static int GetUserId()
        
{
            
return ((BCSLoginPrincipal)System.Web.HttpContext.Current.User).UserId ;
        }


        
/// <summary>
        
/// 登陆用户的昵称,即用户登陆名
        
/// </summary>
        
/// <returns></returns>

        public static string GetUserDisPlayName()
        
{
            
return ((BCSLoginPrincipal) System.Web.HttpContext.Current.User).UserDisPlayName;
        }


        
/// <summary>
        
/// 登陆用户的真实名称
        
/// </summary>
        
/// <returns></returns>

        public static string GetUserName()
        
{
            
return  (( BCSLoginPrincipal ) System.Web.HttpContext.Current.User).UserName ;
        }


        
/// <summary>
        
/// 登陆用户的Email
        
/// </summary>
        
/// <returns></returns>

        public static string GetUserEmail()
        
{
            
return ((BCSLoginPrincipal) System.Web.HttpContext.Current.User).UserEmail;
        }

        
    }

}


 
原创粉丝点击