0

我正在通过控制器操作方法进行 api 调用,如下所示。以下是它的工作代码。但我想保护 webapi,以便只有我的应用程序可以访问它。我见过带有登录凭据的来源,但就我而言,它是一个没有登录用户的面向公众的网站。只有来自我的应用程序的调用才能访问它。任何人都可以请建议可以做什么。或者我当前的 ValidateReferrer 代码是否足以处理?

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

控制器中的 Validate Referrer 具有以下实现:

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;
}
4

1 回答 1

3

同样,您必须对“应用程序”进行身份验证,而不是对用户进行身份验证。如果您检查 facebook/twitter/gmail api,他们有一个客户端密码和客户端 ID 来验证应用程序。但是仍然会有一个使用这个 id 和 secret 进行的“授权”调用,api 会为此返回一个令牌,并且这个令牌将用于授权其他请求。此令牌也将有一个到期日,并且有一些方法可以获取刷新令牌。

如此说来,您必须打电话给您必须为您的 api 实施多少安全性。您可以采用类似的方法,您的客户端首先通过提供客户端 ID 和机密(这应该是机密)来请求安全令牌。您可以对照您的商店(可能是数据库)检查此 id 和密码,如果通过验证,您可以发回一个令牌,您可以使用 [Authroize] 属性或自定义验证对其进行授权。

如何创建代币应该是 IMO 的另一个讨论。这里提到了简单的方法,例如 -如何生成一个在 24 小时后过期的唯一令牌?. 还有其他生成令牌 JWT/OAuth 令牌的标准方法。

编辑 作为一种简单的方法(不考虑太多安全方面)将是:

  • 创建应用机密(可能是 Guid 值)
  • 发送请求时,获取当前时间戳并使用应用程序密钥加密(具有您自己的加密和解密逻辑)时间戳。让我们将该加密值称为“令牌”
  • 在您的请求标头中传递令牌(可能是自定义标头,例如 x-my-auth)
  • 在 api 中,有一个自定义的授权过滤器
  • 在自定义过滤器中,重写 OnAuthroizeCore 方法,从请求头中获取令牌
  • 使用相同的应用程序密钥解密令牌,您将获得客户端发送的时间戳
  • 如果解密没问题,那么我们通过了第一步/或者令牌通过了第一步
  • 另外,检查当前时间和从token解密的时间之间的时间差是否大于5(*你可以有自己的过期值)
  • 如果差异超过您的到期限制,则返回 false ,这会将未经授权的异常返回给客户端(如果令牌无法解密,请执行相同操作
  • 到期检查是为了处理有人从请求中窃取您的令牌然后使用它的情况。如果他在您到期后使用令牌,这将引发未经授权的

将上述逻辑和整个描述视为“思考的食物”,如果没有适当的研究和理解,请勿使用它。我的想法是提供一些关于应用程序身份验证的基本概念,直到真正擅长此操作的人在这篇文章中写出一篇非常好的文章

于 2016-08-22T09:39:20.217 回答