Asp.net MVC 权限过滤器实现方法的最佳实践
https://www.cnblogs.com/hnsongbiao/p/5087359.html
在项目开发中,为了安全、方便地判断用户是否有访问当前资源(Action)的权限,我们一般通过全局过滤器来实现。
Asp.net MVC 页面中常见的权限判断使用过滤器主要在以下几种情况(根据权限判断的先后顺序):
1、判断要访问的Controller或Action是可以匿名访问;
2、判断要访问的Controller或Action是否登录就可以访问;
3、判断是否有访问某个Controller的Action的权限;
4、资源访问权限,如在下拉菜单中获取当前账号可以显示几个下拉项;
通过在全局过滤器中逐项判断,我们可以让有权限的用户顺利通过,没有权限的就会被禁止掉,下面来看看过滤器的代码实现:
    public class CheckPermissionFilter : IAuthorizationFilter
    {
        /// <summary>
        /// 权限判断
        /// </summary>
        /// <param name="filterContext"></param>
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }
            if (filterContext.HttpContext.Request.Url == null)
            {
                throw new ArgumentNullException("filterContext");
            }
            string pageUrl = filterContext.HttpContext.Request.Url.AbsolutePath; //OperateContext.GetThisPageUrl(false);
            // 是否是Ajax请求
            var bAjax = filterContext.HttpContext.Request.IsAjaxRequest();
            // 1、允许匿名访问 用于标记在授权期间要跳过 AuthorizeAttribute 的控制器和操作的特性 
            var actionAnonymous = filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), true) as IEnumerable<AllowAnonymousAttribute>;
            var controllerAnonymous = filterContext.Controller.GetType().GetCustomAttributes(typeof(AllowAnonymousAttribute), true) as IEnumerable<AllowAnonymousAttribute>;
            if ((actionAnonymous != null && actionAnonymous.Any()) || (controllerAnonymous != null && controllerAnonymous.Any()))
            {
                return;
            }
            // 判断是否登录或登录已超时 需要重新登录
            if (Infrastructure.OperateContext.Current.UserInfo == null)
            {
                if (bAjax)
                {
                    BusinessResultBase result = new BusinessResultBase();
                    result.Title = "未登录或登录已超时";
                    result.Status = false;
                    result.StatusCode = BusinessStatusCode.LoginTimeOut.ToString();
                    result.StatusMessage = "请重新登录系统。";
                    var jsonResult = new JsonResult();
                    jsonResult.Data = result;
                    filterContext.Result = jsonResult;
                }
                else
                {
                    filterContext.Result = new RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary(new { Controller = "Account", action = "Login" }));
                }
            }
            else
            {
                // 2、拒绝某个账号登录当前系统
                if (OperateContext.Current.IsDenyVisit())
                {
                    if (bAjax)
                    {
                        BusinessResultBase result = new BusinessResultBase();
                        result.Title = "拒绝访问当前系统";
                        result.Status = false;
                        result.StatusCode = BusinessStatusCode.AccessDeny.ToString();
                        result.StatusMessage = "您的账号不允许访问当前系统。";
                        var jsonResult = new JsonResult();
                        jsonResult.Data = result;
                        filterContext.Result = jsonResult;
                    }
                    else
                    {
                        filterContext.Result = new RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary(new { Controller = "Common", action = "DenyAccess", bAjaxReq = false, message = "没有获取您拥有的权限菜单,请尝试重新登录。" }));
                    }
                }
                else
                {
                    // 3、判断登录状态 Controller  Action 标签 某些功能只需判断是否登录 用户没登录 调到登录页面  
                    // 判断Controller上是否有CheckLoginAttribute标签 只需要登录就可以访问
                    var checkLoginControllerAttr = filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(CheckLoginAttribute), true) as IEnumerable<CheckLoginAttribute>;
                    if (checkLoginControllerAttr != null && checkLoginControllerAttr.Any())
                    {
                        return;
                    }
                    // 判断action上是否有CheckLoginAttribute标签 只需要登录就可以访问
                    var checkLoginActionAttr = filterContext.ActionDescriptor.GetCustomAttributes(typeof(CheckLoginAttribute), true) as IEnumerable<CheckLoginAttribute>;
                    if (checkLoginActionAttr != null && checkLoginActionAttr.Any())
                    {
                        return;
                    }
                    // 4、有些要判断是否有某个菜单 action的权限 具体判断某个用户是否有某个权限
                    // 用于标记在授权期间需要CustomerResourceAttribute 的操作的特性
                    var attNames = filterContext.ActionDescriptor.GetCustomAttributes(typeof(CustomerResourceAttribute), true) as IEnumerable<CustomerResourceAttribute>;
                    // 用户具有的菜单
                    var moduleList = OperateContext.Current.GetPermissionList();
                    if (moduleList == null || !moduleList.Any())
                    {
                        if (bAjax)
                        {
                            BusinessResultBase result = new BusinessResultBase();
                            result.Title = "没有访问权限";
                            result.Status = false;
                            result.StatusCode = BusinessStatusCode.AccessDeny.ToString();
                            result.StatusMessage = "没有获取您拥有的权限菜单,请尝试重新登录。";
                            var jsonResult = new JsonResult();
                            jsonResult.Data = result;
                            filterContext.Result = jsonResult;
                        }
                        else
                        {
                            filterContext.Result = new RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary(new { Controller = "Common", action = "DenyAccess", bAjaxReq = false, message = "没有获取您拥有的权限菜单,请尝试重新登录。" }));
                        }
                    }
                    else
                    {
                        // 判断用户的权限菜单中的code是否与控制器上标示的资源的code一致
                        var joinResult = (from aclEntity in moduleList
                                          join attName in attNames on aclEntity.Code equals attName.ResourceName
                                          select attName).Any();
                        if (!joinResult)
                        {
                            if (bAjax)
                            {
                                BusinessResultBase result = new BusinessResultBase();
                                result.Title = "没有访问权限";
                                result.Status = false;
                                result.StatusCode = BusinessStatusCode.AccessDeny.ToString();
                                result.StatusMessage = "您没有访问权限:" + pageUrl;
                                var jsonResult = new JsonResult();
                                jsonResult.Data = result;
                                filterContext.Result = jsonResult;
                            }
                            else
                            {
                                filterContext.Result = new RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary(new { Controller = "Common", action = "DenyAccess", bAjaxReq = false, message = "您没有访问权限:" + pageUrl }));
                            }
                        }
                        else
                        {
                            return;
                        }
                    }
                }
            }
        }
    }
