在数据库中新建个表PermissionItem表用于保存权限ID和页面路径的关系一个权限ID可以有多个页面一般同一个权限ID下的页面是为了实现同一个功能PermissionList表用于保存用户所具有的权限
Code
USE[UrlAuthorize]
GO
/******Object:Table[dbo][PermissionList]ScriptDate://::******/
SETANSI_NULLSON
GO
SETQUOTED_IDENTIFIERON
GO
CREATETABLE[dbo][PermissionList](
[ID][int]IDENTITY()NOTNULL
[PermissionID][int]NOTNULL
[UserID][int]NOTNULL
CONSTRAINT[PK_PermissionList]PRIMARYKEYCLUSTERED
(
[ID]ASC
)WITH(PAD_INDEX=OFFSTATISTICS_NORECOMPUTE=OFFIGNORE_DUP_KEY=OFFALLOW_ROW_LOCKS=ONALLOW_PAGE_LOCKS=ON)ON[PRIMARY]
)ON[PRIMARY]
GO
SETIDENTITY_INSERT[dbo][PermissionList]ON
INSERT[dbo][PermissionList]([ID][PermissionID][UserID])VALUES()
INSERT[dbo][PermissionList]([ID][PermissionID][UserID])VALUES()
SETIDENTITY_INSERT[dbo][PermissionList]OFF
/******Object:Table[dbo][PermissionItem]ScriptDate://::******/
SETANSI_NULLSON
GO
SETQUOTED_IDENTIFIERON
GO
SETANSI_PADDINGON
GO
CREATETABLE[dbo][PermissionItem](
[ID][int]IDENTITY()NOTNULL
[PermissionID][int]NOTNULL
[Name][nvarchar]()NOTNULL
[Route][varchar]()NOTNULL
CONSTRAINT[PK_PermissionItem]PRIMARYKEYCLUSTERED
(
[ID]ASC
)WITH(PAD_INDEX=OFFSTATISTICS_NORECOMPUTE=OFFIGNORE_DUP_KEY=OFFALLOW_ROW_LOCKS=ONALLOW_PAGE_LOCKS=ON)ON[PRIMARY]
)ON[PRIMARY]
GO
SETANSI_PADDINGOFF
GO
SETIDENTITY_INSERT[dbo][PermissionItem]ON
INSERT[dbo][PermissionItem]([ID][PermissionID][Name][Route])VALUES(N测试页N/Test/Page)
INSERT[dbo][PermissionItem]([ID][PermissionID][Name][Route])VALUES(N测试页N/Test/Page)
INSERT[dbo][PermissionItem]([ID][PermissionID][Name][Route])VALUES(N测试页N/Test/Page)
INSERT[dbo][PermissionItem]([ID][PermissionID][Name][Route])VALUES(N测试页N/Test/Page)
INSERT[dbo][PermissionItem]([ID][PermissionID][Name][Route])VALUES(N测试页N/Test/Page)
SETIDENTITY_INSERT[dbo][PermissionItem]OFF
)thisstylewidth=; border=>
数据库中的示例表示Page和Page同属于权限Page和Page同属于权限Page属于权限用户ID为的用户具有权限和
在ASPNET MVC项目中新建一个AccountHelper类这是一个辅助类GetPermissionItems方法用于获取权限ID和页面路径的对应关系这是全局的并且每个用户在访问页面时都会用到这些信息所以存入Cache中数据库的相关操作这里使用的是ADONET Entity Framework
/**//// <summary>
/// 获取权限项
/// </summary>
/// <returns>权限项列表</returns>
public static List<PermissionItem> GetPermissionItems()
{
// 如果缓存中已经存在权限列表信息则直接从缓存中读取
if (HttpContextCurrentCache[PermissionItems] == null)
{
// 如果缓存中没有权限列表信息则从数据库获取并写入缓存
UrlAuthorizeEntities db = new UrlAuthorizeEntities();
var items = dbPermissionItemWhere(c => cPermissionID > )ToList();
HttpContextCurrentCache[PermissionItems] = items;
}
// 这个缓存中保存了所有需要进行权限控制的页面所对应的权限ID
return (List<PermissionItem>)HttpContextCurrentCache[PermissionItems];
}
GetUserPermission方法是将用户所具有的权限ID保存到一个一维Int数组中
这个信息每个用户是不同的但是会经常使用到所以存入Session
/**//// <summary>
/// 获取用户权限
/// </summary>
/// <param name=userID>用户ID</param>
/// <returns>用户权限数组</returns>
public static Int[] GetUserPermission(int userID)
{
// 如果缓存中已经存在权限列表信息则直接从缓存中读取
if (HttpContextCurrentSession[Permission] == null)
{
// 从数据库获取用户权限并将权限ID放到int数组并存入Session
UrlAuthorizeEntities db = new UrlAuthorizeEntities();
var permissions = dbPermissionListWhere(c => cUserID == userID)Select(c=>cPermissionID)ToArray();
HttpContextCurrentSession[Permission] = permissions;
}
return (Int[])HttpContextCurrentSession[Permission];
}
再新建一个UrlAuthorizeAttribute类继承自AuthorizeAttribute这是一个Filter我们重写它的OnAuthorization方法以在ASPNET页生命周期身份验证阶段执行它
/**//// <summary>
/// 重写OnAuthorization
/// </summary>
/// <param name=filterContext></param>
public override void OnAuthorization(AuthorizationContext filterContext)
{
// 获取权限项列表
List<PermissionItem> pItems = AccountHelperGetPermissionItems();
// 获取当前访问页面对应的权限ID如果item为空则表示当前页面没有权限控制信息不需要进行权限控制
var item = pItemsFirstOrDefault(c => cRoute == filterContextHttpContextRequestPath);
if (item != null)
{
if (ArrayIndexOf<Int>(AccountHelperGetUserPermission(intParse(filterContextHttpContextSession[UserID]ToString())) itemPermissionID) == )
{
// 提示权限不够也可以跳转到其他页面
filterContextHttpContextResponseWrite(没有权限访问该页面);
filterContextHttpContextResponseEnd();
}
}
else
{
// 如果权限项列表中不存在当前页面对应的权限ID则所有用户都不允许访问直接提示无权访问***注***
filterContextHttpContextResponseWrite(没有权限访问该页面);
filterContextHttpContextResponseEnd();
}
}
至此主要的工作都已经完成了的接下来我们只需要在需要进行基于URL权限控制的Action或Controller前加上[UrlAuthorize]这些Action或Controller中的所有Actions就会自动被UrlAuthorize这个Filter进行处理如果某一个Action被标上了[UrlAuthorize]而数据库中又不存在该页面对应的权限ID那么根据示例的代码所有用户都将无法访问这个页面如果需要更改这个设置可以修改上面注下面的行代码