Recaptcha和Web API - 验证令牌的良好REST实践

时间:2015-05-20 12:12:33

标签: c# rest asp.net-web-api

我有一系列Web API控制器,它们返回AngularJS前端消耗的数据。

我担心编写一个机器人脚本非常简单,只需要调用它就可以从数据库中提取所有数据。虽然这些信息是免费提供的,但我需要花费数小时/周/月/年来整理所有信息 - 这实际上是我网站的整个USP。如果有人通过从服务中提取数据来窃取我的数据,我会感到沮丧。

简单地添加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"); } } 无济于事,因为它可以免费注册。

我已经决定,我会向API提交一些令牌,这些令牌将被验证。主要是这将是一个解决的Captcha,但它可能在未来变化,所以我使它可扩展。因此,我在一个“?token = TypeID,TokenValue”参数中发送一个令牌类型和令牌值,并带有一个类型转换器来拾取它并将其转换为令牌对象。

所以我的问题是 - 将令牌和请求一起发送到Web API控制器有什么好的做法?我这样做了,这是对的吗?我已经读过发送查询字符串来进行身份验证并不是非常RESTful - 但它确实很有效。

样本概念验证

我的控制器:

   <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> 

Javascript调用它:

[TypeConverter(typeof(TokenConverter))]
    public class WebApiToken : IToken
    {
        public TokenType TokenType { get; set; }
        public string Token { get; set; }

        public static bool TryParse(string s, out WebApiToken result)
        {
            result = null;

            var parts = s.Split(',');
            if (parts.Length != 2)
            {
                return false;
            }

            int tokenTypeId;

            if (int.TryParse(parts[0], out tokenTypeId))
            {
                result = new WebApiToken() { TokenType = (TokenType)tokenTypeId, Token = parts[1] };
                return true;
            }
            return false;
        }
    }

令牌定义:

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"

提琴手回应:

{{1}}

0 个答案:

没有答案