请注意,本站并不支持低于IE8的浏览器,为了获得最佳效果,请下载最新的浏览器,推荐下载 Chrome浏览器
欢迎光临。交流群:166852192

Orchard,Web Api,全局行为过滤器和依赖性解决方案


Personally I think this is a very exciting addition, as it allows us to expose Orchard services as well as our own services via a RESTful API to the outside world.
我个人认为这是一个非常令人兴奋的补充,因为它允许我们通过RESTful API向外部世界展示Orchard服务以及我们自己的服务。

Writing a Secured WebAPI

One of the requirements I was given is that this API should only be accessible by authorized clients. An easy way to do that is by requiring some sort of API credentials as part of the querystring, e.g. "apiKey", and check against a database of keys. There are a couple of ways this could be done, one of which by implementing an AuthorizationFilterAttribute and apply it to the controller. However, since AuthorizationFilterAttributes are attributes, we cannot simply use Dependency Injection to get access to our services.
So what is one supposed to do?
编写安全的WebAPI
我给出的一个要求是,这个API只能由授权的客户端访问。 一个简单的方法是通过要求某种类型的API凭证作为查询字符串的一部分,例如。 “apiKey”,并检查键的数据库。 有几种方法可以做到这一点,其中一个通过实现AuthorizationFilterAttribute并应用它到控制器。 然而,由于AuthorizationFilterAttributes是属性,我们不能简单地使用依赖注入来访问我们的服务。


那么,应该做什么呢?

WorkContext and the Service Locator Pattern

As luck (or rather, brilliant minds,) would have it, there's an easy way we can resolve instances of our precious services.
When implementing the OnAuthorization method of the AuthorizationFilterAttribute, we get access to a HttpActionContext object, which in turn provides access to the HttpControllerContext. Through this HttpControllerContext, we can get our hands on the WorkContext, which can be used to resolve instances of types registered with Autofac. Resolving services this way is known as the Service Locator Pattern, and although this is generally not the pattern to prefer over Dependency Injection, it works pretty well for these types of scenarios.
WorkContext和服务定位器模式
运气(或者说,聪明的头脑)会有它,有一个简单的方法,我们可以解决我们的珍贵服务的例子。


当实现AuthorizationFilterAttribute的OnAuthorization方法时,我们访问一个HttpActionContext对象,这反过来提供对HttpControllerContext的访问。 通过这个HttpControllerContext,我们可以得到我们的WorkContext,它可以用来解析用Autofac注册的类型的实例。 以这种方式解析服务被称为服务定位器模式,虽然这通常不是依赖注入的模式,但对于这些类型的场景,它工作得相当好。

Show me the code!

Allright, here it is. This is how a custom ApiKeyAuthorizationAttribute could look like:
代码!
好吧,在这里。 这就是一个自定义ApiKeyAuthorizationAttribute看起来像:
using System.Net;using System.Net.Http;using System.Web.Http.Controllers;using System.Web.Http.Filters;using MyModule.Models;using Orchard;using Orchard.ContentManagement;using Orchard.Environment.Extensions;namespace MyModule.Attributes {

    public class ApiKeyAuthorizationAttribute : AuthorizationFilterAttribute {

        public override void OnAuthorization(HttpActionContext actionContext) {
            var query = actionContext.Request.RequestUri.ParseQueryString();
            var apiKey = query["apiKey"];
            var workContext = actionContext.ControllerContext.GetWorkContext();
            var settings = workContext.CurrentSite.As<WebServiceSettingsPart>();

            if (apiKey != settings.ServiceApiKey) {
                actionContext.Response = actionContext.ControllerContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            }
        }
    }}
 
What we're doing here is getting a querystring parameter value keyed "apiKey" and checking it against a custom content part that is attached to the Site content item.
This implementation could be easily swapped with a version that checks the database for a key, or anything else that makes sence in your situation. Or even better: the implementation could be changed by applying the Strategy pattern, where the actual key checking is provided by another class.
Another improvement that could be made is having the "apiKey" turned into a configurable property, passed in via the constructor of the attribute. But I'll leave that up to you.
我们在这里做的是获取一个querystring参数值keyed“apiKey”并检查它附加到网站内容项目的自定义内容部分。
这个实现可以很容易地与一个检查数据库的键的版本交换,或任何其他在你的情况下sence。 或者甚至更好:可以通过应用策略模式来改变实现,其中实际的键检查由另一个类提供。


可以做的另一个改进是使“apiKey”变成可配置属性,通过属性的构造函数传递。 但我会把这一切留给你。

Applying the attribute is simple:

应用属性很简单:
using System.Web.Http;using MyModule.Attributes;namespace MyModule.Api {
    [ApiKeyAuthorization]
    public class OrderController : ApiController {

        public HttpResponseMessage Post(ShoppingCart cart) {
           // Create an order here
           var order = repository.Create(cart)
           var response = Request.CreateResponse<Order>(HttpStatusCode.Created, order);

           response.Headers.Location = new Uri(URL TO RESOURCE);
           return response;
       }
   }}
 
The attribute can be applied on the controller or on actions.
该属性可以应用于控制器或操作。

General tips when implementing a WebApi

Some general tips & guidelines when implementing a WebApi
  1. When implementing a controller, simply use action names like Get, Put, Post, Patch and Delete. Naming actions like CreateOrder on an OrderController is redundant. Also, using these standards frees you from having to explicitly apply HTTP verb attributes such as HttpGet, HttpPut, HttpPost, HttpDelete and HttpPatch to your action methods
  2. When creating a resource (in this example an Order), return a url to that resource (as shown in the 2nd code snippet)
 
Thanks to Nick Mayne not only for providing me with a review of this article and excellent tips as shared above, but also some kuddos for making WebApi possible in Orchard in the first place.


实现WebApi时的一些一般提示和指南


当实现控制器时,只需使用动作名称,如Get,Put,Post,Patch和Delete。 OrderController上的CreateOrder等命名操作是多余的。 此外,使用这些标准,您不必显式应用HTTP动词属性,如HttpGet,HttpPut,HttpPost,HttpDelete和HttpPatch到您的操作方法
当创建一个资源(在这个例子中是一个Order),返回一个url到该资源(如第二个代码片段所示)


感谢Nick Mayne不仅为我提供了这篇文章的评论和上面分享的优秀提示,而且还有一些用于在Orchard中首先制作WebApi的可能性。



作者原创内容不容易,如果觉得内容不错,请点击右侧“打赏”,赏俩给作者花花,也算是对作者付出的肯定,也可以鼓励作者原创更多更好内容。
更多详情欢迎到QQ群 166852192 交流。