.Net中的RealProxy實現AOP

序言

這個AOP要從咱們公司的一個事故提及,前段時間公司的系統忽然在烏雲中出現,數據被泄露的盡收眼底,烏雲上顯示是SQL注入攻擊。呵,多麼貼近生活的一個露洞,可謂是人盡皆知啊。然而卻華麗麗的給拉咱們一記耳光。web

那麼問題既然來啦,咱們.net組有40-50個項目之多吧,怎麼去一一補救這一過失呢?什麼又是SQL注入呢?再有就是常見的Web漏洞有哪些呢?咱們怎麼更好的監控咱們的系統呢?sql

那麼你們不要嫌我囉嗦,本篇我將對常見的網站攻擊與防護,與.Net中AOP實現橫切關注點作一些介紹與演示。數據庫

常見的web攻擊與防護

據數據統計:全球70%的web應用攻擊都是來自XSS攻擊和SQL注入攻擊。此外還有常見的跨站攻擊CSRF,Session劫持,文件上傳等手段。編程

XSS攻擊服務器

XSS攻擊即跨站點腳本攻擊(Cross Site Script),看下全稱縮寫,本應該是CSS無奈,已被樣式表佔用,只能用個更牛逼的XXX代替,XSS,哈哈,蛋扯完啦,說下什麼是XSS,他是攻擊者在網頁中嵌入惡意程序腳本,當用戶打開網頁時,腳本程序便開始執行,竊取客戶端cookie,用戶名,密碼,下載執行病毒木馬程序等等,牛逼的一塌糊塗,好像你的網站系統成啦他本身的同樣。cookie

那麼怎麼注入的呢?舉個例子啊,假如發表個說說,或者微博,發表的內容是  "/><script>alert('123');</script><!-  ,那麼在某種狀況下你可能會讓他加載到你的 <input type="text" value="" />中,你再看下你的代碼成什麼樣子啦,就會運行alert();我這裏僅僅是一個alert();黑客,就黑的不着邊際的黑你啊。架構

XSS防範:mvc

一、將用戶輸入的特殊符號如:<,>,'',""轉義爲&lt,&gt,&amp,&quot;等。app

二、對Cookie添加HttpOnly屬性,他不能對抗XSS攻擊,但能夠防止竊取cookie。框架

CSRF攻擊

CSRF攻擊即跨站請求攻擊(cross site request forgery)。攻擊者經過跨站請求,以合法用戶的身份進行非法操做,如轉帳,發表評語等。具體流程以下:

舉例說明:假設你在中國銀行網站進行轉帳業務,首先你登錄啦中國銀行,進行啦轉帳,這是假設你的轉帳鏈接爲http:www.zhongguoyinhang/zz/1000.那麼你轉完賬後並無關閉頁面。而是訪問啦另一個網站,另一個網站的一個圖片或者鏈接爲攻擊者布好的鏈接:http:www.zhongguoyinhang/zz/1000 。那麼很不幸,你又一次進行啦轉帳。

固然,中國銀行會有各類舉措。不過這確實是攻擊者的一種手段。

CSRF防範:

一、對Cookie添加HttpOnly屬性。

二、增長token驗證,驗證碼驗證,表單token等。

三、經過Referer識別,來源網站。

SQL注入攻擊

SQL注入相信每一個開發者都耳熟能詳啦。很少說,就是經過sql拼接,讓你的sql執行別人想要執行的語句。甚至可惡的update,delete,等等等等!!

SQL注入防範:一、使用orm框架。二、使用預編譯語句。三、避免明文存放密碼。四、處理好響應的異常,由於異常中會包含關於服務器版本,數據庫版本,編程語言甚至數據庫鏈接地址,用戶名密碼等信息。

文件上傳漏洞

文件上傳也好理解:就是攻擊者上傳啦惡意可執行文件或者腳本,並經過腳本獲取服務器響應的權利,多可怕,若是他上傳個格式化你服務器硬盤的程序,可想而知。怕不怕!!

防範:一、驗證後綴名。二、驗證魔數。魔數:不少類型的文件,其實的幾個字節內容是固定,所以根據這幾個字節就能確認文件的類型。這幾個字節也稱爲魔數。三、部署獨立的文件服務器。

