zoukankan      html  css  js  c++  java
  • ASP.NET MVC Filters 4种默认过滤器的使用【附示例】

    过滤器(Filters)的出现使得我们可以在ASP.NET MVC程序里更好的控制浏览器请求过来的URL,不是每个请求都会响应内容,只响应特定内容给那些有特定权限的用户,过滤器理论上有以下功能:

    1. 判断登录与否或用户权限
    2. 决策输出缓存
    3. 防盗链
    4. 防蜘蛛
    5. 本地化与国际化设置
    6. 实现动态Action(做权限管理系统的好东西)

    先来看一个简单的例子:新建一个AuthFiltersController,里面有两个Action

    复制代码
    public ActionResult Index()
    {
        return View();
    }
    
    [Authorize]
    public ActionResult Welcome()
    {
        return View();
    }
    复制代码

    很显然,第一个名为Index的Action是没有过滤的,任何身份的请求都可以通过,只要在浏览器的URL栏里键入:localhost:****/AuthFilters/Index 就能得到对应的视图响应;
    而第二个名为Welcome的Action上面标注了[Authorize],表示这是一个只处理那些通过身份验证的URL请求,如果没有通过身份验证就请求这个Action会被带到登录页面。看看配置文件:

    <authentication mode="Forms">
      <forms loginUrl="~/Account/LogOn" timeout="2880" />
    </authentication>

    根据配置文件的定义,登录页面就是AccountController下名为LogOn的Action,那么就新建一个AccountController,并新建两个Action:

    复制代码
    public ActionResult LogOn()
    {
        return View();
    }
    
    [HttpPost]
    public ActionResult LogOn(LogOnViewModel model)
    {
        if (model.UserName.Trim() == model.Password.Trim()) //伪代码,只要输入的用户名和密码一样就过
        {
            if (model.RememberMe)
                FormsAuthentication.SetAuthCookie(model.UserName, true);   //2880分钟有效期的cookie
            else
                FormsAuthentication.SetAuthCookie(model.UserName, false);  //会话cookie
            return RedirectToAction("Welcome", "AuthFilters");
        }
        else
            return View(model);
    }
    复制代码

    第一个是处理Get请求用于响应视图页面的,第二个是处理用户点击提交回发的登录表单。

    LogOnViewModel是用户登录实体类,看具体定义:

    复制代码
    /// <summary>
    /// 用户登录类
    /// </summary>
    public class LogOnViewModel
    {
        /// <summary>
        /// 用户名
        /// </summary>
        public string UserName { get; set; }
    
        /// <summary>
        /// 密码
        /// </summary>
        public string Password { get; set; }
    
        /// <summary>
        /// 记住我
        /// </summary>
        public bool RememberMe { get; set; }
    
    }
    复制代码

    ok,按F6编译下项目,再按Ctrl + F5运行下项目,在URL里输入:localhost:****/AuthFilters/Index 很轻松的得到了Index这个Action的响应

    再定位到:localhost:****/AuthFilters/Welcome

    可见,虽然定位到了Welcome这个Action,但是却并不像Index一样直接返回对应的视图,而是被带到了登录页面。就是因为Welcome这个Action上被标注了[Authorize],拒绝了所以未验证用户的访问。

    既然拒绝了未验证的用户,那就登录下通过验证,看看上面LogOn里写的伪代码就知道,输入相同的用户名和密码就能登录成功,用户名和密码都输入“wangjie”试试:

    已经通过验证并得到Welcome这个Action的响应了。相比之前就是多生成了一个名为“.ASPXAUTH”的Cookie,这是个默认名,配置文件里可以修改。同时,如果登录的时候勾选了“记住我”那么此Cookie的过期时间就是配置文件里定义的2880分钟。

    ok,现在提高下难度,只设置名为“a”、“bb”、“ccc”的用户可以访问欢迎页面:

    复制代码
    [Authorize(Users = "a,bb,ccc")]
    public ActionResult Welcome()
    {
        ViewBag.Message = "已登录";
        return View();
    }
    复制代码

    再用“wangjie”登录下发现跳不到欢迎页面了,因为指定了a、bb、ccc这三个用户才可以登录。
    先不管为何在Action上标注Users = "a,bb,ccc"就可以控制可以访问的用户,但从操作性上来说这样控制Action的访问权限还是很方便的。但是如果项目大,用户对应的角色和权限变化比较大,每次变化都来重新标注Action显然不合适。MVC框架提供的过滤器(Filters)就派上了用场:

    上图是Asp.Net MVC框架提供的几种默认Filter:授权筛选器、操作筛选器、结果筛选器、异常筛选器,下面来一一讲解,先看演示Demo结构图:

    一、授权筛选器

    授权筛选器用于实现IAuthorizationFilter接口和做出关于是否执行操作方法(如执行身份验证或验证请求的属性)的安全决策。 AuthorizeAttribute类和RequireHttpsAttribute类是授权筛选器的示例。授权筛选器在任何其他筛选器之前运行。
    新建一个继承AuthorizeAttribute类的UserAuthorize类,F12定位到AuthorizeAttribute类,看看内部申明:

    复制代码
    public AuthorizeAttribute();
    
    public string Roles { get; set; }
    public override object TypeId { get; }
    public string Users { get; set; }
    
    protected virtual bool AuthorizeCore(HttpContextBase httpContext);
    protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext);
    public virtual void OnAuthorization(AuthorizationContext filterContext);
    protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext);
    复制代码

    上面演示的指定用户才可以访问就是利用了Users属性,并由基类帮助我们验证,只放指定的Users用户通过。要实现自定义的验证只需重写下OnAuthorization和AuthorizeCore方法。为了演示效果,新建一个SampleData类用来初始化数据:

    复制代码
    /// <summary>
    /// 测试数据(实际项目中,这些数据应该从数据库拿)
    /// </summary>
    public class SampleData
    {
        public static List<User> users;
        public static List<Role> roles;
        public static List<RoleWithControllerAction> roleWithControllerAndAction;
    
        static SampleData()
        {
            // 初始化用户
            users = new List<User>(){
                new User(){ Id=1, UserName="wangjie", RoleId=1},
                new User(){ Id=2, UserName ="senior1", RoleId=2},
                new User(){ Id=3, UserName ="senior2", RoleId=2},
                new User(){ Id=5, UserName="junior1", RoleId=3},
                new User(){ Id=6, UserName="junior2", RoleId=3},
                new User(){ Id=6, UserName="junior3", RoleId=3}
            };
            // 初始化角色
            roles = new List<Role>()
            {
                new Role() { Id=1, RoleName="管理员", Description="管理员角色"},
                new Role() { Id=2, RoleName="高级会员", Description="高级会员角色"},
                new Role() { Id=3, RoleName="初级会员", Description="初级会员角色"}
            };
            // 初始化角色控制器和Action对应类
            roleWithControllerAndAction = new List<RoleWithControllerAction>()
            {
                new RoleWithControllerAction(){ Id=1, ControllerName="AuthFilters", ActionName="AdminUser", RoleIds="1"},
                new RoleWithControllerAction(){ Id=2, ControllerName="AuthFilters", ActionName="SeniorUser", 
    Ids="1,2"},
                new RoleWithControllerAction(){ Id=3, ControllerName="AuthFilters", ActionName="JuniorUser", 
    Ids="1,2,3"},
                new RoleWithControllerAction(){ Id=4, ControllerName="ActionFilters", ActionName="Index", RoleIds="2,3"}
            };
        }
    }
    复制代码

    简单明了,用户拥有角色,不同角色可以访问的Action也不同。这比较符合权限项目里的控制。再看看UserAuthorize类的具体定义:

    复制代码
    /// <summary>
    /// 自定义用户授权
    /// </summary>
    public class UserAuthorize : AuthorizeAttribute
    {
        /// <summary>
        /// 授权失败时呈现的视图
        /// </summary>
        public string AuthorizationFailView { get; set; }
    
        /// <summary>
        /// 请求授权时执行
        /// </summary>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            //获得url请求里的controller和action:
            string controllerName = filterContext.RouteData.Values["controller"].ToString().ToLower();
            string actionName = filterContext.RouteData.Values["action"].ToString().ToLower();
            //string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
            //string actionName = filterContext.ActionDescriptor.ActionName;
    
            //根据请求过来的controller和action去查询可以被哪些角色操作:
            Models.RoleWithControllerAction roleWithControllerAction = 
    base.SampleData.roleWithControllerAndAction.Find(r => r.ControllerName.ToLower() == controllerName && 
    tionName.ToLower() == actionName);
            if (roleWithControllerAction != null)
            {
                this.Roles = roleWithControllerAction.RoleIds;     //有权限操作当前控制器和Action的角色id
            }
            base.OnAuthorization(filterContext);   //进入AuthorizeCore
        }
    
        /// <summary>
        /// 自定义授权检查(返回False则授权失败)
        /// </summary>
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext.User.Identity.IsAuthenticated)
            {
                string userName = httpContext.User.Identity.Name;    //当前登录用户的用户名
                Models.User user = Database.SampleData.users.Find(u => u.UserName == userName);   //当前登录用户对象
    
                if (user != null)
                {
                    Models.Role role = Database.SampleData.roles.Find(r => r.Id == user.RoleId);  //当前登录用户的角色
                    foreach (string roleid in Roles.Split(','))
                    {
                        if (role.Id.ToString() == roleid)
                            return true;
                    }
                    return false;
                }
                else
                    return false;
            }
            else
                return false;     //进入HandleUnauthorizedRequest 
        }
    
        /// <summary>
        /// 处理授权失败的HTTP请求
        /// </summary>
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            filterContext.Result = new ViewResult { ViewName = AuthorizationFailView };
        }
    }
    复制代码

    自定义好授权类就可以到控制器上使用了,看看AuthFiltersController类:

    复制代码
    public class AuthFiltersController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    
        //[Authorize(Users = "a,bb,ccc")]
        [Authorize]
        public ActionResult Welcome()
        {
            ViewBag.Message = "普通已授权页面";
            return View();
        }
    
        [UserAuthorize(AuthorizationFailView = "Error")]   //管理员页面
        public ActionResult AdminUser()
        {
            ViewBag.Message = "管理员页面";
            return View("Welcome");
        }
    
        [UserAuthorize(AuthorizationFailView = "Error")]   //会员页面(管理员、会员都可访问)
        public ActionResult SeniorUser()
        {
            ViewBag.Message = "高级会员页面";
            return View("Welcome");
        }
    
        [UserAuthorize(AuthorizationFailView = "Error")]   //游客页面(管理员、会员、游客都可访问)
        public ActionResult JuniorUser()
        {
            ViewBag.Message = "初级会员页面";
            return View("Welcome");
        }
    }
    复制代码

    Welcome这个Action使用了默认的授权验证,只要登陆成功就可以访问。其他几个Action上都标注了自定义的UserAuthorize,并没有标注Users="....",Roles=".....",因为这样在Action上写死用户或者角色控制权限显然是不可行的,用户和角色的对应以及不同的角色可以操作的Action应该是从数据库里取出来的。为了演示就在SampleData类里初始化了一些用户和角色信息,根据SampleData类的定义,很明显wangjie拥有1号管理员角色,可以访问AuthFilters这个控制器下的所有Action,senior1、senior2拥有2号高级会员的角色,可以访问AuthFilters这个控制器下除了AdminUser之外的Action等等
    再次登陆下,就发现拥有高级会员角色的用户senior1是不可以访问AdminUser这个Action,会被带到AuthorizationFailView属性指定的Error视图:

    二、操作筛选器、结果筛选器

    操作筛选器用于实现IActionFilter接口以及包装操作方法执行。IActionFilter接口声明两个方法:OnActionExecuting和OnActionExecuted。OnActionExecuting在操作方法之前运行。OnActionExecuted在操作方法之后运行,可以执行其他处理,如向操作方法提供额外数据、检查返回值或取消执行操作方法。

    结果筛选器用于实现IResultFilter接口以及包装ActionResult对象的执行。IResultFilter接口声明两个方法OnResultExecuting和OnResultExecuted。OnResultExecuting在执行ActionResult对象之前运行。OnResultExecuted在结果之后运行,可以对结果执行其他处理,如修改 HTTP 响应。OutputCacheAttribute 类是结果筛选器的一个示例。

    操作筛选器和结果筛选器都实现ActionFilterAttribute类,看看类里定义的方法:

    public virtual void OnActionExecuted(ActionExecutedContext filterContext);
    public virtual void OnActionExecuting(ActionExecutingContext filterContext);
    public virtual void OnResultExecuted(ResultExecutedContext filterContext);
    public virtual void OnResultExecuting(ResultExecutingContext filterContext);

    根据方法的名字就知道4个方法执行的顺序了:
    OnActionExecuting是Action执行前的操作、OnActionExecuted则是Action执行后的操作、OnResultExecuting是解析ActionResult前执行、OnResultExecuted是解析ActionResult后执行
    即:Action执行前:OnActionExecuting方法先执行→Action执行 →OnActionExecuted方法执行→OnResultExecuting方法执行→返回的ActionRsult中的 executeResult方法执行→OnResultExecuted执行

    完全可以重写OnActionExecuting方法实现上面授权筛选器一样的功能,因为OnActionExecuting方法是在Action方法执行前运行的,自定义一个实现ActionFilterAttribute类的ActionFilters类,OnActionExecuting方法这么写:

    复制代码
    /// <summary>
    /// 在执行操作方法之前由 MVC 框架调用
    /// </summary>
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        string userName = filterContext.HttpContext.User.Identity.Name;    //当前登录用户的用户名
        Models.User user = Database.SampleData.users.Find(u => u.UserName == userName);   //当前登录用户对象
    
        if (user != null)
        {
            Models.Role role = Database.SampleData.roles.Find(r => r.Id == user.RoleId);  //当前登录用户的角色
    
            //获得controller:
            string controllerName = filterContext.RouteData.Values["controller"].ToString().ToLower();
            //string actionName = filterContext.RouteData.Values["action"].ToString().ToLower();
            if (ActionName == null)
                ActionName = filterContext.RouteData.Values["action"].ToString();
    
            //查询角色id
            Models.RoleWithControllerAction roleWithControllerAction = 
    .SampleData.roleWithControllerAndAction.Find(r => r.ControllerName.ToLower() == controllerName && 
    Name.ToLower() == ActionName.ToLower());
            if (roleWithControllerAction != null)
            {
                this.Roles = roleWithControllerAction.RoleIds;     //有权限操作当前控制器和Action的角色id
            }
            if (!string.IsNullOrEmpty(Roles))
            {
                foreach (string roleid in Roles.Split(','))
                {
                    if (role.Id.ToString() == roleid)
                        return;   //return就说明有权限了,后面的代码就不跑了,直接返回视图给浏览器就好
                }
            }
            filterContext.Result = new EmptyResult();   //请求失败输出空结果
            HttpContext.Current.Response.Write("对不起,你没有权限!");   //打出提示文字
            //return;
        }
        else
        {
            //filterContext.Result = new ViewResult { ViewName = "Error" };
            filterContext.Result = new EmptyResult();
            HttpContext.Current.Response.Write("对不起,请先登录!");
            //return;
        }
        //base.OnActionExecuting(filterContext);
    }
    复制代码

    看看如何在ActionFiltersController控制器里使:

    复制代码
    public class ActionFiltersController : Controller
    {
        [ActionFilters]
        public ActionResult Index()
        {
            return View();
        }
    
        [ActionFilters(ActionName = "Index")]
        public ActionResult Details()
        {
            return View();
        }
    
        [ActionFilters]
        public ActionResult Test()
        {
            return View();
        }
    }
    复制代码

    很明显Index和Details这两个Action同用一个权限,看看初始化数据SampleData类的定义:

    new RoleWithControllerAction(){ Id=4, ControllerName="ActionFilters", ActionName="Index", RoleIds="2,3"}

    只有2和3号角色可以访问,那么1号角色的wangjie用户应该是访问不了的,登录试试:

    三、异常筛选器

    异常筛选器用于实现IExceptionFilter接口,并在ASP.NET MVC管道执行期间引发了未处理的异常时执行。异常筛选器可用于执行诸如日志记录或显示错误页之类的任务。HandleErrorAttribute类是异常筛选器的一个示例。

    有之前授权筛选器、操作和结果筛选器的使用经验,再看异常筛选器就简单许多了,来看看自定义的继承自HandleErrorAttribute类的异常筛选类ExceptionFilters:

    复制代码
    /// <summary>
    /// 异常筛选器
    /// </summary>
    public class ExceptionFilters : HandleErrorAttribute
    {
        /// <summary>
        /// 在发生异常时调用
        /// </summary>
        public override void OnException(ExceptionContext filterContext)
        {
            //if (!filterContext.ExceptionHandled && filterContext.Exception is NullReferenceException)
            if (!filterContext.ExceptionHandled)
            {
                //获取出现异常的controller名和action名,用于记录
                string controllerName = (string)filterContext.RouteData.Values["controller"];
                string actionName = (string)filterContext.RouteData.Values["action"];
                //定义一个HandErrorInfo,用于Error视图展示异常信息
                HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
    
                ViewResult result = new ViewResult
                {
                    ViewName = this.View,
                    ViewData = new ViewDataDictionary<HandleErrorInfo>(model)  //定义ViewData,泛型
                };
                filterContext.Result = result;
                filterContext.ExceptionHandled = true;
            }
            //base.OnException(filterContext);
        }
    }
    复制代码

    看看如何在视图中使用:

    [ExceptionFilters(View = "Exception")]
    public ActionResult Index()
    {
        throw new NullReferenceException("测试抛出异常!");
    }

    View是制定的捕获异常后显示给用户的视图:

    再看一个Action:

    复制代码
    [ExceptionFilters(View = "ExceptionDetails")]
    public ActionResult Details()
    {
        int i = int.Parse("hello,world!");
        return View();
    }
    复制代码

    把string类型的数据强转int,肯定得报FormatException异常,看看ExceptionDetails视图如何定义的:

    复制代码
    @model System.Web.Mvc.HandleErrorInfo
    @{
        Layout = null;
    }
    <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>异常</title>
    </head>
    <body>
        <p>
            抛错控制器:<b>@Model.ControllerName</b> 抛错方法:<b>@Model.ActionName</b> 抛错类型:<b>@Model.Exception.GetType
    
    ().Name</b>
        </p>
        <p>
            异常信息:<b>@Model.Exception.Message</b>
        </p>
        <p>
            堆栈信息:</p>
        <pre>@Model.Exception.StackTrace</pre>
    </body>
    </html>
    复制代码

    浏览器显示结果:

    感谢阅读,如果觉得还不错,请不吝给我点个“赞”,谢谢。

    本文源码

    睿备份 www.i-bak.com 1 / 7 睿备份 软件功能规格表 版本信息: 软件版本:V4.1.8,发布时间:2019/1/3 文档修订: 2018/1/3 增加“V4.1.8”新功能说明。 2018/12/06 增加“V4.1.7”新功能说明。 2018/12/04 增加“推荐运行环境”说明。 2018/11/30 修订文档中的相关名词,增加相应注释信息。 2018/11/29 文档发布。 一、 软件运行环境 1、 基本运行环境 类型 名称 版本 CPU 架构 操作系统 Windows Desktop XP SP3 及以上注 1 x64,x86 Windows Server 2003 SP4 及以上注 2 x64,x86 系统环境 .NET Framework 4.0 及以上 x64,x86 Microsoft Visual C++ 2017 x64,x86 注: 1、 使用“本地文件备份强力复制”功能,Windows Desktop 操作系统需 Winodws Vista 及以上。 2、 使用“本地文件备份强力复制”功能,Windows Server 操作系统需 Winodws 2008 及以上。 2、 推荐运行环境 类型 名称 版本 CPU 架构 操作系统 Windows Desktop Vista 及以上 x64 Windows Server 2008R2 及以上 x64 系统环境 .NET Framework 4.5.2 及以上 x64 Microsoft Visual C++ 2017 x64 睿备份 www.i-bak.com 2 / 7 二、 数据库备份支持 1、 Microsoft SQL Server 注 1 版本 备份方式 备份类型 本地 远程 完整 差异 事物日志 2000 ● ● ● ● ● 2005 ● ● ● ● ● 2008 ● ● ● ● ● 2008R2 ● ● ● ● ● 2012 ● ● ● ● ● 2014 ● ● ● ● ● 2016 注 2 ● ● ● ● ● 2017 ● ● ● ● ● 注: 1、 同时支持各版本 Microsoft SQL Server 数据库的“Express”版本。 2、 支持从 Microsoft SQL Server 2016 开始增加的 Linux 版本数据库。 2、 Oracle 版本 备份方式 备份类型 本地 远程 完整 差异增量 累积增量 8i ● ● ● ● ● 9i ● ● ● ● ● 10g ● ● ● ● ● 11g ● ● ● ● ● 12c ● ● ● ● ● 18c ● ● ● ● ● 3、 MySQL 睿备份 www.i-bak.com 3 / 7 版本 备份方式 备份类型 本地 远程 完整 差异 增量 4.1 ● ● ● ━ ━ 5 系列 ● ● ● ━ ━ 8.0 ● ● ● ━ ━ 4、 DM(达梦) 版本 备份方式 备份类型 本地 远程 完整 增量 累积增量 DM6 ● ● ● ● ● DM7 ● ● ● ● ● DMETL ● ● ● ● ● 5、 PostgreSQL 版本 备份方式 备份类型 本地 远程 完整 差异 增量 9 系列 ● ● ● ━ ━ 10 系列 ● ● ● ━ ━ 11.1 ● ● ● ━ ━ 6、 MongoDB 版本 备份方式 备份类型 本地 远程 完整 差异 增量 2.6 ● ● ● ━ ━ 3 系列 ● ● ● ━ ━ 4.0 ● ● ● ━ ━ 7、 Kingbase(金仓) 版本 备份方式 备份类型 睿备份 www.i-bak.com 4 / 7 本地 远程 完整 差异 增量 KingbaseES V7 ● ● ● ━ ━ 三、 文件备份支持 备份方式 强力复制 备份类型 完整 差异 增量 本地 ● ● ● ● 网络 ━ ● ● ● FTP ━ ● ━ ━ SFTP ━ ● ━ ━ 四、 版本功能对照表 功能 免费版 专业版 数 据 库 备 份 MSSQL 完整备份 ● ● 差异备份 ━ ● 事物日志备份 ━ ● ORACLE 完整备份 ● ● 差异增量备份 ━ ● 累积增量备份 ━ ● MySQL 完整备份 ● ● 达梦 完整备份 ● ● 增量备份 ━ ● 累积增量备份 ━ ● PostgreSQL 完整备份 ● ● MongoDB 完整备份 ● ● 金仓 完整备份 ● ● 文 件 备 本地 完整备份 ● ● 差异备份 ━ ● 增量备份 ━ ● 睿备份 www.i-bak.com 5 / 7 份 网络(UNC) 完整备份 ● ● 差异备份 ━ ● 增量备份 ━ ● FTP 完整备份 ━ ● SFTP 完整备份 ━ ● 任务 执行 依据计划周期自动执行 ● ● 移动存储插入感应执行 ━ ● 备 份 存 储 移动存储 ━ ● 睿存储 ○注 1 ● 网络(UNC)存储 ● ● FTP 存储 ━ ● SFTP 存储 ━ ● 云存储 七牛云存储 ● ● 阿里云 OSS ━ ● 数 据 恢 复 MSSQL ● ● MySQL ━ ● PostgreSQL ━ ● MongoDB ━ ● 日志 信息 备份日志查阅 ○注 2 ● 备份日志导出 ━ ● 高 级 功 能 备份 远程数据库 不回传,仅在远程留存 ● ● 通过网络(UNC)回传 ● ● 通过 FTP 回传 ━ ● 通过 SFTP 回传 ━ ● 压缩与加密 7Z 压缩 ● ● 加密 ━ ● ZIP 压缩 ● ● 加密 ━ ● 睿备份 www.i-bak.com 6 / 7 自动删除 删除指定日期前的备份 ● ● 保留指定数量的备份 ━ ● 软件登陆与锁定密码 ━ ● 本地文件备份强力复制技术 ━ ● Email 发送备份信息 ● ● 当前执行任务数量跟踪 ○注 3 ● 任务逾期后,依据计划周期推算 ━ ● MSSQL“仅复制备份”技术 ━ ● 备份执行过程中对数据库压缩 ━ ● 关键时刻“云任务”技术 ━ ● 自主定义相关数据库的 DUMP 执行文件注 4 ━ ● 扩 展 工 具 备份文件管理 ○注 5 ● 历次备份数据增量分析 ○注 6 ● 网络远程唤醒计算机 ● ● MSSQL 日志清理 ● ● 系统服务重启 ● ● 服 务 QQ 群、Email ● ● 远程协助 ○注 7 ● 专属 QQ、电话 ━ ● 注: 1、 仅可试用 60 天《睿存储》全功能版。 通过《睿存储》,可以在多类主流操作系统及集群应用平台中,快速建立私有云存储体系。通过安全、 高效、可控的开放式通讯接口,实现对各类数据资源的统一化存储与管理。有效提升企业信息系统的 投资回报率,抵御各类文件损坏/丢失风险,全面保障企业数据资产安全!详见:pcs.i-bak.com 2、 在“日志-文件备份-文件详情”中,仅可查阅前 50 条文件备份详细信息。 3、 在“首页”中,仅可查阅到当前正在执行的任务数量,而无法查看任务的详细信息。 睿备份 www.i-bak.com 7 / 7 4、 用以实现对目标数据库个性化的数据备份。Oracle、Mysql、PostgreSQL、MongoDB 数据库可分别自主 定义:rman.exe、mysqldump.exe、pg_dump.exe、mongodump.exe 执行文件所在的地址。 5、 在“工具-备份文件管理工具”中,不能查阅 15 天前的备份文件信息。 6、 在“工具-历史备份数据增量分析”中,不能对 15 天的备份信息进行分析,并且不能导出分析数据。 7、 仅限特定情况的下的远程协助,如:潜在的 BUG 故障分析。

  • 相关阅读:
    一提黄金肯定就是西方的货币史
    封装QtCore(在非Qt项目里使用QString,QJson,QFileInfo,QFile等类)
    Qt 自定义事件(三种方法:继承QEvent,然后Send Post就都可以了,也可以覆盖customEvent函数,也可覆盖event()函数)
    MAC 设置环境变量path的几种方法
    深入Qt 学习 -- 反射机制(比较简单清楚)
    排序
    寄存器,cache、伙伴系统、内存碎片、段式页式存储管理
    NET Core项目
    消息队列
    RedisHelper
  • 原文地址:https://www.cnblogs.com/Jeely/p/10953372.html
Copyright © 2011-2022 走看看