我正在尝试使用Java客户端在Azure上设置CORS属性。执行代码后,我运行HTML5代码来上传文件,并在chrome JavaScript控制台中遇到以下错误:


  最大块大小= 47276
  
  总块数= 1
  
  https:myacc.blob.core.windows.net/mycon/ch1.jpg?sr = c&sv = 2015-04-05&sig = djbVxIBlyVy18bV0SkqNSLql1n9efAVcYnGy3VsGKis%3D&si = champ
  
  当前文件指针= 0字节读取= 47276
  
  区块ID =区块000000
  
  https:myacc.blob.core.windows.net/mycon/ch1.jpg?sr = c&sv = 2015-0…kqNSLql1n9efAVcYnGy3VsGKis%3D&si = champ&comp = block&blockid = YmxvY2stMDAwMDAw
  
  无法加载资源:服务器的响应状态为403(未启用CORS或找不到与此请求匹配的规则。)
  
  XMLHttpRequest无法加载
  https:myacc.blob.core.windows.net/mycon/ch1.jpg?sr = c&sv = 2015-0…kqNSLql1n9efAVcYnGy3VsGKis%3D&si = heath&comp = block&blockid = YmxvY2stMDAwMDAw。
  
  对预检请求的响应未通过访问控制检查:请求的请求上不存在“ Access-Control-Allow-Origin”标头
  资源。因此,不允许访问源“ file://”。的
  响应的HTTP状态码为403。


我想知道的是,如果Java客户端执行成功,为什么它没有设置CORS?另外,如何验证规则策略“ champ”是否配置正确,我生成的SAS是否正确以及是否创建了CORS属性?

这是Java客户端代码:

public class CORS_and_SAS {
public static void main(String[] args) {
    // Define the connection-string with your values
    final String storageConnectionString ="DefaultEndpointsProtocol=http;" + "AccountName=myacc;" + "AccountKey=B2q4AGp6YoRsTREXIkOv3e/Sxf46YzqzfnM9F8U+o7VA5Y3EiKc+CuritnvuyZxGXKNOQ5nJy2KfkniF970on1dQ==";
    try {
        // Retrieve storage account from connection-string.
        CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectionString);

        // Create the blob client.
       CloudBlobClient blobClient = storageAccount.createCloudBlobClient();

       // Get a reference to a container.
       // The container name must be lower case
       CloudBlobContainer container = blobClient.getContainerReference("mycon");

       // Create the container if it does not exist.
        //container.createIfNotExists();
       // Set CORS support
       //ServiceProperties blobServiceProperties = blobClient.GetServiceProperties();
       ServiceProperties propers = getCORS();
       blobClient.uploadServiceProperties(propers);
        SharedAccessBlobPolicy policy = new SharedAccessBlobPolicy();
          GregorianCalendar calendar =
             new GregorianCalendar(TimeZone.getTimeZone("UTC"));
          calendar.setTime(new Date());
          policy.setSharedAccessStartTime(calendar.getTime()); //Immediately applicable
          calendar.add(Calendar.HOUR, 3000); //Applicable time-span is 3000 hours
          policy.setSharedAccessExpiryTime(calendar.getTime());
          policy.setPermissions(EnumSet.of(SharedAccessBlobPermissions.READ,
             SharedAccessBlobPermissions.WRITE, SharedAccessBlobPermissions.DELETE,
             SharedAccessBlobPermissions.LIST));
          BlobContainerPermissions containerPermissions = new BlobContainerPermissions();
          //Private container with no access for anonymous users
          containerPermissions.setPublicAccess(BlobContainerPublicAccessType.OFF);
          //Name the shared access policy: heath
          containerPermissions.getSharedAccessPolicies().put("champ", policy);
          container.uploadPermissions(containerPermissions);
          //Generate the policy SAS string for heath access
          String sas = container.generateSharedAccessSignature(
             new SharedAccessBlobPolicy(),"champ");
          System.out.println("The stored access policy signature:");
          System.out.println(sas);
    } catch (Exception e) {
        // Output the stack trace.
        e.printStackTrace();
    }
}

