asp.net Forms身份验证和基于角色的权限访问(转)

构建基于forms的验证机制过程如下:
 1,设置IIS为可匿名访问和asp.net web.config中设置为form验证
  2,检索数据存储验证用户,并检索角色(如果不是基于角色可不用)
 3,使用FormsAuthenticationTicket创建一个 Cookie并回发到客户端,并存储
  角色到票据中,如:
  FormsAuthentication.SetAuthCookie(Username,true | false)
  cookies保存时间:
  HttpContext.Current.Response.Cookies[FormsAuthentication.FormsCookieName].Expires=DateTime.Now.AddDays(1)
 
  如果需要存储角色,采用:
 FormsAuthenticationTicket authTicket = new
 FormsAuthenticationTicket(
  1, // 版本号。
  txtUserName.Text, // 与身份验证票关联的用户名。
  DateTime.Now, // Cookie 的发出时间。
  DateTime.Now.AddMinutes(20),// Cookie 的到期日期。
  false, // 如果 Cookie 是持久的,为 true;否则为 false。
  UserData ); // 将存储在 Cookie 中的用户定义数据,可以是用户所属角色,
                       // 若角色保存在数据库中,则用User.Roles等方式;
                       // 若不在数据库中,则可以直接写,如“Admin”,"User"等值
  string encryptedTicket = FormsAuthentication.Encrypt(authTicket); //加密
 
  存入Cookie
  HttpCookie authCookie =
  new HttpCookie(FormsAuthentication.FormsCookieName,
  encryptedTicket);
 
  Response.Cookies.Add(authCookie);
 
 4,在 Application_AuthenticateRequest事件中处理程序中(Global.asax)中,使用
  票创建IPrincipal对象并存在HttpContext.User中
  代码:
  HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
  FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);//解密
  string[] roles = authTicket.UserData.Split(new char[]{';'});//根据存入时的格式分解,;或|....
  Context.User = new GenericPrincipal(Context.User.Identity, Roles);//存到HttpContext.User中
 
 判断某个角色验证
  HttpContext.Current.User.IsInRole(roles)
 具体实现
 
 Web.config 文件
 加入节点,name为COOKIE名称,loginUrl为没有通过验证跳转的地址
 <system.web>
  <authentication mode="Forms">
  <forms name="Hstear"
  loginUrl="login.aspx" protection="All" path="/" timeout="40"/>
  </authentication>
 </system.web>
 设置目录访问 path为目录名,roles为票据中的角色名
 发现网上的都说要单独一个WEB.CONFIG文件放在目录中,但实际在根目录中设置即可,单 个文件也一样
 <location path="Admin">
       <system.web>
       <authorization>
       <allow roles="admin"/>
       <deny users="*"/>
       </authorization>
       </system.web>
 </location>

以下是一个具体实例的步骤:


1、创建一个网站,结构如下:
网站根目录
Admin目录 ----> 管理员目录
Manager.aspx ----> 管理员可以访问的页面
Users目录 ----> 注册用户目录
Welcome.aspx ----> 注册用户可以访问的页面
Error目录 ----> 错误提示目录
AccessError.htm ----> 访问错误的提示页面
default.aspx ----> 网站默认页面
login.aspx ----> 网站登录页面
web.config ----> 网站配置文件
2、配置web.config如下:

<configuration>
<system.web>
<!--设置Forms身份验证--> 
        <authentication mode="Forms"> 
                <forms loginUrl="Login.aspx" name="MyWebApp.APSXAUTH" path="/" protection="All" timeout="30"/> 
        </authentication> 
        <authorization> 
                <allow users="*"/> 
        </authorization>
</system.web>
</configuration>

<!--设置Admin目录的访问权限-->
<location path="Admin"> 
        <system.web> 
                <authorization> 
                        <allow roles="Admin"/> 
                        <deny users="?"/> 
                </authorization> 
        </system.web>
</location>
<!--设置Users目录的访问权限-->
<location path="Users"> 
        <system.web> 
                <authorization> 
                        <allow roles="User"/> 
                        <deny users="?"/> 
                </authorization> 
        </system.web>
</location>

3、在login.aspx页面的登录部分代码如下:

