安全的Ajax调用Rest API

6

这个问题在面试中被问到过。我在网上搜索了一下,但没有找到一个能让我理解的解释。

假设我有一个 Web 服务,该服务返回一些东西的列表并可在公共域(任何人都可以使用该服务)中使用。为了安全起见,用户需要钥匙才能访问该 Web 服务。

如何安全地在 Ajax 中使用该 Web 服务?

问题在于,如果我使用 Ajax 访问该 Web 服务,任何人都可以看到我的私钥。

我建议使用加密,但我必须在解密时传递该密钥(正如我所获得的那样)。然后我建议使用一个中介文件(位于服务器端),通过它调用该 Web 服务,但是如果有人直接访问该中介文件呢?(我知道同源策略)

我真的想知道如何克服这些问题的可能解决方案以及进行 REST 安全 AJAX 调用的最佳实践是什么。

3个回答

3
事实上,OAuth2 为这种特定用例提供了专门的安全流程,称为“隐式授权流程”。
您可以查看这些链接获取更多详细信息: 如果您不使用OAuth2,可以建议用户进行身份验证并获取访问令牌。您可以将其存储在浏览器的本地存储中,但需要非常小心防止XSS攻击。这个问题(以及它的答案)可以为您提供一些关于此类问题的提示:REST基本身份验证与Javascript客户端有哪些(如果有)安全缺陷?
希望对您有所帮助, Thierry

0
我们正在使用cookie。就像Session一样,我们已经将安全密钥存储在Web服务器上。通过Cookie,我们可以获取安全密钥。因此,他只能看到他的密钥的“键”。没有隐藏所有信息的选项。但是您可以向他显示无法直接使用的信息。
总之,存在钓鱼问题。如果有人钓取您的cookie,则拥有您的安全密钥的“键”。许多其他人也在做类似的事情。例如Facebook。
这不是特定于Ajax调用的问题,但由于它适用于普通GET和AJAX调用,因此它可能是一个解决方案。

是的,Cookie可能是一个解决方案,但任何人都可以在其域上使用相同的密钥创建相同的Cookie并能够访问数据。 - Shailendra Sharma

0

如果您无法完全控制客户端和服务器端,您可能希望使用客户端身份验证解决方案(例如Oauth 1或2)。 如果您可以完全控制客户端和服务器端,简单的方法是使用基本身份验证+ SSL。

我们项目的内容是: - 我们提供SSL的restful服务。 - 只有我们的合作伙伴公司可以通过互联网使用它。

我们所做的是: - 他们在请求中(是一个Ajax)使用他们的用户名/密码在他们的内部应用程序中(不是公共访问的网页) - 示例如下restful代码(您可以通过Postman进行测试):

//  to inject request 
@Context
private HttpServletRequest request; 

@GET
@Path("/testAuth")
@Produces(MediaType.APPLICATION_JSON)
public Response testAuth() {
    // TODO 
    // this is only a template for doing authentication in the near future
    String returnString = "";

    //check if authenticated
    String authorization = request.getHeader("Authorization");
    if (authorization == null ||             authorization.toUpperCase().startsWith("BASIC ") == false) {
        //no authenticated
        returnString =  "{\"testAuth\", \"need authentication\"}"; 
        return Response.status(401).entity(returnString).build();
    } else{

        String credentials =     authorization.substring("Basic".length()).trim();
        byte[] decoded = DatatypeConverter.parseBase64Binary(credentials);
        String decodedString = new String(decoded);
        String[] actualCredentials = decodedString.split(":");
        String ID = actualCredentials[0];
        String Password = actualCredentials[1];
        String Result = userAuthenticate(ID, Password);

        returnString =  "{\"testAuth\", \"" + 
            " (" + Result + ") \"}";
        return Response.status(200).entity(returnString).build();
    }   

}

即使不是公开的,这也是不好的。如果你的合作伙伴是一家公司,使用访问API密钥更有意义。注意CSRF。如果在IT角度上不匹配,永远不要混合解决方案。常见的授权和认证技术已经存在(JWT、CSRF、OAuth2...),因此没有使用基本身份验证的理由。 - kurtanamo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接