Cloudfront签名cookie和同时访问S3存储桶中多个路径

6

我正在使用签名的Cookie来通过Cloudfront在我的基于Web的应用程序中限制访问S3存储桶中的内容。

例如,用户可以通过http://mycf.example.com/folder1访问s3://mys3/folder1中的内容。但他将无法访问同一级别的其他文件夹中的内容。

这里是我的问题:

用户使用我的Web应用程序访问位于s3://mys3/user1中的内容。他打开另一个浏览器窗口来访问同事的s3://mys3/buddy中的内容。第二个浏览器将下载新的签名Cookie并覆盖user1的那个。现在,如果他切换回第一个窗口,他将遇到“Access denied”问题。

如何避免这个问题的最佳实践?例如,是否可以在策略的URL中指定多个路径?

2个回答

8
您不能在策略中指定多个路径。如果您的文件夹结构与通配符值不匹配,则可能需要为每个路径生成签名cookie并相应地对其进行范围限制。
您可以指定cookie适用于哪个路径。在设置Cookie时,将路径指定为/ user1以供第一个用户使用,并将路径指定为/ user2以供第二个用户使用。然后,当路径匹配时,您的浏览器将仅发送它们。

http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-setting-signed-cookie-canned-policy.html#private-content-canned-policy-signature-cookies


2
我认为你误解了我的问题。User1需要同时访问/user1/user2。据我所知,策略中的路径只能是/user1/user2其中之一。 - Anthony Kong
这不是一个答案。问题是关于为同一浏览器设置多个 cookie 到不同路径的问题。而不是为两个不同浏览器上的不同用户设置单个 cookie,这似乎是这个“答案”所假设的“第二个”用户的概念。 - Seivan
2
@AnthonyKong 不,他理解了你的问题,他的答案很可能是正确的。如果在cookie中指定不同的路径,您可以同时保留两组cookie,从而允许同时访问不同的存储桶。请参阅此相关cookie问题。 - Cerin
我一开始误读了这个,认为它不能解决我的用例,但它确实有效。我已经使用2个路径的cookie进行了测试和验证。能够在CloudFront中仅访问这两个路径,而其他所有内容都受到保护。令人困惑的是,我们需要使用相同的cookie名称设置不同的路径。我实际上并不知道这是可能的。因此,对于每个唯一的路径,您可以使用通配符,并将cookie路径设置为相同的内容,减去通配符。 - George

0

由于我曾经遇到过这个问题,也许这篇文章可以帮助其他人避免同样的痛苦。必须使用自定义cookie策略而不是通用的策略来支持多个目录。对于每个目录,您需要设置3个cookie(CloudFront-Key-Pair-Id、CloudFront-Policy和CloudFront-Signature)。对于每个目录,您需要使用相同名称但不同路径的3个cookie(对我来说,设置相同的cookie名称超过一次有点违反直觉,但我已经测试过它可以工作)。另一个困难的部分是您必须确保cloudfront域名与您的域名匹配,否则您无法传递cookie。在本地主机上,我使用host文件创建虚假的DNS查找进行测试(将127.0.0.1映射到myapp.com,而cloudfront必须使用类似cdn.myapp.com的某个域名)。

<dependencyManagement>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>bom</artifactId>
            <version>2.16.60</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-bom</artifactId>
            <version>1.12.1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-cloudfront</artifactId>
</dependency>


@GetMapping("/cloudfront-cookies")
public String getCloudfrontCookies(HttpServletResponse resp) {
    
    String path1 =  "/protected/user1/";
    String path2 =  "/protected/user2/";
    
    setCookies(resp, path1, distributionDomain, "https");
    setCookies(resp, path2, distributionDomain, "https");
    return "success";
}

protected void setCookies(HttpServletResponse resp, String path, String domain, String proto) {
    Date start = new Date(System.currentTimeMillis());
    Date expiration = new Date(System.currentTimeMillis()+expirationSeconds*1000);
    InputStream is = this.getClass().getResourceAsStream(privateKeyFilePath);
    try {
        PrivateKey privateKey = RSA.privateKeyFromPKCS8(IOUtils.toByteArray(is));

        String url = proto + "://" + domain + path + "*";
        CookiesForCustomPolicy  cp =  CloudFrontCookieSigner.getCookiesForCustomPolicy(
                url,
                privateKey, 
                keyPairId,
                expiration, 
                start,
                null);
        
        Entry<String,String> kpi = cp.getKeyPairId();
        Entry<String,String> pol = cp.getPolicy();
        Entry<String,String> sig = cp.getSignature();
        
        resp.addCookie(getCookie(pol.getKey(),pol.getValue(),path,domain));
        resp.addCookie(getCookie(sig.getKey(),sig.getValue(),path,domain));
        resp.addCookie(getCookie(kpi.getKey(),kpi.getValue(),path,domain));         
        
    }catch(Exception e) {
        e.printStackTrace();
    }
    finally {
        try {is.close();} catch(IOException ignore) {}
    }

}    

protected Cookie getCookie(String key, String value, String path, String domain) {
    Cookie c = new Cookie(key,value);
    c.setPath(path); 
    return c;
}

一些属性是通过属性文件设置的,我从文件系统中获取证书。其余内容请遵循 AWS 签名 cookie 文档。

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