基于这样的过滤器,我们的Controller和Action该怎么写呢?下面分别举出几个demo
1、匿名访问的Controller,这是一个测试安装环境中数据库连接是否连通的功能:
    /// <summary>
    /// InstallationController
    /// 
    /// 安装环境测试
    /// 
    /// 2015-12-25 版本:1.0 SongBiao 创建文件。
    /// 
    /// <author>
    ///     <name>SongBiao</name>
    ///     <date>2015-12-25</date>
    /// </author>
    /// </summary>
    [AllowAnonymous]
    public class InstallationController : Controller
    {
        //
        // GET: /InstallationEnvironment/
        public ActionResult Index()
        {
            string result;
            try
            {
                // 获取数据库时间 测试数据库是否通
                using (IDbHelper dbHelper = DbHelperFactory.GetHelper(BaseSystemInfo.UserCenterDbType, BaseSystemInfo.UserCenterDbConnection))
                {
                    result ="数据库已连通,当前数据库时间:"+ DateTime.Parse(dbHelper.GetDbDateTime()).ToString(BaseSystemInfo.DateTimeFormat);
                }
            }
            catch (Exception ex)
            {
                result="数据库连接异常:"+ex.Message;
            }
            ViewBag.Result = result;
            return View();
        }
    }
这个头部增加了AllowAnonymous标签,实现匿名访问功能,用户不需登录即可访问。
2、只需要登录就可以访问的功能
namespace DotNet.MVC.Controllers
{
    using DotNet.Business;
    using DotNet.Model;
    using DotNet.MVC.Attributes;
    using DotNet.MVC.Infrastructure;
    /// <summary>
    /// 系统菜单权限
    /// 
    /// 修改纪录
    /// 
    /// 2015-09-09 版本:1.0 SongBiao 创建文件。
    /// 
    /// <author>
    ///     <name>SongBiao</name>
    ///     <date>2015-09-09</date>
    /// </author>
    /// </summary>
    [CheckLogin]
    public class ItemsSystemController : BaseController
    {
        //
        // GET: /ItemsSystem/
        public ActionResult Index()
        {
            return View();
        }
        /// <summary>
        /// 返回全部子系统下拉列表数据
        /// </summary>
        /// <returns></returns>
        public ActionResult GetSystemSelect()
        {
            string tableName = "ItemsSystem";
            Hashtable hashTable = new Hashtable();
            List<BaseItemDetailsEntity> list = null;
            var itemDetailsManager = new BaseItemDetailsManager(UserCenterDbHelper, UserInfo, tableName);
            // 管理员取得所有数据
            if (UserInfo.IsAdministrator)
            {
               list= itemDetailsManager.GetList<BaseItemDetailsEntity>(new KeyValuePair<string, object>(BaseItemDetailsEntity.FieldDeletionStateCode, 0)
                    , BaseItemDetailsEntity.FieldSortCode);
            }
            else
            {
                string permissionCode = "Resource.ManagePermission";
                BasePermissionScopeManager permissionScopeManager = new BasePermissionScopeManager(UserCenterDbHelper, UserInfo);
                string[] ids = permissionScopeManager.GetResourceScopeIds(UserInfo.Id, tableName, permissionCode);
                list = itemDetailsManager.GetList<BaseItemDetailsEntity>(ids);
            }
            if (list != null && list.Any())
            {
                var result = (from p in list select new { key = p.ItemName, value = p.ItemValue }).ToList();
                hashTable.Add("list", result);
            }
            else
            {
                hashTable.Add("list", null);
            }
            return Json(hashTable, JsonRequestBehavior.AllowGet);
        }
    }
}
这里在控制器上使用 CheckLogin 标签来实现只要用户登录就可以访问当前控制器里的Action,当然也可以指定Controller下某个Action只要登录就可以访问,如下写法
        #region  public ActionResult LogOff() 退出
        /// <summary>
        /// 退出
        /// </summary>
        /// <returns></returns>
        [CheckLogin]
        public ActionResult LogOff()
        {
            try
            {
                OperateContext.Current.RemoveCurrent();
                return RedirectToAction("Login", "Account");
            }
            catch (Exception)
            {
                return RedirectToAction("Login", "Account");
            }
        } 
        #endregion
