2016-08-22 150 views
-1

我正在通过控制器操作方法进行api调用,如下所示。以下是它的工作代码。 但我想保护webapi,以便只有我的应用程序才能访问它。我已经看到登录凭证 的来源,但在我的情况下,它是一个面向公众的网站,没有登录用户。 只有来自我的应用程序的调用才能访问它。任何人都可以请建议可以做些什么。或者我的当前代码与ValidateReferrer足以处理?允许mvc5 c#webapi,以便只有我的应用程序可以访问它

[HttpGet] 
[ValidateReferrer] 
[ActionName("GetFind")] 
[CacheOutput(ClientTimeSpan = 300, ServerTimeSpan = 300)] 
public ApiQueryResponse GetFind(string query) 
{ 
    return _Worker.GetFind(query); 
} 

验证引荐控制器具有以下实现:

public override void OnAuthorization(AuthorizationContext filterContext) 
{ 
    if (filterContext.HttpContext == null) 
    { 
     throw new System.Web.HttpException("No Http context, request not allowed."); 
    } 
    else 
    { 
     if (filterContext.HttpContext.Request.UrlReferrer == null) 
     { 
      throw new System.Web.HttpException("Referrer information missing, request not allowed."); 
     } 
     else if (filterContext.HttpContext.Request.UrlReferrer.Host != filterContext.HttpContext.Request.Url.Host) 
     { 
      throw new System.Web.HttpException(string.Format("Possible cross site request forgery attack, request sent from another site: {0}", filterContext.HttpContext.Request.UrlReferrer.Host)); 
     } 
    } 
} 

在工人阶级,

public ApiQueryResponse GetFind(string query) 
{ 
    var results = GetResults(Settings.ApiKey, SetFindParameters(query), Resource);   
    return results; 
} 

private ApiQueryResponse GetResults(string apiKey, string parameterQuery, string Resource) 
{ 
    var results = new ApiQueryResponse(); 
    if (apiKey != null && !String.IsNullOrWhiteSpace(apiKey)) 
    { 
     using (var client = new HttpClient()) 
     { 
      client.DefaultRequestHeaders.Accept.Clear(); 
      client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 
      var response = client.GetAsync(string.Format("{0}/{1}?{2}&key={3}", WebApiUrl, Resource, parameterQuery, apiKey)).Result; 
      if (response.IsSuccessStatusCode) 
      { 
       var responseBodyAsText = response.Content.ReadAsStringAsync().Result; 
       results = JsonConvert.DeserializeObject<ApiQueryResponse>(responseBodyAsText); 
      } 
     } 
    } 
    return results; 
} 

回答

1

再次,这是你必须验证您的“应用程序”的情况下但不是用户。如果您查看facebook/twitter/gmail api,他们有一个客户机密钥和客户机ID来验证应用程序。但是仍然会有一个“授权”调用使用此id和秘密为api返回一个令牌,此令牌用于授权其他请求。该令牌也将有一个过期,并有方法来获取刷新令牌。

因此,你必须接受一个关于你必须为你的api执行多少安全性的调用。你可以有一个类似的方法,你的客户首先通过提供客户端ID和秘密(这应该是一个秘密)来请求安全令牌。你可以检查这个ID和秘密针对你的商店(可能是数据库),如果通过了验证,你可以发回一个令牌,你可以使用[Authroize]属性或自定义验证进行authroize。

如何创建令牌应该是IMO的另一个讨论。这里提到了简单的方法,例如:how to generate a unique token which expires after 24 hours?。还有其他标准的生成令牌JWT/OAuth令牌的方式。

编辑 作为一个简单的方法(没有采取太多的安全性方面考虑)将是:

  • 创建一个应用程序的秘密(可能是一个GUID值)
  • 虽然发送请求,获取当前时间戳并加密(使用自己的加密和解密逻辑)具有应用秘密的时间戳。让我们称之为该加密值作为“令牌”
  • 传入您的请求头中的令牌(可自定义标题,比方说, X-MY-AUTH)
  • 在API中,有一个自定义授权过滤
  • 在自定义过滤器,覆盖OnAuthroizeCore方法,从请求头
  • 得到 令牌使用相同的应用程序秘密解密令牌,你会得到 时间戳从客户
  • 如果解密是好的,那么我们是通过发送第一步/或令牌通过第一步
  • Additionaly,检查令牌解密当前时间 和时间之间的差异是否大于5(*你可以有你 自己的过期值)
  • 如果差大于你的有效期限多,返回false这 会抛出异常擅自返回给客户端(做同样的,如果令牌不能解密
  • 到期支票处理如果有人入侵您的请求 令牌,然后以后使用它的情况。在他 使用该令牌的期限届满后的情况下,这将抛出未经授权

考虑以上逻辑和整个描述只是作为一个“思考的食粮”,没有适当的研究和理解,不要使用它。我的想法是给出一些关于应用程序认证的基本概念,直到有人真的擅长这一点在本文中写出一篇非常好的文章

+1

您不应该将“秘密”与请求一起发送。这否定了“秘密”的全部目的。发布该秘密以允许您加密或以其他方式保护您对API的请求,例如生成HMAC以防止重播攻击。 –

+0

@ChrisPratt - 非常真实,我只是想让OP非常简单,假设他会对此做进一步的研究;我会更新我的答案/请随时更新。感谢您指出这一点。 – Developer

相关问题