重构公共API以降低安全风险

时间:2013-09-04 08:34:16

标签: c# asp.net-mvc-3 wcf security refactoring

在我们的应用程序中,WCF层中的PublicManagerService类显示出指数级增长的迹象,这导致方法在公共API中暴露,这可能导致我们的安全性风险增加,恶意攻击的门户以及性能下降。

这个例子可以在我们的AccountController类中,在Accept和Decline方法中看到,这些方法在用户点击电子邮件中的超链接时使用。以下调用是针对公共API中的方法进行的:

  • GetTransactionEmailLogByGUID
  • UpdateTransactionHitCount
  • SaveApprovalLog
  • GeneratePDF
  • UploadBlobByType
  • SetCurrentCulture(但是,这可以用于其他方法) 留)
  • SendEmail

我们的目标应该只是公开暴露一种方法来执行Accept过程,同样对于使用完全相同的调用的Decline方法。

    /// <summary>
    ///  Response to Accept 
    /// </summary>
    /// <param name="guid"></param>
    /// <param name="comment"></param>
    /// <returns></returns>
    public ActionResult Accept(string guid,string comment)
    {
        Gateway.Instance.Logger.LogDebug("[Accept] method entered.");
        IEnumerable<TransactionEmailLog> transactionEmailLogs = _publicServiceManager.GetTransactionEmailLogByGUID(guid.Trim());
        ViewBag.GUID = guid.Trim();
        if (transactionEmailLogs != null && transactionEmailLogs.Count() > 0)
        {
            var transactionEmailLog = transactionEmailLogs.FirstOrDefault();
            if (transactionEmailLog.HitCount < 50)
            {
                _publicServiceManager.UpdateTransactonHitCount(transactionEmailLog.GUID);
                var transaction = transactionEmailLog.Transaction;

                if (transaction != null)
                {
                    ViewBag.InvoiceDate = transaction.InvoiceIssueDate != null ? Convert.ToDateTime(transaction.InvoiceIssueDate).ToShortDateString() : "";
                    ViewBag.InvoiceNumber = transaction.InvoiceNumber != null ? Convert.ToString(transaction.InvoiceNumber) : "";
                    ViewBag.DueDate = transaction.PaymentDueDate != null ? Convert.ToDateTime(transaction.PaymentDueDate).ToShortDateString() : "";
                    ViewBag.AmountDue = transaction.PaymentDueDate != null ? transaction.CurrencyCode + " " + Convert.ToDecimal(transaction.InvoiceTotalPayable, CultureInfo.CurrentCulture.NumberFormat).ToString("N") : "";
                }

                ViewBag.IsAcceptOrDecline = "True";
                TransactionApprovalLog approvalLog = new TransactionApprovalLog { IsAccepted = true, CreatedBy = transactionEmailLog.ReferredTo, CreatedDate = DateTime.UtcNow, Transaction = transaction };
                if (!string.IsNullOrWhiteSpace(comment))
                {
                    approvalLog.Comments = comment;
                }
                this._publicServiceManager.SaveApprovalLog(approvalLog);

                if (transaction != null)
                {
                    this.SendEmailNotficationOfInvoiceVerification(transaction, guid, comment, Language.Accepted, transactionEmailLog);
                }
            }
        }
        ViewBag.Message =Language.InvoiceVerificationAcceptMessage;

        Gateway.Instance.Logger.LogDebug("[Accept] method exited.");

        if (Request.IsAjaxRequest())
        {
            return Json(new { result = "success" }, JsonRequestBehavior.AllowGet);
        }
        return View("InvoiceVerification");
    }

如您所见,'_ publicServiceManager'中有许多不同的公开方法。我所做的是创建一个DataContract对象,其中包含需要的信息,如GUID,CultureName等,我的目标是将其传递给PublicManagerService中的新方法。

public void VerifyInvoice (InvoiceVerificationDataContract invoiceVerificationDetails){}

我的问题是,我如何才能最好地重构此代码?我应该在WCF层中有任何逻辑,还是应该全部保留在业务层中?非常感谢您提前提出的所有建议。

1 个答案:

答案 0 :(得分:1)

我认为重构此代码的第一步是将调用包装在某种集成测试中的Accept和Decline操作中。

这将使您能够了解服务的构成,并了解您没有回归或损害整个过程。

这个过程看起来好像是为某种业务流程建模的,所以要把它变成一组整合的公共操作,我想你需要解决以下问题:

  • 每个步骤是否都需要成功执行才能使整个操作成功?
  • 每个步骤都必须按特定顺序执行吗?
  • 您将如何处理一个或多个步骤中的故障/恢复?
  • 将单独的功能组合在一起是否有意义?
  • 是否需要同步调用整个业务流程?

你可能已经考虑了所有这些要点以及更多,所以这个答案可能没有多大价值,但很难用当前形式的具体细节来回答你的问题。您可以将command-processor pattern视为解耦流程中各个步骤的一种方式。

感谢这不能直接回答你的问题。