权限设置(飞机订票系统案例)
第一种方法、(页面)
缺点:没有办法阻止用户通过网页地址(页面路径)进入某页面
1.在主页面上写一个方法(主页面—其他页面的根页面,通过主页面跳转)
function JurisdictionMenu()
2.获取页面上全部菜单
var dirIdModlarName = {
"PNR": "PNR",
"电子票证": "ELectromicTicket",
…………}
3.发送提交请求
$.post("/Main/SelectModularJurisdiction", { time: (new Date()).getTime().toString() }, function (objModulars) {}
4.判断
if (objModulars == "") {
window.location.href = "/";
} else {
for (key in objModulars) {
var obj = objModulars[key];
if (obj.ID == 0) {
var modularName = obj.ModularName;
var elId = dirIdModlarName[modularName];
console.log(elId);
$("#" + elId).remove();//去掉没有的权限对应的菜单
}
}
}
5.回到控制器接收请求
public ActionResult SelectModularJurisdiction()
6.判断
if (Session["userID"] != null) //与登录时所保存的名称(大小写)一致 Session["userID"] = dbUser.userID;
6.读取权限信息(查询权限)
var temModulars = from tabPermission in myModel.S_Permission
join tabModule in myModel.S_Module
on tabPermission.moduleID equals tabModule.moduleID
join tabUser in myModel.S_User
on tabPermission.UserTypeID equals tabUser.userTypeID
where tabUser.userID == userId && tabModule.blFun == false
select new
{
ID = tabModule.moduleID,//模块ID
Name = tabModule.moduleDescrible.Trim() //模块描述
};
//外连接(左连接 Model表)
var userModulars = (from tbSysModular in myModel.S_Module
join tbTempModulars in temModulars
on tbSysModular.moduleID equals tbTempModulars.ID into temp
select new
{
ModularID = tbSysModular.moduleID,//模块ID
ModularName = tbSysModular.moduleDescrible.Trim(),//模块名称
ID = temp.FirstOrDefault() != null ? temp.FirstOrDefault().ID : 0 //有该模块的权限 ID>0 没有权限ID=0
}).ToList();
7.返回查询数据
return Json(userModulars, JsonRequestBehavior.AllowGet);
返回数值为0的原因
①没有查询区域 所以区域值为0(只查询了在菜单栏上的功能值)
②功能有各自的ID ,ID为0等于没有权限
③PNR复制为0 原因:PNR复制是方法没有在菜单显示 没有查询方法 查询的只有功能
8.页面引用方法
$(document).ready(function () {
JurisdictionMenu();
});
第二种方法、(过滤器—进入控制器前查询是否拥有权限)
优点:直接在后台控制器拦截,无法从网页路径进入页面
1.找到整个项目中解决方案的APP_Start文件夹添加一个类(图中选中)
类中的namespace 直接是项目名称(类方法名):namespace FJDPXT
2.在FilterConfig类中,写一个固定的方法(不能乱改)
/// <summary>
/// 注册全局过滤器
/// static 修饰方法(类的方法,不是实例方法,不需要用new调用)
/// </summary>
/// <param name="filters"></param>
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//全局默认的过滤器-错误处理
filters.Add(new HandleErrorAttribute());
//添加自定义 权限过滤器
filters.Add(new PermissionFilter());
}
3.找到整个项目中解决方案的Global.asax
注册FilterConfig中需要的filters(注册全局过滤器)
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
//注册全局过滤器 FilterConfig
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
4.新建一个目录(自命名)
5.新建一个(自命名)-- 权限过滤器
5.1继承类
using System.Web.Mvc;
public class PermissionFilter :ActionFilterAttribute
5.2重写重定向方法(前置控制器重写重定向方法)
/// <summary>
/// 在方法执行前 执行
/// </summary>
/// <param name="filterContext"></param>
public override void OnActionExecuting(ActionExecutingContext filterContext){
base.OnActionExecuting(filterContext);
OnActionExecuted 方法执行后 执行
OnResultExecuted 返回数据后执行
OnResultExecuting 返回数据前执行
5.3获取请求的URL
int loginUserID = 0;
try
{
string url = filterContext.HttpContext.Request.Url.AbsolutePath;
5.4检查是否登录
跳过登录检查的URL
if (url == "/" || url == "/Main/Login" || url == "/Main/CreateValidImage" || url == "/Main/UserLogin")
{
return; (如果url == "/Main/Login",跳出(结束)检查)
}
url != "/Main/Login"时检查
5.5转换ID
loginUserID = Convert.ToInt32(filterContext.HttpContext.Session["userID"].ToString());
转换ID,转换成功后进行权限检查
5.6权限检查
需要使用<ModuleVo>类:添加类(自命名),引用Model
//实例化model
FJDPXTEntities myModel = new FJDPXTEntities();
public class ModuleVo:S_Module 继承Module
{
/// <summary>
/// 父模块
/// </summary>
public S_Module parentModule { get; set; }
}
if (url == "/" || url.Contains("/Main{
return;
}
/"))(主控制器不进行检查)
5.6第一种方法:在登录时获取查询的模块信息
优点: 响应速度快,效率高
缺点:管理员在用户登录之后再更改权限,这时候权限无法生效,下一次重新登录后才能生效(只查询一次权限)
List<ModuleVo> userModules = filterContext.HttpContext.Session["userModules"] as List<ModuleVo>;
5.6第二种方法:每一次请求都查询一次权限(在登录页面控制器查询)
优点:安全性高
缺点:当网站过大时: 每次操作都需要重新获取权限 会导致性能开销太大(每次操作时都需要查询数据库会影响到响应速度)
???两种方法需要根据自己的项目来进行选择 需要的是权限的更改及时或性能优先
int loginUserID = dbUser.userID;
List<ModuleVo> userModules = (from tabModule in myModel.S_Module
join tabP in myModel.S_Permission
on tabModule.moduleID equals tabP.moduleID
join tabUseType in myModel.S_UserType
on tabP.UserTypeID equals tabUseType.userTypeID
join tabUser in myModel.S_User
on tabUseType.userTypeID equals tabUser.userTypeID
where tabUser.userID == loginUserID
select new ModuleVo
{
moduleID = tabModule.moduleID,
moduleName = tabModule.moduleName,
moduleDescrible = tabModule.moduleDescrible,
moduleFarID = tabModule.moduleFarID,
blFun = tabModule.blFun,
parentModule = (from tabModuleF in myModel.S_Module
where tabModuleF.moduleID == tabModule.moduleFarID
select tabModuleF).FirstOrDefault()
}).ToList();
保存用户信息到session
Session["userModules"] = userModules;
根据/分割 -> 0-空字符串,1-区域名称,2-控制器名称,3-Action
string[] strUrls = url.Split('/');
5.7判断
if (strUrls.Length >= 4)(根据自身实际情况处理)
{
string areaName = strUrls[1];//获取区域名称
string controllerName = strUrls[2]; //获取控制器名称
//一般情况权限处理--判断 区域和 控制器
int exist = userModules.Count(o => o.moduleName == controllerName && o.parentModule.moduleName == areaName);
if (exist == 0)(没有权限,重定向到没有权限页面)
{
filterContext.HttpContext.Response.Redirect("/Main/NoPermission");
}
处理PNR复制功能(属于控制器里的方法)处理方式不一样,单独判断
if (strUrls[3] == "CopyPNR")
{
if (userModules.Count(o => o.moduleName == "PNRCopy" && o.parentModule.moduleName == controllerName) == 0)
{
filterContext.HttpContext.Response.Redirect("/Main/NoPermission");
}
}
}
5.5转换ID,转换失败
catch (Exception e)—进入异常
{
Console.WriteLine(e);
filterContext.HttpContext.Response.Redirect("/Main/Login");重定向到登录页面(主控制器内部)}
6.在主控制器建立权限页面
成果图