Asp.net MVC 權限過濾器實現方法的最佳實踐

在項目開發中,爲了安全、方便地判斷用戶是否有訪問當前資源(Action)的權限,咱們通常經過全局過濾器來實現。css

Asp.net MVC 頁面中常見的權限判斷使用過濾器主要在如下幾種狀況(根據權限判斷的前後順序):html

一、判斷要訪問的Controller或Action是能夠匿名訪問;數據庫

二、判斷要訪問的Controller或Action是否登陸就能夠訪問;json

三、判斷是否有訪問某個Controller的Action的權限;瀏覽器

四、資源訪問權限,如在下拉菜單中獲取當前帳號能夠顯示幾個下拉項;安全

經過在全局過濾器中逐項判斷,咱們可讓有權限的用戶順利經過,沒有權限的就會被禁止掉,下面來看看過濾器的代碼實現:服務器

    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();
            // 一、容許匿名訪問 用於標記在受權期間要跳過 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
            {
                // 二、拒絕某個帳號登陸當前系統
                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
                {
                    // 三、判斷登陸狀態 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;
                    }
                    // 四、有些要判斷是否有某個菜單 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該怎麼寫呢?下面分別舉出幾個demoide

一、匿名訪問的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標籤,實現匿名訪問功能,用戶不需登陸便可訪問。ui

二、只須要登陸就能夠訪問的功能

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");
            }
        }
    }
}

三、判斷是否具備某個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);
            }
        }


    }
}
View Code
相關文章
相關標籤/搜索