private static ServiceProperties getCORS() {
    // TODO Auto-generated method stub
    ServiceProperties propers = new ServiceProperties();
    CorsProperties corsprop = propers.getCors();

    CorsRule cr = new CorsRule();

    List<String> allowedHeaders = new ArrayList<String>();
    allowedHeaders.add("x-ms-*");
    List<String> exposedHeaders = new ArrayList<String>();
    exposedHeaders.add("x-ms-*");

    cr.setAllowedHeaders(allowedHeaders);
    cr.setExposedHeaders(exposedHeaders);
    EnumSet<CorsHttpMethods> allowedMethod = EnumSet.of(CorsHttpMethods.PUT,CorsHttpMethods.GET,CorsHttpMethods.POST,CorsHttpMethods.HEAD,CorsHttpMethods.DELETE);
    //EnumSet<CorsHttpMethods> allowedMethod1 = EnumSet.of(CorsHttpMethods.GET);
    cr.setAllowedMethods(allowedMethod);

    List<String> allowedOrigin = new ArrayList<String>();
    allowedOrigin.add("*");
    cr.setAllowedOrigins(allowedOrigin);
    cr.setMaxAgeInSeconds(600);

    corsprop.getCorsRules().add(cr);

    //corsprop.getCorsRules().add(cr);
    propers.setCors(corsprop);
    return propers;
}
}

最佳答案

我试图重现该问题,并仔细检查了JS控制台中的Java客户端代码和错误。我发现问题是由使用blob容器共享访问签名作为上传文件的URL引起的。

这是您修改的Java代码。

private static final String accountName = "<account-name>";
private static final String accountKey = "<account-key>";
private static final String connectionStringTemplate = "DefaultEndpointsProtocol=http;AccountName=%s;AccountKey=%s";
private static final String containerName = "<block-blob-container-name>";
private static final String blobFileName = "<blob-file-name>";

public static void main(String[] args) throws InvalidKeyException, URISyntaxException, StorageException {
    String connectionString = String.format(connectionStringTemplate, accountName, accountKey);
    CloudStorageAccount account = CloudStorageAccount.parse(connectionString);
    CloudBlobClient blobClient = account.createCloudBlobClient();
    /*
     * Enable CORS
     */
    // CORS should be enabled once at service startup
    // Given a BlobClient, download the current Service Properties
    ServiceProperties blobServiceProperties = blobClient.downloadServiceProperties();
    // Enable and Configure CORS
    CorsProperties cors = new CorsProperties();
    CorsRule corsRule = new CorsRule();
    List<String> allowedHeaders = new ArrayList<String>();
    allowedHeaders.add("*");
    EnumSet<CorsHttpMethods> allowedMethods = EnumSet.of(CorsHttpMethods.PUT, CorsHttpMethods.GET, CorsHttpMethods.HEAD, CorsHttpMethods.POST);
    System.out.println(Arrays.toString(allowedMethods.toArray()));
    List<String> allowedOrigins = new ArrayList<String>();
    allowedOrigins.add("*");
    List<String> exposedHeaders = new ArrayList<String>();
    exposedHeaders.add("*");
    int maxAgeInSeconds = 1800;
    corsRule.setAllowedHeaders(allowedHeaders);
    corsRule.setAllowedMethods(allowedMethods);
    corsRule.setAllowedOrigins(allowedOrigins);
    corsRule.setExposedHeaders(exposedHeaders);
    corsRule.setMaxAgeInSeconds(maxAgeInSeconds);
    cors.getCorsRules().add(corsRule);
    blobServiceProperties.setCors(cors);
    // Commit the CORS changes into the Service Properties
    blobClient.uploadServiceProperties(blobServiceProperties);
    /*
     * Generate the SAS for the uploading url
     */
    CloudBlobContainer container = blobClient.getContainerReference(containerName);
    CloudBlockBlob blockBlob = container.getBlockBlobReference(blobFileName);
    SharedAccessBlobPolicy sharedAccessBlobPolicy = new SharedAccessBlobPolicy();
    GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
    calendar.setTime(new Date());
    sharedAccessBlobPolicy.setSharedAccessStartTime(calendar.getTime());
    calendar.add(Calendar.HOUR, 1);
    sharedAccessBlobPolicy.setSharedAccessExpiryTime(calendar.getTime());
    sharedAccessBlobPolicy.setPermissions(EnumSet.of(SharedAccessBlobPermissions.WRITE));
    String sas = blockBlob.generateSharedAccessSignature(sharedAccessBlobPolicy, null);
    System.out.println(sas);
    String blobUploadSASURL = String.format("https://%s.blob.core.windows.net/%s/%s?%s", accountName, containerName, blobFileName, sas);
    System.out.println(blobUploadSASURL);
}


运行代码并以https://<account-name>.blob.core.windows.net/<container>/<blob-file-name>?sig=<SIG>&st=2015-12-01T11%3A51%3A20Z&se=2015-12-01T12%3A51%3A20Z&sv=2015-04-05&sp=r&sr=b形式获取上传的blob SAS Url

使用标头为x-ms-blob-type: BlockBlob的URL的PUT方法可成功上传文件。

提供了更多详细信息和示例ajax代码来执行此操作,请参阅Azure存储团队http://blogs.msdn.com/b/windowsazurestorage/archive/2014/02/03/windows-azure-storage-introducing-cors.aspx的博客。

07-24 09:50
查看更多