那么,上面的CheckLogin怎么写呢?请看如下实现(OperateContext.Current.UserInfo是我实现的上下文中获取当前用户的方法,Views层也可以使用)。
namespace DotNet.MVC.Attributes
{
    using DotNet.MVC.Infrastructure;
    /// <summary>
    /// CheckLoginAttribute
    /// 用于检测用户是否处于登录状态的标签
    /// 某些功能只需要用户登录就可以使用
    /// 
    /// 修改纪录
    /// 
    /// 2015-10-11 版本:1.0 SongBiao 创建文件。   
    /// 
    /// <author>
    ///     <name>SongBiao</name>
    ///     <date>2015-10-11</date>
    /// </author>
    /// </summary>
    public class CheckLoginAttribute :System.Web.Mvc.AuthorizeAttribute //AuthorizeAttribute
    {
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            bool pass = false;
            // httpContext.Session[DotNet.Business.Utilities.SessionName]
            //!httpContext.Request.IsAuthenticated
            if (OperateContext.Current.UserInfo==null)
            {
                httpContext.Response.StatusCode = 401;//无权限状态码
                pass = false;
            }
            else
            {
                pass = true;
            }
            return pass;
        }
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            base.HandleUnauthorizedRequest(filterContext);
            if (filterContext.HttpContext.Response.StatusCode == 401)
            {
                filterContext.Result = new RedirectResult("/Account/Login");
            }
        }
    }
}
3、判断是否具有某个Action的权限
        /// <summary>
        /// 获取列表数据
        /// </summary>
        /// <param name="quoteId"></param>
        /// <param name="pager"></param>
        /// <param name="sort"></param>
        /// <param name="direction"></param>
        /// <param name="firstHaveData"></param>
        /// <returns></returns>
        [AjaxRequest]
        [CustomerResource("XpressionList")]
        public ActionResult GetList(string quoteId, QuiGridPager pager, string sort, string direction, bool firstHaveData = true)
        {
            XpressionManager xpressionManager = new XpressionManager(BusinessDbHelper, UserInfo);
            List<XpressionEntity> list = xpressionManager.ExecuteReaderByPage(quoteId, pager, sort, direction, "*", firstHaveData).ToList<ZtoQuoteExpressionEntity>();
            return JsonQuiGridPager(pager, list, pager.totalRows, sort, direction, StartTime, firstHaveData);
        }