protected void btnLogin_Click(object sender, EventArgs e)

        //Forms身份验证初始化 
        FormsAuthentication.Initialize(); 
        //验证用户输入并得到登录用户,txtName是用户名称,txtPassword是登录密码 
        UserModel um = ValidUser(txtName.Text.Trim(),txtPassword.Text.Trim()); 
        if (um != null) 
        { 
                //创建身份验证票据 
                FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, 
                um.Name, 
                DateTime.Now, 
                DateTime.Now.AddMinutes(30), 
                true, 
                um.Roles,//用户所属的角色字符串 
                FormsAuthentication.FormsCookiePath); 
                //加密身份验证票据 
                string hash = FormsAuthentication.Encrypt(ticket); 
                //创建要发送到客户端的cookie 
                HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash); 
                if (ticket.IsPersistent) 
                { 
                        cookie.Expires = ticket.Expiration; 
                } 
                //把准备好的cookie加入到响应流中 
                Response.Cookies.Add(cookie);

                //转发到请求的页面 
                Response.Redirect(FormsAuthentication.GetRedirectUrl(um.Name,false)); 
        } 
        else 
        { 
                ClientScriptManager csm = this.Page.ClientScript; 
                csm.RegisterStartupScript(this.GetType(), "error_tip", "alert('用户名或密码错误!身份验证失败!');", true); 
        }
}
//验证用户
private UserModel ValidUser(string name, string password)

        return new UserService().Validate(name, password);
}

4、给网站添加处理程序Global.asax,其中通用身份验证代码如下:

//改造原来的User,给其添加一个用户所属的角色数据
protected void Application_AuthenticateRequest(object sender, EventArgs e)

        if (HttpContext.Current.User != null ) 
        { 
                if (HttpContext.Current.User.Identity.IsAuthenticated) 
                { 
                        if (HttpContext.Current.User.Identity is FormsIdentity) 
                        { 
                                FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity; 
                                FormsAuthenticationTicket ticket = id.Ticket;

                                string userData = ticket.UserData; 
                                string[] roles = userData.Split(','); 
                                //重建HttpContext.Current.User,加入用户拥有的角色数组 
                                HttpContext.Current.User = new GenericPrincipal(id, roles); 
                        } 
                } 
        }
}

5、在Admin目录中Manager.aspx页面加载代码如下:
复制代码 代码如下:
protected void Page_Load(object sender, EventArgs e)

        //判断通过身份验证的用户是否有权限访问本页面 
        FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity; 
        //判断通过身份验证的用户是否是Admin角色 
        if (!id.Ticket.UserData.Contains("Admin")) 
        { 
                //跳转到访问权限不够的错误提示页面 
                Response.Redirect("~/Error/AccessError.htm", true); 
        }
}
//安全退出按钮的代码
protected void btnExit_Click(object sender, EventArgs e)

        //注销票据 
        FormsAuthentication.SignOut(); 
        ClientScriptManager csm = this.Page.ClientScript; 
        csm.RegisterStartupScript(this.GetType(), "exit_tip", "alert('您已经安全退出了!');", true); 
 }

6、在Users目录中Welcome.aspx页面加载代码如下:

protected void Page_Load(object sender, EventArgs e)

        //判断通过身份验证的用户是否有权限访问本页面 
        FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity; 
        //判断通过身份验证的用户是否是User角色 
        if (!id.Ticket.UserData.Contains("User")) 
        { 
                //跳转到访问权限不够的错误提示页面 
                Response.Redirect("~/Error/AccessError.htm", true); 
        }
}


//安全退出按钮的代码
protected void btnExit_Click(object sender, EventArgs e)

        //注销票据 
        FormsAuthentication.SignOut(); 
        ClientScriptManager csm = this.Page.ClientScript; 
        csm.RegisterStartupScript(this.GetType(), "exit_tip", "alert('您已经安全退出了!');", true);
}

测试结果:
数据:
假设有3个用户,如下:
------------------------------------------
用户名 密码 角色字符串
------------------------------------------
sa sa Admin,User
admin admin Admin
user user User
------------------------------------------
测试:
如果使用admin登录,只能访问Admin目录的Manager.aspx页面;
如果使用user登录,只能访问Users目录的Welcome.aspx页面;
使用sa登录,既能访问Admin目录的Manager.aspx页面,又能访问Users目录的Welcome.aspx页面。
注意:测试时注意及时点击安全退出按钮,否则影响测试结果。

--------------------------------------------------------------------------------------------------------------------------------------------------------

原文地址:https://www.cnblogs.com/hfutwyy/p/2127133.html