我们知道对于权限管理这块,采取的思想就是RBAC
每个用户对应一个角色,我们只需要对这个角色进行分配相应的权限即可,也就是给这个用户分配了权限,这样管理起来很方便,设计也很简答,大概就是用户表,角色表,模块表,在加上一个角色与模块对应的表就可以了,然后根据不同的用户权限,显示相应的模块或者提示没有权限访问,这里要说的就是,对每个页面的访问权限,如果都写的话,这么多的页面是个很大的工作量,类似判断用户是否登录一样,在asp.net中我们完全可以使用Forms验证来代替使用session每个页面都要判断的做法,同样,在这里我们也可以通过HttpModule来直接过滤掉没有访问权限的页面,方便多了,我们知道HttpModule可以再服务器端接收处理之前进行相关的过滤,这点给我们提供很大的方便,我们完全可以利用它的这一点,具体的来看看下:
{
private static string loginPage = "login.aspx";
#region IHttpModule Members
public void Dispose()
{
//此处放置清除代码。
}
public void Init(HttpApplication context)
{
context.AcquireRequestState += new EventHandler(checkUserRight);
}
/// <summary>
/// 检测用户权限
/// </summary>
void checkUserRight(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender; // 获取应用程序
string url = HttpContext.Current.Request.Url.ToString(); // 获取Url
int start=url.LastIndexOf('/') + 1; //查找URL中最后一个/的位置
int end=url.IndexOf('?',start); //查找URL中?位置
string requestPage = null;
if (end < 0) end = url.Length - 1;
requestPage=url.Substring(start, end - start +1); //得到所请求的页面
requestPage = requestPage.ToLower();
if (requestPage == loginPage) return;
if (!isProtectedResource(requestPage)) return;
User user=SJL.Web.HttpCode.WebUtility.currentUser; //获得当前用户
if (user==null)
{
application.Response.Redirect("~/Login.aspx");
return;
}
if (SJL.Bll.UserRight.UserBLL.isAdmin(user)) return;
//检测用户权限
if (!SJL.Bll.UserRight.RoleRightBLL.canAccessPage(user.RoleID, requestPage))
application.Response.Redirect("~/AccessDeny.htm");
}
/// <summary>
/// 判断页面是否为受权限管理保护的资源(如Aspx等)
/// </summary>
/// <param name="page">所请求的页面</param>
/// <returns>是否受保护</returns>
bool isProtectedResource(string page)
{
page = page.ToLower();
System.Collections.Generic.List<String> protectedFiles =
new System.Collections.Generic.List<string>(); //受保护资源的扩展名
protectedFiles.AddRange(new string[] { ".aspx", ".asmx", ".ashx" });
string found=protectedFiles.Find(s => page.EndsWith(s));
if (found == null)
return false;
ApplicationModule module = SJL.Bll.UserRight.ApplicationModuleBLL.getByUrl(page);
if (module == null) return false;
return !module.IsPublic; //如果页面为公共模块则不受保护
}
#endregion
public void OnLogRequest(Object source, EventArgs e)
{
//可以在此放置自定义日志记录逻辑
}
}
Web.coinfig中配置下
<httpModules>
<add name="CheckUserModule" type="SJL.Web.HttpCode.CheckUserModule"/>
</httpModules>
先判断是否登录,是否是受保护的资源,然后根据url来判断是否有权限访问!
我们可以根据自己需要控制的权限去设置,比如一个企业级的软件,我们需要控制菜单的页面,那么这个时候,我们只需要判断
1、.aspx结尾的文件,httpModules过滤的时候也会过滤下比如css,js,ashx等页面,在这里因为受权限保护的只有aspx结尾的,所有只需要对aspx结尾的进行过滤判断即可
2、是否是受权限控制的页面
3、如果没有登录,则跳到登录页面
4、如果是受权限控制的页面,那么就看看此时登录的用户是否有访问的这个页面的url权限即可
注意点:
1、因为这种方式主要是对页面进行权限判断,所以为了权限设置到位,比较严,最好每一个需要权限保护的功能都单独做一个页面,不要和其他页面套在一起,放置权限设置混乱
2、判断权限页面的时候,对访问的页面和数据库保存的页面都要去除参数和目录,比如/user/user_edit.aspx?id=5,那么这个时候我们就要截取获得user_edit.aspx用来判断,否则,就会出现权限控制不严格的情况,比如列表 /user/user_list.aspx,如果你对访问过来的url没有截取判断,那么访问user_list.aspx?page=5则会通过,但是事实上我们已经控制这个页面不让访问了,就是因为url不同导致权限控制有问题,所以这点一定要注意!
采用httpModule的好处就是一步操作就可以完成权限控制和未登录验证,效果很好,改变了传统的每个页面都需要判断的写法
Code:
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
using shuang.Model;
/// <summary>
///CheckUserModule 的摘要说明
/// </summary>
public class CheckRoleModule : IHttpModule
{
public static string loginPage = "login.aspx";
public CheckRoleModule()
{
//
//TODO: 在此处添加构造函数逻辑
//
}
#region IHttpModule 成员
public void Init(HttpApplication context)
{
context.AcquireRequestState += new EventHandler(checkUserMenu);
}
void checkUserMenu(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender; // 获取应用程序
string url = HttpContext.Current.Request.Url.ToString(); // 获取Url
int start = url.LastIndexOf('/') + 1; //查找URL中最后一个/的位置
int end = url.IndexOf('?', start); //查找URL中?位置
string requestPage = null;
if (end < 0) end = url.Length;
requestPage = url.Substring(start, end - start); //得到所请求的页面
//截取后缀
if (requestPage == loginPage) return;
string requestPageSuffix = requestPage.Substring(requestPage.LastIndexOf(".") + 1);
if (requestPageSuffix != "aspx")
{
return;
}
string user = OperateCommon.currentUser;//对每一个页面都要判断是否登录
if (user == null)
{
application.Response.Write("<script language='javascript'>parent.location.href='" + Common.ApplicationRootPath + "/login.aspx';</script>");
return;
}
else
{
//查看是否是菜单权限控制页面
// requestPage = url.Substring(start);
if (!isProtectedResource(requestPage)) return;
//检测用户权限
if (!OperateCommon.isPross(user,requestPage)) {
Common.showMsg("0", "你没有访问该页面的权限,请联系管理员");
}
}
}
/// <summary>
/// 判断页面是否为受权限管理保护的资源
/// </summary>
/// <param name="page">所请求的页面</param>
/// <returns>是否受保护</returns>
bool isProtectedResource(string page)
{
// page = page.ToLower();
List<String> protectedFiles =OperateCommon.GetMenu();//受保护的页面
//读取所有菜单栏目的url
bool fig = false;
foreach (string item in protectedFiles)
{
if(item==page)
{
fig = true;
break;
}
}
return fig;
}
public void Dispose()
{
// throw new NotImplementedException();
}
#endregion
}
OPerateCommon
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using shuang.BLL;
using shuang.Model;
using System.Collections.Generic;
/// <summary>
///OperateCommon 的摘要说明
/// </summary>
public class OperateCommon
{
public OperateCommon()
{
//
//TODO: 在此处添加构造函数逻辑
//
}
private const string SessionUser = "LoginName"; //登录用户
private static string loginName = "";
public static string currentUser
{
get
{
if (HttpContext.Current == null)
{
return null;
}
else
{
if (HttpContext.Current.Session[SessionUser] != null)
{
return HttpContext.Current.Session[SessionUser].ToString();
}
}
return null;
}
set
{
HttpContext.Current.Session[SessionUser] = value;
}
}
public static void getLoginName()
{
if (currentUser!= null)
{
loginName = HttpContext.Current.Session[SessionUser].ToString();
}
else
{
HttpContext.Current.Response.Redirect("~/logout.aspx");
}
}
/// <summary>
/// 检测用户的访问权限
/// </summary>
/// <returns></returns>
public static bool isPross(string loginName,string requestPage)
{
UserBLL bll = new UserBLL();
RoleBLL rolebll = new RoleBLL();
menuBLL menubll = new menuBLL();
bool fig = false;
DataSet ds = bll.GetList(" userName='"+loginName+"'");
if (ds != null)
{
string roleId = ds.Tables[0].Rows[0]["userRole"].ToString();
Role role = rolebll.GetModel(Convert.ToInt32(roleId));
string menuId = role.roleMenulimit;
DataSet dsMenu = menubll.GetList(" menuId in("+menuId+")");
foreach (DataRow row in dsMenu.Tables[0].Rows)
{
string url = row["url"].ToString();
int start = url.LastIndexOf('/') + 1; //查找URL中最后一个/的位置
int end = url.IndexOf('?', start);
string url1 = null;
if (end < 0) end = url.Length;
url1 = url.Substring(start, end - start);
if (url1 == requestPage)
{
fig=true;
break;
}
}
}
return fig;
}
/// <summary>
/// 获取受保护的菜单页面
/// </summary>
/// <returns></returns>
public static List<string> GetMenu()
{
menuBLL menubll = new menuBLL();
DataSet ds = menubll.GetList(" parent!=0");
List<string> menuList = new List<string>();
foreach (DataRow row in ds.Tables[0].Rows)
{
string url = row["url"].ToString();
int start = url.LastIndexOf('/') + 1;//查找URL中最后一个/的位置
// url = url.Substring(start);
int end = url.IndexOf('?', start);
string requestPage = null;
if (end < 0) end = url.Length;
requestPage = url.Substring(start, end - start);
menuList.Add(requestPage);
}
return menuList;
}
}
web.config
<add name="CheckUserModule" type="CheckRoleModule"/>
这样就完成了权限限制,文件过滤等问题...