【问题标题】:allow mvc5 c# webapi so that only my app can access it允许 mvc 5 c# web api 以便只有我的应用程序可以访问它
【发布时间】:2016-12-28 18:43:25
【问题描述】:

我正在通过控制器操作方法进行 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;
}

【问题讨论】:

    标签: asp.net-mvc asp.net-web-api asp.net-mvc-5 episerver-7


    【解决方案1】:

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

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

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

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

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

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

    【讨论】:

    • 您永远不应该将“秘密”与请求一起发送。这否定了“秘密”的全部目的。发布该密钥是为了让您可以加密或以其他方式保护您向 API 发出的请求,例如生成 HMAC 以防止重放攻击。
    • @ChrisPratt - 非常正确,我只是想让 OP 非常简单,假设他会对此进行进一步研究;我会更新我的答案/请随时更新。感谢您指出这一点。
    猜你喜欢
    • 2013-01-11
    • 1970-01-01
    • 1970-01-01
    • 2021-09-05
    • 2015-06-02
    • 1970-01-01
    • 2022-06-30
    • 1970-01-01
    • 2021-05-11
    相关资源
    最近更新 更多