之前介绍了My AppBox V2.0,今天把拦截器补上,适用FineUICore,实现登录超时跳转,url参数获取,以及操作日志的保存;

1. 继承扩展和引用

在Controller层,所有页面都引用了 SysPageController ,所以拦截器的扩展只针对 SysPageController 类就可以了,在 System.Web.Mvc 中扩展拦截器直接继承 Controller 类,扩展 OnResultExecuted 方法,在 Microsoft.AspNetCore.Mvc 中挪了位置,要继承 ActionFilterAttribute 类中的 OnResultExecuted 方法:

/// <summary>
/// 回发权限控制
/// </summary>
public class SysPageFilter : ActionFilterAttribute
{
    #region 回发权限控制 OnResultExecuted
    /// <summary>
    /// 覆盖
    /// </summary>
    /// <param name="filterContext"></param>
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        //
        base.OnResultExecuted(filterContext);
    }
}

需要在 SysPageController 头上添加引用:

/// <summary>
/// 拦截器
/// </summary> 
[SysPageFilter] //注解
public class SysPageController : BaseController
{
    //
}

2. 超时登录的JS

当用户登录超时(直接判断Session在不在),需要弹出是否重新登录的提示,只需要抛出一段js就行了,执行的并不是跳转页面,而是触发顶层框架上的退出按钮方法:

//得到重新登录的js
private string GetSysLoginJs()
{
    //确定后执行的js
    string js = "top.window.F.doPostBack({url: 'btnHomePage_Click',disableControl: 'btnHomePage'}); ";
    string conjs = "";
    //如果顶层已经弹出了就不在此弹出了
    conjs += "if(top.$('div.relodeMsg.f-messagebox-alert').length==0){";
    Alert a = new Alert();
    a.CssClass = "relodeMsg";
    a.Message = "登录已过期<br/>点击【确定】跳转到登录页面";
    a.Title = "提示";
    a.OkScript = js;
    a.IconFont = IconFont.Warning;
    a.Target = Target.Top;
    conjs += a.GetShowReference();
    conjs += "}";
    return conjs;
}

3. 是否第一次回发

我还为 HttpRequest 扩展了一个方法,判断是否是 Ajax 回发,如果为真则认为是点击按钮触发的拦截,与打开菜单区分

/// <summary>
/// HttpRequest 扩展
/// </summary>
public static class HttpRequestEx
{
    /// <summary>
    /// 是否是ajax回发
    /// </summary>
    /// <param name="req"></param>
    /// <returns></returns>
    public static bool IsAjax(this HttpRequest req)
    {
        bool result = false;
        //请求头标识
        var xreq = req.Headers.ContainsKey("x-requested-with");
        if (xreq)
        {
            result = req.Headers["x-requested-with"] == "XMLHttpRequest";
        }

        return result;
    }
}

4. 上代码,注意看注释

没有难点,注意看注释

internal class SysPageFilter : ActionFilterAttribute
{
/// <summary>
/// 覆盖
/// </summary>
/// <param name="filterContext"></param>
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
    //得到用户
    var value = filterContext.HttpContext.Session.GetString("LoginUser");
    if (string.IsNullOrEmpty(value))
    {
        string conjs = GetSysLoginJs();
        PageContext.RegisterStartupScript(conjs);
        return;
    }
    JObject _value = JObject.Parse(value);
    Mssystem_1 lodeuser = (Mssystem_1)_value.ToObject(typeof(Mssystem_1));

    //为空时跳转 注意当前页面不是登录页面
    if (filterContext.RouteData.Values.Values.ToList()[1].ToString() != "SysLogin" && lodeuser == null)
    {
        string conjs = GetSysLoginJs();
        PageContext.RegisterStartupScript(conjs);
        return;
    }
    //是否第一次回发, 即加载页面
    if (!filterContext.HttpContext.Request.IsAjax())
    {
        string curMenuId = "";
        //得到当前菜单ID
        curMenuId = filterContext.HttpContext.Request.Query["MenuId"];
        if (!string.IsNullOrEmpty(curMenuId))
        {
            bool b = true;//按钮权限开关,默认开
            //如果是超级管理员,直接跳过权限
            if (lodeuser.isadmin)
            {
                b = false;
            }
            if (b)
            {
                //判断该用户是否有该菜单权限
                if (!lodeuser.menuids.Contains(Convert.ToInt32(curMenuId)))
                {
                    string conjs = GetSysLoginJs();
                    PageContext.RegisterStartupScript(conjs);
                    return;
                }
                //得到数据库中 用户 菜单权限 显示的按钮ID 
                List<string> btnids = BLLsystem_1.GetUserBtnByMenu(lodeuser.sys10.System_10_10, curMenuId, false);
                if (btnids != null)
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (string item in btnids)
                    {
                        //隐藏 也可以执行除隐藏之外的代码
                        sb.Append("if(F.ui." + item + "){F.ui." + item + ".hide();};");
                    }
                    //抛出 
                    PageContext.RegisterStartupScript(sb.ToString());
                }
            }
            //记录日志 用户点击菜单
            BLLsystem_16.ClickMenuLog(lodeuser.System_1_10.ToString(), curMenuId);
        }
    }
    //如果不用是第一次回发 记录点击的按钮
    else
    {
        //加入算法获取MenuId
        string MenuId = "";
        //参数很难获取,谁会赶紧告诉我
        string url = ((HttpRequestHeaders)((DefaultHttpRequest)filterContext.HttpContext.Request).Headers).HeaderReferer;
        string query = url.Split("?")[1];
        foreach (var item in query.Split('&'))
        {
            foreach (var _item in item.Split('='))
            {
                if (_item == "MenuId")
                {
                    MenuId = item.Split('=')[1];
                }
            }
        }
        if (!string.IsNullOrEmpty(MenuId))
        {
            //触发事件名称,由后台判断是否是一个按钮方法
            string streve = filterContext.RouteData.Values.Values.ToList()[2].ToString();
            //记录日志 用户点击按钮
            BLLsystem_16.ButtonLog(lodeuser.System_1_10.ToString(), MenuId, streve);
        }
    }
    base.OnResultExecuted(filterContext);
}
}
日志