C# Recaptcha和Web API—验证令牌的良好REST实践

C# Recaptcha和Web API—验证令牌的良好REST实践,c#,rest,asp.net-web-api,C#,Rest,Asp.net Web Api,我有一系列Web API控制器,它们返回AngularJS前端要使用的数据 我担心编写一个机器人的脚本是非常容易的,它只需要通过调用来敲打它,并从我的数据库中提取所有数据。虽然这些信息是免费提供的,但我花了很多时间/周/月/年来整理这些信息-这确实是我网站的整个USP。如果有人仅仅通过从服务中提取数据就偷走了我的数据,我会很难过 简单地添加Authorize不会有帮助,因为它可以免费注册 我已经决定,我将在每个请求中向API提交某种令牌,该API将得到验证。基本上,这将是一个已解决的验证码,但它

我有一系列Web API控制器,它们返回AngularJS前端要使用的数据

我担心编写一个机器人的脚本是非常容易的,它只需要通过调用来敲打它,并从我的数据库中提取所有数据。虽然这些信息是免费提供的,但我花了很多时间/周/月/年来整理这些信息-这确实是我网站的整个USP。如果有人仅仅通过从服务中提取数据就偷走了我的数据,我会很难过

简单地添加Authorize不会有帮助,因为它可以免费注册

我已经决定,我将在每个请求中向API提交某种令牌,该API将得到验证。基本上,这将是一个已解决的验证码,但它可能在未来有所不同,所以我将使其可扩展。因此,我将发送一个令牌类型和一个?token=TypeID,TokenValue参数中的令牌值,并使用一个类型转换器来获取它并将其转换为token对象

所以,我的问题是-向Web API控制器发送令牌和请求的最佳实践是什么?我是这样做的,对吗?我已经读到,发送querystring来进行身份验证不是非常RESTful的,但是它工作得非常好

概念证明样本

我的控制器:

public class ProductsController : ApiController
    {
        public IHttpActionResult Get(WebApiToken token, int id)
        {
            if (token == null)
                return BadRequest("Token not supplied");


            ITokenValidator requestValidator;

            // Some kind of a factory to decide how to validate the token that's been provided.
            requestValidator = new GuidTokenValidator();

            if (requestValidator.ValidateToken(token))
            {
                return Ok(string.Format("Some JSON would be returned here representing product ID {0}", id));
            }
            else
                return BadRequest("Token validation failed");
        }
    }
调用它的Javascript:

   <script type="text/javascript">
       $(document).ready(function () {
           $("#postTest").click(function () {

               $.ajax({
                   type: "GET",
                   dataType: "json",
                   url: "/api/Products/2?token=2,OK",
                   success: function (data) {
                       alert(data);
                   },
                   error: function (error) {
                       // Error handler
                   }
               });
           });
       });
    </script> 
类型转换器:

public class TokenConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType)
        {
            if (sourceType == typeof(string))
            {
                return true;
            }

            return base.CanConvertFrom(context, sourceType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value is string)
            {
                WebApiToken token;
                if (WebApiToken.TryParse((string)value, out token))
                {
                    return token;
                }
            }

            return base.ConvertFrom(context, culture, value);
        }
    }
小提琴手请求:

GET http://localhost:58106/api/Products/2?token=2,OK HTTP/1.1 Host: localhost:58106 Connection: keep-alive Accept: application/json, text/javascript, */*; q=0.01 X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36 Referer: http://localhost:58106/ Accept-Encoding: gzip, deflate, sdch Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
小提琴手的反应:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?YzpcdXNlcnNcYmVuLnNsb2FuXGRvY3VtZW50c1x2aXN1YWwgc3R1ZGlvIDIwMTNcUHJvamVjdHNcV2ViQVBJQWN0aW9uRmlsdGVyc1xXZWJBUElBY3Rpb25GaWx0ZXJzXGFwaVxQcm9kdWN0c1wy?=
X-Powered-By: ASP.NET
Date: Wed, 20 May 2015 11:59:55 GMT
Content-Length: 60

"Some JSON would be returned here representing product ID 2"

我读到过,发送一个查询字符串来进行身份验证并不是非常RESTful的,他们可能得到的是RESTful URL通常是样式化的。然而,这是为了描述资源,在您的例子中,令牌是上下文信息,因此查询字符串至少在我看来是绝对好的。但是,一种更干净的方法是将令牌作为头发送,这样它就不会影响您的URL,因为令牌实际上与资源不相关。@James感谢您的输入。非常感谢。除了在头中设置令牌外,最好对令牌进行加密。更好的做法是设置OAuth2或更难的东西,让恶意应用程序复制请求。如果您使用的是.NET4.5,请查看OWIN和基于声明的身份验证。
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?YzpcdXNlcnNcYmVuLnNsb2FuXGRvY3VtZW50c1x2aXN1YWwgc3R1ZGlvIDIwMTNcUHJvamVjdHNcV2ViQVBJQWN0aW9uRmlsdGVyc1xXZWJBUElBY3Rpb25GaWx0ZXJzXGFwaVxQcm9kdWN0c1wy?=
X-Powered-By: ASP.NET
Date: Wed, 20 May 2015 11:59:55 GMT
Content-Length: 60

"Some JSON would be returned here representing product ID 2"