其實攻擊手段還有不少,DDOS,CC,DNS域名劫持,cdn回源攻擊等等,你們能夠在網上搜搜查查,瞭解一下。

AOP解決40-50個項目中的sql注入漏洞

這裏的aop實際上是.Net中的透明代理與真是代理的實現。他讓通常開發者不用關心某個橫切點,好比接口性能的的記錄,日誌記錄,過濾危險字符,事物提交回滾等等。

首先咱們的項目有的用的orm框架,有的沒有用,有的用的參數化拼接,有的直接字符串拼接。那麼咱們這麼多項目怎麼一會兒進行清理盤查呢。咱們想拉個辦法就是咱們的項目都有業務邏輯層去鏈接數據讀寫層的。那麼咱們只要把業務邏輯層這一層的方法參數給過濾一下危險字符,不就能夠拉。那麼工程開始啦。

namespace A.Helper.Client.Action
{
    public class SqlVerifyProxy :RealProxy
    {
        MarshalByRefObject _target = null;
        public SqlVerifyProxy(Type type, MarshalByRefObject target)
            : base(type)
        {
            this._target = target;
        }
        //覆寫Invoke,處理RealProxy截獲的各類消息,
        //此種方式最簡捷,但不能截獲遠程對象的激活,好在咱們並非真的要Remoting
        public override IMessage Invoke(IMessage msg)
        {
            IMethodCallMessage call = (IMethodCallMessage)msg;
            IConstructionCallMessage ctr = call as IConstructionCallMessage;
            IMethodReturnMessage back = null;
            //構造函數,只有ContextBoundObject(Inherit from MarshalByRefObject)對象才能截獲構造函數
            if (ctr != null)
            {
                RealProxy defaultProxy = RemotingServices.GetRealProxy(_target);
                //若是不作下面這一步,_target仍是一個沒有直正實例化被代理對象的透明代理,
                //這樣的話,會致使沒有直正構建對象。
                defaultProxy.InitializeServerObject(ctr);
                //本類是一個RealProxy,它可經過GetTransparentProxy函數獲得透明代理
                back = EnterpriseServicesHelper.CreateConstructionReturnMessage(ctr, (MarshalByRefObject)GetTransparentProxy());
            }
            //MarshalByRefObject對象就可截獲普通的調用消息,
            //MarshalByRefObject對象告訴編譯器,不能將其內部簡單的成員函數優化成內聯代碼,
            //這樣才能保證函數調用都能截獲。
            else
            {
                IDictionary<string, object> dic = new Dictionary<string, object>();
                dic = actionContext.ActionArguments;
                if (dic != null && dic.Count > 0)
                {
                    foreach (var m in dic)
                    {
                        string o = m.Value.ToJson();
                        Utils.Filter(o);
                    }
                }
                back = RemotingServices.ExecuteMessage(_target, call);                
            }
            return back;
        }
    }
}
namespace A.Helper.Client.Action
{
    //從ProxyAttribute繼承,自動實現RealProxy植入
    [AttributeUsage(AttributeTargets.Class)]
    class SqlVerifyProxyAttribute : ProxyAttribute
    {
        //覆寫CreateInstance函數,返回咱們自建的代理
        public override MarshalByRefObject CreateInstance(Type serverType)
        {
            MarshalByRefObject obj = base.CreateInstance(serverType);
            SqlVerifyProxy proxy = new SqlVerifyProxy(serverType, obj);
            return (MarshalByRefObject)proxy.GetTransparentProxy();
        }
    }
}

好啦,就這麼簡單,只要業務邏輯層的基類,集成ContextBoundObject添加咱們的[SqlVerifyProxy]屬性就好啦,這個做爲一個dll給其餘項目引入,別人不用一個一個再寫一遍。不過這也是咱們的權宜之計,相信咱們之後的項目會有更好的架構設計,來防範諸如此類低級問題的發生。

RealProxy實現AOP業務層事務入侵

