Nhibenate-DOS攻击

Nhibenate-DOS攻击

问题描述:

我公司的一位测试人员在我的ASP.Net MVC 3解决方案中发现了一个错误,我认为这很常见。Nhibenate-DOS攻击

它可以处理的服务器的一篇文章。但是,如果你发了很多帖子,像阻断服务攻击(DoS攻击)它抛出一个异常:

Server Error in '/' Application. 
Initializing[UseSoft.ProdMaster.Domain.Entities.CustomerOrderHeader#567]-failed to lazily initialize a collection of role: UseSoft.ProdMaster.Domain.Entities.CustomerOrderHeader.CustomerOrderLines, no session or session was closed 
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: NHibernate.LazyInitializationException: Initializing[UseSoft.ProdMaster.Domain.Entities.CustomerOrderHeader#567]-failed to lazily initialize a collection of role: UseSoft.ProdMaster.Domain.Entities.CustomerOrderHeader.CustomerOrderLines, no session or session was closed 

Source Error: 

Line 880: 
Line 881: 
Line 882:   return 
Line 883:    Json(
Line 884:     new 


Source File: C:\Projects\DavidPM\Hosts\ProdMaster.Hosts.Web\Areas\Sales\Controllers\CustomerOrderController.cs Line: 882 

Stack Trace: 

[LazyInitializationException: Initializing[UseSoft.ProdMaster.Domain.Entities.CustomerOrderHeader#567]-failed to lazily initialize a collection of role: UseSoft.ProdMaster.Domain.Entities.CustomerOrderHeader.CustomerOrderLines, no session or session was closed] 
    NHibernate.Collection.AbstractPersistentCollection.ThrowLazyInitializationException(String message) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Collection\AbstractPersistentCollection.cs:484 
    NHibernate.Collection.AbstractPersistentCollection.ThrowLazyInitializationExceptionIfNotConnected() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Collection\AbstractPersistentCollection.cs:474 
    NHibernate.Collection.AbstractPersistentCollection.Initialize(Boolean writing) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Collection\AbstractPersistentCollection.cs:465 
    NHibernate.Collection.AbstractPersistentCollection.Read() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Collection\AbstractPersistentCollection.cs:264 
    NHibernate.Collection.Generic.PersistentGenericBag`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Collection\Generic\PersistentGenericBag.cs:142 
    System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +63 
    System.Linq.Buffer`1..ctor(IEnumerable`1 source) +217 
    System.Linq.Enumerable.ToArray(IEnumerable`1 source) +78 
    UseSoft.ProdMaster.Hosts.Web.Areas.Sales.Controllers.CustomerOrderController.SaveOrUpdateOrderLines(CustomerOrderModel customerOrderModel) in C:\Projects\DavidPM\Hosts\ProdMaster.Hosts.Web\Areas\Sales\Controllers\CustomerOrderController.cs:882 
    lambda_method(Closure , ControllerBase , Object[]) +162 
    System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +17 
    System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +208 
    System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27 
    System.Web.Mvc.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12() +55 
    System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +263 
    System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() +19 
    System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +191 
    System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +343 
    System.Web.Mvc.Controller.ExecuteCore() +116 
    System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +97 
    System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10 
    System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +37 
    System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +21 
    System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +12 
    System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62 
    System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +50 
    System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7 
    System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22 
    System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60 
    System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9 
    System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8862381 
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184 

将被描述如下:

单击一个按钮多次。或者点击一次并按下回车键,它会向服务器发送很多请求。

模型基本上是:

public class CustomerOrderModel 
{ 
    public CustomerOrderModel() 
    { 
     this.CustomerOrderLines = new List<CustomerOrderLineModel>(); 
     this.CustomerOrderHeader = new CustomerOrderHeaderModel(); 
    } 

    public CustomerOrderHeaderModel CustomerOrderHeader 
    { get; set; } 

    public List<CustomerOrderLineModel> CustomerOrderLines 
    { get; set; } 

} 

控制器:

[HttpPost] 
     public JsonResult SaveOrUpdateOrderLines( CustomerOrderModel customerOrderModel) 
     { 

    if (customerOrderModel.CustomerOrderHeader.OrderNumber == 0) 
      { 
       customerOrderModel.CustomerOrderHeader.OrderNumber = this.CustomerOrderService.CreateOrUpdate(customerOrderHeader, false); 
      } 

返回 JSON( 新 { ORDERNUMBER = customerOrderModel.CustomerOrderHeader.OrderNumber, CustomerOrderLines =新 { CustomerOrderLine =( 从custOrderHeader.CustomerOrderLines ordeline 选择新 { 编号= ordeline.Id, LineNumber上= ordeline.LineNumber, LineStatus = ordeline.LineStatus }

      ).ToArray() 

         } 
       }, 
       JsonRequestBehavior.AllowGet 
      ); 

} 

的CustomerOrder服务:

public class CustomerOrderService : ServiceBase, ICustomerOrderService 
    { 

public long CreateOrUpdate(CustomerOrderHeader customerOrderHeader, bool updateCustomerOrderHeader) 
     { 
      using (var session = this.SessionManager.OpenSession()) 
      { 
       var transaction = session.BeginTransaction(); 

       try 
       { 
        //TODO: CHECKS IF PARTNER EXISTS 
        bool existsPartner = false; 
        long number = 0; 
        if (this.PartnerService.FindByName(customerOrderHeader.Partner.Name) != null) 
        { 
         existsPartner = true; 
        } 

        //CREATE PARTNER AND PARTNER ADDRESSES 
        if (!existsPartner) 
        { 
         this.PartnerService.Create(customerOrderHeader.Partner as Partner); 
        } 



        if (!updateCustomerOrderHeader) 
        { 
         number = this.CustomerOrderHeaderService.Create(customerOrderHeader, true); 
        } 
        else 
        { 
         this.CustomerOrderHeaderService.Create(customerOrderHeader, false); 
        } 
        transaction.Commit(); 
        return number; 


       } 

       catch (Exception ex) 
       { 

        transaction.Rollback(); 
        throw ex; 
       } 
       finally 
       { 
        session.Close(); 
       } 
      } 
     } 



     /// <summary> 
     /// Initializes a new instance of the <see cref="CustomerOrderService"/> class. 
     /// </summary> 
     /// <param name="sessionManager"> 
     /// The session manager. 
     /// </param> 
     public CustomerOrderService(ISessionManager sessionManager) 
     { 
      this.SessionManager = sessionManager; 
     } 
} 

CustomerOrderHeaderService:

public long Create(CustomerOrderHeader customerOrderHeader, bool firstTime) 
     { 


      using (var session = this.SessionManager.OpenSession()) 
      { 
      // var transaction = session.BeginTransaction(); 

      // try 
      // { 




        if (firstTime) 
        { 
         foreach (var customerOrderLine in customerOrderHeader.CustomerOrderLines) 
         { 
          customerOrderLine.CustomerOrderHeader = customerOrderHeader; 
         } 

         customerOrderHeader.OrderNumber = this.NextOrderNumber(); 
         session.Save(customerOrderHeader); 
        } 
        else 
        { 

         CustomerOrderHeader customerOrderHeaderToBeChanged = 
          this.FindByOrderNumber(customerOrderHeader.OrderNumber); 

         customerOrderHeaderToBeChanged.CopyDomainProperties(
          customerOrderHeader, new[] 
                { 
                 "Id", 
                 "Partner", 
                 "DataOwner", 
                 "dataOwner", 
                 "SysCreatedOn", 
                 "SysCreatedBy", 
                 "CustomerOrderLines" 
                }); 
         customerOrderHeaderToBeChanged = UpdateLines(customerOrderHeader, customerOrderHeaderToBeChanged); 
         List<ICustomerOrderLine> linestoBeInserted = GetTheLineNumbersToBeInserted(customerOrderHeader); 

         foreach (var customerOrderLine in linestoBeInserted) 
         { 
          customerOrderHeaderToBeChanged.CustomerOrderLines.Add(customerOrderLine); 
          customerOrderLine.CustomerOrderHeader = customerOrderHeaderToBeChanged; 
         } 

         session.Update(customerOrderHeaderToBeChanged); 
        } 

      //  transaction.Commit(); 
      } 
      // catch (Exception ex) 
      // { 
      //  transaction.Rollback(); 
      //  throw ex; 
      // } 
      // finally 
      // { 
      //  session.Close(); 
      // } 
      //} 
      //throw new System.ArgumentException(); 

      return customerOrderHeader.OrderNumber; 
     } 


public class CustomerOrderHeaderService : ServiceBase, ICustomerOrderHeaderService 
    { 
     #region Constructors and Destructors 

     /// <summary> 
     /// Initializes a new instance of the <see cref="CustomerOrderHeaderService"/> class. 
     /// </summary> 
     /// <param name="sessionManager"> 
     /// The session manager. 
     /// </param> 
     public CustomerOrderHeaderService(ISessionManager sessionManager) 
     { 
      this.SessionManager = sessionManager; 
     } 

     #endregion 

public long Create(CustomerOrderHeader customerOrderHeader, bool firstTime) 
     { 


      using (var session = this.SessionManager.OpenSession()) 
      { 
      // var transaction = session.BeginTransaction(); 

      // try 
      // { 




        if (firstTime) 
        { 
         foreach (var customerOrderLine in customerOrderHeader.CustomerOrderLines) 
         { 
          customerOrderLine.CustomerOrderHeader = customerOrderHeader; 
         } 

         customerOrderHeader.OrderNumber = this.NextOrderNumber(); 
         session.Save(customerOrderHeader); 
        } 
        else 
        { 

         CustomerOrderHeader customerOrderHeaderToBeChanged = 
          this.FindByOrderNumber(customerOrderHeader.OrderNumber); 

         customerOrderHeaderToBeChanged.CopyDomainProperties(
          customerOrderHeader, new[] 
                { 
                 "Id", 
                 "Partner", 
                 "DataOwner", 
                 "dataOwner", 
                 "SysCreatedOn", 
                 "SysCreatedBy", 
                 "CustomerOrderLines" 
                }); 
         customerOrderHeaderToBeChanged = UpdateLines(customerOrderHeader, customerOrderHeaderToBeChanged); 
         List<ICustomerOrderLine> linestoBeInserted = GetTheLineNumbersToBeInserted(customerOrderHeader); 

         foreach (var customerOrderLine in linestoBeInserted) 
         { 
          customerOrderHeaderToBeChanged.CustomerOrderLines.Add(customerOrderLine); 
          customerOrderLine.CustomerOrderHeader = customerOrderHeaderToBeChanged; 
         } 

         session.Update(customerOrderHeaderToBeChanged); 
        } 

      //  transaction.Commit(); 
      } 
      // catch (Exception ex) 
      // { 
      //  transaction.Rollback(); 
      //  throw ex; 
      // } 
      // finally 
      // { 
      //  session.Close(); 
      // } 
      //} 
      //throw new System.ArgumentException(); 

      return customerOrderHeader.OrderNumber; 
     } 
} 

提高连接池的限制可以帮助它持续下这个更长的时间,只要你没有太多的饱和服务器/网络。

尽可能晚或更早打开和关闭数据库连接。您可能想要将会话从每个请求(或您正在使用的任何)打开/关闭切换为正在使用。

在你的情况,因为它是界面上的按钮,你可以暂时(使用JavaScript)来禁用它一段时间,因此用户不能保持单击它的速度比他们应该永远需要。

无论如何,您应该对网络或IIS级别的传入请求进行速率限制。

确保您没有跨多个NHibernate会话共享对象。

如果会话#1加载会话#2尝试提交的对象,则可能会发生此错误。