登陆并将自定义信息存入cookie以实现分权访问!

    技术2025-10-21  11

    以前做登陆都是使用login控件的,发觉如果要加入自定义的信息好象比较麻烦,所以参考了别人的东西后记录一下心得,参考:http://www.cnblogs.com/Showshare/archive/2010/07/09/1772886.html

    在这里我使用的是form认证,在web.config中设置不允许匿名访问。

    <authentication mode="Forms"> <forms name=".ASPXAUTH" loginUrl="Login.aspx" protection="All" path="/" timeout="20" defaultUrl="Default.aspx"></forms> </authentication> <authorization> <deny users="?"/> </authorization> 

    <authehtication>节中设置了认证方式、cookie的名称、默认登陆页等信息,<authorization>节中设置不允许匿名。

    实现分权限是根据网站目录来划分的,不同的目录用<location>节中的<allow>...</allow>限制不同用户访问

    在web.config中加入

    <location path="Register.aspx"> <system.web> <authorization> <allow users="*"/> </authorization> </system.web> </location> <location path="ManageAdmin"> <system.web> <authorization> <allow roles="Admininstrators"/> <deny users="*"/> </authorization> </system.web> </location>  

    1、注意上面的片断是加入到<system.web>节外的,与<system.web>同级的位置。

    2、<location path="Register.aspx">...</location>段是说明在根目录下的Register.aspx是所有用户都可以访问,<location path="ManageAdmin">...</location>指定roles为"Admininstrators“的用户才可以访问ManageAdmin目录下的网页。

    建立自定义用户信息,在类中加入以下代码。

    [Serializable] public class UserInfo { //用户登录信息 private int _nId; private string _sRealName; private string _sName; private string _sPassword; private string _sRoles; public int Id { get { return this._nId; } set { this._nId = value; } } public string RealName { get { return this._sRealName; } set { this._sRealName = value; } } public string Name { get { return this._sName; } set { this._sName = value; } } public string Password { get { return this._sPassword; } set { this._sPassword = value; } } public string Roles { get { return this._sRoles; } set { this._sRoles = value; } } public UserInfo() { } } 

    [Serializable]标识类为可序列化,因为以后要将UserInfo存入cookie中,而cookie只能储存字符所以要存入前先进行序列化。

    序列化与反序列化函数:

    public class UserSerialize { public UserSerialize() { } public string UserInfoToSerialize(UserInfo user) { BinaryFormatter bf = new BinaryFormatter(); MemoryStream mStream = new MemoryStream(); bf.Serialize(mStream, user); byte[] buf = mStream.ToArray(); mStream.Close(); return System.Convert.ToBase64String(buf); } public UserInfo UnSerializeToUserInfo(string strUserInfo) { byte[] binary = Convert.FromBase64String(strUserInfo); BinaryFormatter bf = new BinaryFormatter(); MemoryStream mStream = new MemoryStream(binary); UserInfo currentUser = (UserInfo)bf.Deserialize(mStream); mStream.Close(); return currentUser; } } 

    以上两个函数要使用到System.IO和System.Runtime.Serialization.Formatters.Binary两个命名空间。

    要方便的使每个网页都可以访问到用户的信息,就要在页中加入自定义类型UserInfo,所以在类中定义一个page类作为所有已登陆页的基类

    public class LoginBasePage : Page { protected UserInfo LoginUser { get { string strUser = ((FormsIdentity)Context.User.Identity).Ticket.UserData; return new myClass.UserSerialize().UnSerializeToUserInfo(strUser); } } public LoginBasePage() { } } 

    以后页面的.cs文件中就要改为以LoginBasePage为基类,如Default.apsx的.cs文件就要改为

    public partial class _Default : myClass.LoginBasePage { protected void Page_Load(object sender, EventArgs e) { } }

    其中myClass是我的类文件名称。以前要读取已登陆用户信息的话就直接用类似LoginUser.Name这样就可以了。

    另外,要实现按roles控制目录访问权限,就要设置好Contex.User.Identity的角色验证。现在每进入一个页面都需要将角色信息设置到Context.User中,那么最好的办法就是在Global.asax 文件中的Application_AuthenticateRequest方法中设置。

      Application_AuthenticateRequest方法,是在每次验证请求时触发,它与另外一个方法Application_BeginRequest的区别就在于,Application_AuthenticateRequest方法内,能够访问Context.User.Identity,而Application_BeginRequest则无法访问。

      我们在根目录添加一个Global.asax 文件,增加如下代码:

    protected void Application_AuthenticateRequest(object sender, EventArgs e) { if (this.Context.User != null) { if (this.Context.User.Identity.IsAuthenticated) { if (this.Context.User.Identity is FormsIdentity) { string strUser = ((FormsIdentity)this.Context.User.Identity).Ticket.UserData; string[] roles = new MyClass.UserSerialize().UnSerializeToUserInfo(strUser).Roles.Split(','); this.Context.User = new GenericPrincipal(this.Context.User.Identity, roles); } } } }  

     

    此处,主要代码就是将Context.User.Identity强制转换为FormsIdentity类的对象,通过访问Ticket属性的UserData属性,获得被序列化后的对象的字符串,最后用方法Serialize.Decrypt<UserInfo>(strUser)将字符串反序列化成对象,再将UserInfo对象的Roles属性以“,”为分隔符分隔成角色数组,再用Context.User.Identity和角色数组生成一个新的GenericPrincipal对象,赋值给Context.User ,则Context.User 为已经设置好角色的验证对象。

      按照我们的设置,Admin用户能访问两个目录,而User1用户,则只能访问ManageUsers一个目录。

     

    最后就是Login.aspx中的内容了,下面模似了用户的认证过程,如果用户通过了认证就将用户信息序列化,加入到认证cookie中,然后加密cookie,最后写入认证cookie以完成用户登陆。

    protected void Btn_Login_Click(object sender, System.EventArgs e) { if (Txt_UserName.Text == "Admin" && Txt_Password.Text == "123") { myClass.UserInfo user = new myClass.UserInfo(); user.Id = 1; user.Name = Txt_UserName.Text.Trim(); user.Password = Txt_Password.Text.Trim(); user.RealName = "真的不知是谁"; user.Roles = "Admininstrators,Users"; string strUser = new myClass.UserSerialize().UserInfoToSerialize(user); FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, user.Name, DateTime.Now, DateTime.Now.AddMinutes(20), false, strUser); string strTicket = FormsAuthentication.Encrypt(ticket); HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, strTicket); cookie.Expires = ticket.Expiration; Response.Cookies.Add(cookie); Response.Redirect("Default.aspx"); } 

     

    最新回复(0)