讓你的代碼不用每次都聲明事物,你也沒必要擔憂你的事物是否提交,或者回滾啦嗎?我作了一個示例僅供參考。

        /// <summary>
        /// 插入能夠成功
        /// </summary>  
        public Int32 UpdateTrue(string appName)
        {
            try
            {
                using (var conn = GetInstance())
                {
                    string sql = "update aoptran set appName='"+appName+"' where id <10 ";
                    var result = conn.ExecuteScalar(sql);
                    return result != null ? Convert.ToInt32(result) : 0;
                }
            }
            catch (Exception ex)
            {               
                return 0;
            }
        }
        /// <summary>
        /// 由於appName字段多寫成了appName1因此修改不會成功
        /// </summary>  
        public Int32 UpdateFalse(string appName)
        {
            try
            {
                using (var conn = GetInstance())
                {
                    string sql = "update aoptran set appName1='" + appName + "' where id <10 ";
                    var result = conn.ExecuteScalar(sql);
                    return result != null ? Convert.ToInt32(result) : 0;
                }
            }
            catch (Exception ex)
            {
                return 0;
            }
        }
namespace TranAopRealProxy.Aop
{
    /// <summary>
    /// RealProxy is a abstract class, which is a class in Framework to provide the function about base proxy.
    /// The Invoke method like the hook of MFC, it intercept the message, inject the custom logic and generate a new message
    /// for system to performance.
    /// </summary>
    class AOPRealProxy : RealProxy, IProxyDI
    {
        private MarshalByRefObject _target = null;
        private IInterception _interception = null;

        public AOPRealProxy(Type targetType, MarshalByRefObject target)
            : base(targetType)
        {
            _target = target;
            _interception = new NullInterception();
        }

        /// <summary>
        /// Overridden the method "Invoke" of the base class, invokes the method that is specified
        //  in the provided System.Runtime.Remoting.Messaging.IMessage on the remote
        //  object that is represented by the current instance.
        /// </summary>
        /// <param name="msg">A System.Runtime.Remoting.Messaging.IMessage that contains a System.Collections.IDictionary
        //  of information about the method call.
        //  </param>
        /// <returns>The message returned by the invoked method, containing the return value and
        //  any out or ref parameters.
        //  </returns>
        public override System.Runtime.Remoting.Messaging.IMessage Invoke(System.Runtime.Remoting.Messaging.IMessage msg)
        {
            IMethodReturnMessage methodReturnMessage = null;
            IMethodCallMessage methodCallMessage = msg as IMethodCallMessage;//Check whether the message is method call message.
            if (methodCallMessage != null)
            {
                IConstructionCallMessage constructionCallMessage = methodCallMessage as IConstructionCallMessage;
                if (constructionCallMessage != null)
                {
                    RealProxy defaultProxy = RemotingServices.GetRealProxy(_target);
                    defaultProxy.InitializeServerObject(constructionCallMessage);
                    methodReturnMessage = EnterpriseServicesHelper.CreateConstructionReturnMessage(constructionCallMessage, (MarshalByRefObject)GetTransparentProxy());
                }
                else
                {
                    _interception.PreInvoke();
                    try
                    {
                        methodReturnMessage = RemotingServices.ExecuteMessage(_target, methodCallMessage);
                    }
                    catch
                    {
                    }
                    if (methodReturnMessage.Exception != null)
                    {
                        _interception.ExceptionHandle();
                    }
                    else
                    {
                        _interception.PostInvoke();
                    }
                }
            }
            return methodReturnMessage;
        }

        #region IProxyDI Members

        /// <summary>
        /// Dependency injection the interception into proxy class.
        /// </summary>
        /// <param name="interception">The interception.</param>
        public void InterceptionDI(IInterception interception)
        {
            _interception = interception;
        }

        #endregion
    }
}
View Code
namespace TranAopRealProxy.Aop
{
    /// <summary>
    /// Description of AOPProxyAttribute.
    /// </summary>
    [AttributeUsage(AttributeTargets.Class)]
    public class AOPProxyAttribute : ProxyAttribute
    {
        private IInterception _interception;
        public Type Interception
        {
            get 
            {
                return _interception.GetType();
            }
            set
            {
                IInterception interception = Activator.CreateInstance(value) as IInterception;
                _interception = interception;
            }
        }
        public AOPProxyAttribute()
        {
            _interception = new NullInterception();
        }
        public override MarshalByRefObject CreateInstance(Type serverType)
        {
            MarshalByRefObject target = base.CreateInstance(serverType);
            AOPRealProxy aopRealProxy = new AOPRealProxy(serverType, target);
            aopRealProxy.InterceptionDI(_interception);
            return aopRealProxy.GetTransparentProxy() as MarshalByRefObject;
        }
    }
}
View Code
using System;