通过在Action 上添加标签[CustomerResource("XpressionList")]实现,在过滤去中会自动去判断当前账号是否具有这个Action的访问权限,这个标签的实现如下,
namespace DotNet.MVC.Attributes
{
    /// <summary>
    /// CustomerResourceAttribute
    /// 
    /// 自定义的对方法应用的属性,在Action上标注权限菜单对应的Code
    /// 
    /// 修改纪录
    /// 
    /// 2015-10-11 版本:1.0 SongBiao 创建文件。   
    /// 
    /// <author>
    ///     <name>SongBiao</name>
    ///     <date>2015-10-11</date>
    /// </author>
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
    public sealed class CustomerResourceAttribute : Attribute
    {
        private readonly string _resourceName;
        public CustomerResourceAttribute(string resourceName)
        {
            _resourceName = resourceName;
        }
        /// <summary>
        /// 资源名称
        /// </summary>
        public string ResourceName
        {
            get { return _resourceName; }
        }
        /// <summary>
        /// 资源描述
        /// </summary>
        public string Descript { get; set; }
    }
}
这里CustomerResourceAttribute是实现权限细分判断的关键点,在权限配置中,我们把每一个Action都存储到数据库中,实现界面(B/S)
通过Code实现当前用户是否具有该权限(当然也可以通过ID),Code实现了不可重复的检查。
目前这个过滤器底层使用了通用权限管理系统,主要用于权限菜单的存储及判断,数据库及功能设计上完全考虑到了各种形式的判断(按用户、公司、角色)。结合Asp.net MVC,轻轻松松就实现了权限过滤器功能。开发人员只需要会配置系统菜单及系统角色,通过接口或底层dll完全就可以了,开发人员只需关注业务功能的实现。
其它语言,如有类似权限判断全局访问过滤器的功能,也可参照实现。
对以上功能,如有疑问,欢迎一起探讨~~~
根据园友“wzmzang”的需求,提供OperateContext源码,大家参考~~
 
