6

すべてのアクションで使用できる HTTP 動詞を制限することは良い方法ですか? [HttpGet]私のコードは、[HttpPost]、 、[HttpPut]、またはすべてのアクションを装飾しなくてもきれいですが[HttpDelete]、堅牢性や安全性が低下する可能性もあります。GET バージョンが新しいフォームを返し、POST バージョンが新しいレコードを挿入する 2 つの「作成」アクションがあるように、動詞が明示的に必要でない限り、多くのチュートリアルやサンプル コードでこれが行われることはありません。

4

3 に答える 3

3

個人的には、 RESTful 規則を尊重し、サーバーの状態を変更しない GET アクションを除いて HTTP 動詞を指定して、任意の HTTP 動詞で呼び出せるようにします。

于 2011-04-28T18:34:29.350 に答える
1

はい、アクションを処理する適切な HTTP メソッドのみに制限することは良い習慣だと思います。これにより、システムから不正なリクエストを排除し、攻撃の可能性を減らし、コードのドキュメントを改善し、RESTful を強制します。デザインなど

はい、[HttpGet], .. 属性を使用すると、特に, などの[HttpPost]他の属性も使用する場合、コードが読みにくくなる可能性があります。[OutputCache][Authorize]

属性を使用する代わりに、カスタムでちょっとしたトリックをIActionInvoker使用します。アクション メソッド名の前に HTTP メソッドを追加します。

public class AccountController : Controller {

   protected override IActionInvoker CreateActionInvoker() {
      return new HttpMethodPrefixedActionInvoker();
   }

   public ActionResult GetLogOn() {
      ...
   }

   public ActionResult PostLogOn(LogOnModel model, string returnUrl) {
      ...
   }

   public ActionResult GetLogOff() {
      ...
   }

   public ActionResult GetRegister() {
      ...
   }

   public ActionResult PostRegister(RegisterModel model) {
      ...
   }

   [Authorize]
   public ActionResult GetChangePassword() {
      ...
   }

   [Authorize]
   public ActionResult PostChangePassword(ChangePasswordModel model) {
      ...
   }

   public ActionResult GetChangePasswordSuccess() {
      ...
   }
}

これはアクション名を変更しないことに注意してください。これは、、、、などのままですLogOnLogOffRegister

コードは次のとおりです。

using System;
using System.Collections.Generic;
using System.Web.Mvc;

public class HttpMethodPrefixedActionInvoker : ControllerActionInvoker {

   protected override ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName) {

      var request = controllerContext.HttpContext.Request;

      string httpMethod = request.GetHttpMethodOverride()
         ?? request.HttpMethod;

      // Implicit support for HEAD method. 
      // Decorate action with [HttpGet] if HEAD support is not wanted (e.g. action has side effects)

      if (String.Equals(httpMethod, "HEAD", StringComparison.OrdinalIgnoreCase))
         httpMethod = "GET";

      string httpMethodAndActionName = httpMethod + actionName;

      ActionDescriptor adescr = base.FindAction(controllerContext, controllerDescriptor, httpMethodAndActionName);

      if (adescr != null)
         adescr = new ActionDescriptorWrapper(adescr, actionName);

      return adescr;
   }

   class ActionDescriptorWrapper : ActionDescriptor {

      readonly ActionDescriptor wrapped;
      readonly string realActionName;

      public override string ActionName {
         get { return realActionName; }
      }

      public override ControllerDescriptor ControllerDescriptor {
         get { return wrapped.ControllerDescriptor; }
      }

      public override string UniqueId {
         get { return wrapped.UniqueId; }
      }

      public ActionDescriptorWrapper(ActionDescriptor wrapped, string realActionName) {

         this.wrapped = wrapped;
         this.realActionName = realActionName;
      }

      public override object Execute(ControllerContext controllerContext, IDictionary<string, object> parameters) {
         return wrapped.Execute(controllerContext, parameters);
      }

      public override ParameterDescriptor[] GetParameters() {
         return wrapped.GetParameters();
      }

      public override object[] GetCustomAttributes(bool inherit) {
         return wrapped.GetCustomAttributes(inherit);
      }

      public override object[] GetCustomAttributes(Type attributeType, bool inherit) {
         return wrapped.GetCustomAttributes(attributeType, inherit);
      }

      public override bool Equals(object obj) {
         return wrapped.Equals(obj);
      }

      public override int GetHashCode() {
         return wrapped.GetHashCode();
      }

      public override ICollection<ActionSelector> GetSelectors() {
         return wrapped.GetSelectors();
      }

      public override bool IsDefined(Type attributeType, bool inherit) {
         return wrapped.IsDefined(attributeType, inherit);
      }

      public override string ToString() {
         return wrapped.ToString();
      }
   }
}
于 2011-04-29T16:34:50.110 に答える
0

HttpGet を指定する必要はありません。他はすべて必要です。

于 2011-04-28T14:45:06.080 に答える