namespace TranAopRealProxy.Aop
{
    /// <summary>
    /// Description of IInterception.
    /// </summary>
    public interface IInterception
    {
        /// <summary>
        /// Pre the method invoke.
        /// </summary>
        void PreInvoke();

        /// <summary>
        /// Post the method invoke.
        /// </summary>
        void PostInvoke();

        /// <summary>
        /// Handling the exception which occurs when the method is invoked.
        /// </summary>
        void ExceptionHandle();
    }
}
View Code
using System;
using System.Collections.Generic;
using System.Text;

namespace TranAopRealProxy.Aop
{
    interface IProxyDI
    {
        void InterceptionDI(IInterception interception);
    }
}
View Code
//
// Authors:
// Xiaoliang Pang (mailto:mv@live.cn)
//
// Copyright (c) 2010 Landpy Software
//
// http://www.cnblogs.com/pangxiaoliang
//
using System;
using System.Collections.Generic;
using System.Text;

namespace TranAopRealProxy.Aop
{
    /// <summary>
    /// Null Object pattern for interception.
    /// </summary>
    public class NullInterception : IInterception
    {

        #region IInterception Members

        /// <summary>
        /// Before invoke the real instance to do something.
        /// </summary>
        public virtual void PreInvoke()
        {
            // Do nothing.
        }

        /// <summary>
        /// End invoke the real instance to do something.
        /// </summary>
        public virtual void PostInvoke()
        {
            // Do nothing.
        }

        /// <summary>
        /// Handling the exception which occurs when the method is invoked.
        /// </summary>
        public void ExceptionHandle()
        {
            // Do nothing.
        }

        #endregion

    }
}
View Code
using System;
using System.Collections.Generic;
using System.Text;

namespace TranAopRealProxy.Aop
{
    public class ProxyFactory
    {
        public static T CreateProxyInstance<T>(IInterception interception) where T : new()
        {
            Type serverType = typeof(T);
            MarshalByRefObject target = Activator.CreateInstance(serverType) as MarshalByRefObject;
            AOPRealProxy aopRealProxy = new AOPRealProxy(serverType, target);
            aopRealProxy.InterceptionDI(interception);
            return (T)aopRealProxy.GetTransparentProxy();
        }
    }
}
View Code
using System.Text;
using System.Threading.Tasks;
using TranAopRealProxy.Aop;
using System.Transactions;
namespace TranAopRealProxy.Aop
{
    /// <summary>
    /// The interception of the AOP for trasaction.
    /// </summary>
    class Transaction : IInterception
    {
        #region IInterception Members

        TransactionScope tran = null;
        public void ExceptionHandle()
        {
            tran.Dispose();
        }
        public void PostInvoke()
        {
            tran.Complete();
            tran.Dispose();
        }
        public void PreInvoke()
        {
            tran = new TransactionScope();             
        }
        #endregion
    }
}
 public class Logic : BaseTran
    {
        /// <summary>
        /// 回滾
        /// </summary>
        public void ActionFalseRollBack()
        {
            DoDB db = new DoDB();
            db.UpdateTrue("abc");
            int isSuccess= db.UpdateFalse("defg");
            if (isSuccess <=0)
            {
                throw new Exception("蒼天啊,大地啊,回滾吧。");
            }
        }
        /// <summary>
        /// 提交
        /// </summary>
        public void ActionFalseRollBack1()
        {
            DoDB db = new DoDB();
            db.UpdateTrue("abc");
            db.UpdateTrue("abc234");           
        }
    }

總結

AOP在.net中還有體現,好比mvc的過濾器。也有不少第三方的插件供咱們使用,好比:postsharp,castle.net等,你們能夠了解學習下。若是你想把這裏的透明代理與真實代理學透徹,也推薦閱讀.Net本質論中的高級方法。同時也歡迎你們加入左上方羣,咱們一塊兒探討學習。

相關文章
相關標籤/搜索