namespace DotNet.MVC.Infrastructure { using DotNet.MVC.Infrastructure.Caching; using DotNet.Utilities; using DotNet.Model; using DotNet.Business; using DotNet.MVC.Models; /// <summary> /// OperateContext /// /// 上下文 /// /// 修改纪录 /// /// 2015-09-13版本:1.0 SongBiao 创建文件。 /// /// <author> /// <name>SongBiao</name> /// <date>2015-4-13</date> /// </author> /// </summary> public class OperateContext { /// <summary> /// 秘钥 /// </summary> private string LoginUserKey = "LoginUserKey"; /// <summary> /// 登陆提供者模式:Session、Cookie /// </summary> private string LoginProvider = BusinessSystemInfo.LoginProvider; #region public static OperateContext Current 获取当前 操作上下文 /// <summary> /// 获取当前 操作上下文 (为每个处理浏览器请求的服务器线程 单独创建 操作上下文) /// </summary> public static OperateContext Current { get { OperateContext oContext = CallContext.GetData(typeof(OperateContext).Name) as OperateContext; if (oContext == null) { oContext = new OperateContext(); CallContext.SetData(typeof(OperateContext).Name, oContext); } return oContext; } } #endregion #region 增加的子系统之间跳转认证的code /// <summary> /// 生成Code /// </summary> /// <param name="openid">openid</param> /// <param name="key">向谁跳传谁规定的key</param> /// <returns></returns> public static string MakeCode(string openid, string key) { DateTime time = DateTime.Now; string data = time.ToString("dd") + "_" + openid + "_" + time.ToString("yyyy") + "_" + key + "_" + time.ToString("MM"); MD5 md5 = new MD5CryptoServiceProvider(); byte[] result = Encoding.Default.GetBytes(data); byte[] output = md5.ComputeHash(result); data = BitConverter.ToString(output).Replace("-", "").ToLower(); SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); byte[] bytes = sha1.ComputeHash(Encoding.ASCII.GetBytes(data));//"596d42faf5710b35c7ea0f0a9600ee31" F69D39E1CA07FC23C1CE62F549E9D5B9780 //转16进制 清除前面0 StringBuilder strB = new StringBuilder(); for (int i = 0; i < bytes.Length; i++) { string strX2 = bytes[i].ToString("X2"); if (strX2.Substring(0, 1) == "0") { strX2 = strX2.Substring(1, 1); } strB.Append(strX2); } return strB.ToString(); } /// <summary> /// Code验证 /// </summary> /// <param name="openid">openid</param> /// <param name="code">待验证的数据</param> /// <param name="key">自己系统规定的key</param> /// <returns></returns> public static bool ValidateCode(string openid, string code, string key) { string signedData = MakeCode(openid, key); return code.Equals(signedData, StringComparison.OrdinalIgnoreCase); } #endregion public BaseUserInfo _userInfo = null; /// <summary> /// 获取当前用户 /// </summary> /// <returns></returns> public BaseUserInfo UserInfo { get { try { if (string.Equals(LoginProvider, "Cookie", StringComparison.OrdinalIgnoreCase)) { if (!string.IsNullOrWhiteSpace(CookieHelper.GetCookie(LoginUserKey))) { _userInfo = JsonConvert.DeserializeObject<BaseUserInfo>(SecretUtil.Decrypt(CookieHelper.GetCookie(LoginUserKey))); } } else { if (SessionHelper.Get(LoginUserKey) != null) { _userInfo = JsonConvert.DeserializeObject<BaseUserInfo>(SecretUtil.Decrypt(SessionHelper.Get(LoginUserKey).ToString())); } } return _userInfo; } catch { throw new Exception("登录信息超时,请重新登录。"); } } set { _userInfo = value; } } #region Http上下文 及 相关属性 /// <summary> /// Http上下文 /// </summary> HttpContext ContextHttp { get { return HttpContext.Current; } } /// <summary> /// 输出对象 /// </summary> HttpResponse Response { get { return ContextHttp.Response; } } /// <summary> /// 请求对象 /// </summary> HttpRequest Request { get { return ContextHttp.Request; } } /// <summary> /// Session对象 /// </summary> System.Web.SessionState.HttpSessionState Session { get { return ContextHttp.Session; } } #endregion #region public void AddCurrent(BaseUserInfo userInfo) 写入登录信息 /// <summary> /// 写入登录信息 /// </summary> /// <param name="userInfo">成员信息</param> public void AddCurrent(BaseUserInfo userInfo) { try { userInfo.SystemCode = BaseSystemInfo.SystemCode; if (LoginProvider == "Cookie") { CookieHelper.WriteCookie(LoginUserKey, SecretUtil.Encrypt(JsonConvert.SerializeObject(userInfo)), 1440); } else { SessionHelper.Add(LoginUserKey, SecretUtil.Encrypt(JsonConvert.SerializeObject(userInfo))); } //清除上一次的 ICacheManager cacheManager = new MemoryCacheManager(); cacheManager.Clear(); } catch (Exception ex) { throw new Exception(ex.Message); } } #endregion #region public void RemoveCurrent() 删除登录信息 /// <summary> /// 删除登录信息 /// </summary> public void RemoveCurrent() { if (LoginProvider == "Cookie") { HttpCookie objCookie = new HttpCookie(LoginUserKey.Trim()); objCookie.Expires = DateTime.Now.AddYears(-5); ContextHttp.Response.Cookies.Add(objCookie); } else { SessionHelper.Remove(LoginUserKey.Trim()); } ICacheManager cacheManager = new MemoryCacheManager(); cacheManager.Clear(); } #endregion #region public bool IsOverdue() 是否过期 /// <summary> /// 是否过期 /// </summary> /// <returns></returns> public bool IsOverdue() { object str = ""; if (LoginProvider == "Cookie") { str = CookieHelper.GetCookie(LoginUserKey); } else { str = SessionHelper.Get(LoginUserKey); } if (str != null && str.ToString() != "") { return true; } else { return false; } } #endregion #region public bool IsStaticResource() 是否是访问静态资源 /// <summary> /// public bool IsStaticResource() 是否是访问静态资源 /// </summary> /// <returns></returns> public bool IsStaticResource() { if (ContextHttp == null) throw new ArgumentNullException("request"); string path = ContextHttp.Request.Path; string extension = VirtualPathUtility.GetExtension(path); if (extension == null) return false; switch (extension.ToLower()) { case ".axd": case ".ashx": case ".bmp": case ".css": case ".gif": case ".htm": case ".html": case ".ico": case ".jpeg": case ".jpg": case ".js": case ".png": case ".rar": case ".zip": return true; } return false; } #endregion #region public string ServerVariables(string name) 获取服务器端变量 /// <summary> /// Gets server variable by name /// </summary> /// <param name="name">Name</param> /// <returns>Server variable</returns> public string ServerVariables(string name) { string result = string.Empty; try { if (ContextHttp == null || ContextHttp.Request == null) return result; //put this method is try-catch //as described here http://www.nopcommerce.com/boards/t/21356/multi-store-roadmap-lets-discuss-update-done.aspx?p=6#90196 if (ContextHttp.Request.ServerVariables[name] != null) { result = ContextHttp.Request.ServerVariables[name]; } } catch { result = string.Empty; } return result; } #endregion #region public static string GetClientIP() 获取客户端的IP地址 /// <summary> /// 获取客户端的IP地址 /// </summary> /// <returns></returns> public static string GetClientIP() { string result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; if (!string.IsNullOrEmpty(result)) { //可能有代理 if (result.IndexOf(".", StringComparison.Ordinal) == -1) //没有"."肯定是非IPv4格式 result = null; else { if (result.IndexOf(",", StringComparison.Ordinal) != -1) { //有",",估计多个代理。取第一个不是内网的IP。 result = result.Replace(" ", "").Replace("", ""); string[] temparyip = result.Split(",;".ToCharArray()); for (int i = 0; i < temparyip.Length; i++) { if (IsIPAddress(temparyip[i]) && temparyip[i].Substring(0, 3) != "10." && temparyip[i].Substring(0, 7) != "192.168" && temparyip[i].Substring(0, 7) != "172.16.") { return temparyip[i];//找到不是内网的地址 } } } else if (IsIPAddress(result)) //代理即是IP格式 return result; else result = null;//代理中的内容 非IP,取IP } } string ipAddress = (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null && HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != String.Empty) ? HttpContext.Current.Request.ServerVariables ["HTTP_X_FORWARDED_FOR"] : HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; if (string.IsNullOrEmpty(result)) result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; if (string.IsNullOrEmpty(result)) result = HttpContext.Current.Request.UserHostAddress; return result; } /// <summary> /// ip判断 /// </summary> /// <param name="str1"></param> /// <returns></returns> private static bool IsIPAddress(string str1) { if (string.IsNullOrEmpty(str1) || str1.Length < 7 || str1.Length > 15) return false; string regformat = @"^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$"; Regex regex = new Regex(regformat, RegexOptions.IgnoreCase); return regex.IsMatch(str1); } #endregion /// <summary> /// 解决Error"基础连接已经关闭: 未能为SSL/TLS 安全通道建立信任关系。" /// </summary> /// <param name="sender"></param> /// <param name="certificate"></param> /// <param name="chain"></param> /// <param name="sslPolicyErrors"></param> /// <returns></returns> private static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; } /// <summary> /// 业务库连接 /// </summary> public static IDbHelper BusinessDbHelper { get { return DbHelperFactory.GetHelper(BaseSystemInfo.BusinessDbType, BaseSystemInfo.BusinessDbConnection); } } /// <summary> /// 用户中心库连接 /// </summary> public static IDbHelper UserCenterDbHelper { get { return DbHelperFactory.GetHelper(BaseSystemInfo.UserCenterDbType, BaseSystemInfo.UserCenterDbConnection); } } } }
如果您认为这篇文章还不错或者有所收获,您可以通过右边的“打赏”功能 打赏我一杯咖啡【物质支持】,也可以点击文章下方“推荐”按钮【精神支持】,您的“推荐”将是我最大的写作动力!
欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,凡是转载于本人的文章,不能设置打赏功能,如有特殊需求请与本人联系!


 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号