全部產品
Search
文件中心

Object Storage Service:保留原則(WORM)

更新時間:Dec 10, 2025

OSS保留原則具有WORM(Write Once Read Many)特性,滿足使用者以不可刪除、不可篡改方式儲存和使用資料。如果您希望指定時間內任何使用者(包括資源擁有者)均不能修改和刪除OSS某個Bucket中的Object,您可以選擇為Bucket配置保留原則。在保留原則指定的Object保留時間到期之前,僅支援在Bucket中上傳和讀取Object。Object保留時間到期後,才可以修改或刪除Object。

使用情境

OSS保留原則支援的WORM特性符合美國證券交易委員會(SEC)和金融業監管局(FINRA)的合規要求。適用於金融、保險、醫學、證券、日誌資料等保審查等情境。

說明

OSS已通過Cohasset Associates審計認證,滿足SEC Rule 17a-4(f)、FINRA 4511、CFTC 1.31等合規要求。更多資訊,請參見OSS Cohasset Assessment Report

前提條件

確保需要設定保留原則的Bucket的版本控製為開啟或未開啟,暫停不支援設定保留原則。關於版本控制的更多資訊,請參見版本控制

注意事項

  • 目前僅支援針對Bucket層級設定保留原則。

  • 同一個Bucket中,不支援同時開通OSS-HDFS服務並設定保留原則。

  • Bucket內的Object在保留原則生效期間,可通過設定生命週期規則進行儲存類型轉化,在保證合規性的前提下,降低儲存成本。

規則說明

  • 生效規則

    當基於時間的保留原則建立後,該策略預設處於InProgress狀態,有效期間為24小時。在此期間,Bucket資源處於保護狀態。

    • 啟動保留原則24小時內

      • 如果24小時內未提交鎖定保留原則,則Bucket所有者以及授權使用者可以刪除該策略。

      • 如果24小時內已提交鎖定保留原則,則不允許刪除該策略,且無法縮短保護周期,僅可延長保護周期。同時,Bucket內的資料處於保護狀態,嘗試刪除或修改這些資料時,OSS將返回409 FileImmutable錯誤資訊。

    • 啟動保留原則24小時後

      如果超過24小時未鎖定該保留原則,則該策略自動失效,您可以刪除該策略。

  • 刪除規則

    • 基於時間的保留原則是Bucket的一種Metadata屬性。當刪除某個Bucket時,該Bucket對應的保留原則也會被刪除。

    • 啟動保留原則24小時內,如果該保留原則未提交鎖定,則Bucket所有者以及授權使用者可以刪除該策略。

    • 如果Bucket內有Object處於保護周期內,那麼您將無法刪除保留原則,同時也無法刪除Bucket。

  • 規則樣本

    假設您在2022年06月01日為某個Bucket建立了保護周期為30天的保留原則,且該策略在建立後進入鎖定狀態。您在不同時間上傳了file1.txt、file2.txt、file3.txt三個Object。具體上傳時間及到期時間如下:

    Object名稱

    上傳時間

    Object到期時間

    file1.txt

    2022年04月01日

    2022年04月30日

    file2.txt

    2022年06月01日

    2022年06月30日

    file3.txt

    2022年09月01日

    2022年09月30日

操作方式

使用OSS控制台

  1. 建立保留原則。

    1. 登入OSS管理主控台

    2. 單擊Bucket 列表,然後單擊目標Bucket名稱。

    3. 在左側導覽列,選擇數據安全>保留策略

    4. 保留策略頁面,單擊創建策略

    5. 創建策略對話方塊,指定保留周期

      說明

      保留周期以天為單位,取值範圍為1~25,550。

    6. 單擊確定

      說明

      策略狀態為待鎖定。該狀態的有效期間為24小時。在此期間,相關Bucket資源將受到保護。若您決定不保留該策略,可在24小時內將其刪除。

  2. 鎖定保留原則。

    1. 單擊鎖定

    2. 在彈出的對話方塊,單擊確定

      重要

      鎖定後無法修改或刪除保留原則,且在保留周期內無法修改或刪除Bucket中的資料。

  3. (可選)修改保留周期。

    1. 單擊編輯

    2. 在彈出的對話方塊,修改保留周期。

      重要

      只能延長保留周期,無法縮短。

使用阿里雲SDK

以下僅列舉常見SDK的設定保留原則的程式碼範例。關於其他SDK的設定保留原則程式碼範例,請參見SDK簡介

Java

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.InitiateBucketWormRequest;
import com.aliyun.oss.model.InitiateBucketWormResult;

public class Demo {

    public static void main(String[] args) throws Exception {
        // Endpoint以華東1(杭州)為例,其它Region請按實際情況填寫。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填寫Bucket名稱,例如examplebucket。
        String bucketName = "examplebucket";
        // 填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為cn-hangzhou。
        String region = "cn-hangzhou";

        // 建立OSSClient執行個體。
        // 當OSSClient執行個體不再使用時,調用shutdown方法以釋放資源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
        OSS ossClient = OSSClientBuilder.create()
        .endpoint(endpoint)
        .credentialsProvider(credentialsProvider)
        .clientConfiguration(clientBuilderConfiguration)
        .region(region)               
        .build();

        try {
            // 建立InitiateBucketWormRequest對象。
            InitiateBucketWormRequest initiateBucketWormRequest = new InitiateBucketWormRequest(bucketName);
            // 指定Object保護天數為1天。
            initiateBucketWormRequest.setRetentionPeriodInDays(1);

            // 建立合規保留原則。
            InitiateBucketWormResult initiateBucketWormResult = ossClient.initiateBucketWorm(initiateBucketWormRequest);

            // 查看合規保留原則ID。
            String wormId = initiateBucketWormResult.getWormId();
            System.out.println(wormId);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

PHP

<?php

// 引入自動負載檔案 載入依賴庫
require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

// 定義命令列參數描述
$optsdesc = [
    "region" => ['help' => 'The region in which the bucket is located', 'required' => True], // 地區是必填項 儲存空間所在的地區
    "endpoint" => ['help' => 'The domain names that other services can use to access OSS', 'required' => False], // 終端節點是可選項 其他服務可以用來訪問OSS的網域名稱
    "bucket" => ['help' => 'The name of the bucket', 'required' => True], // 儲存空間名稱是必填項
];

// 產生長選項列表 用於解析命令列參數
$longopts = \array_map(function ($key) {
    return "$key:"; // 每個參數後面加冒號 表示需要值
}, array_keys($optsdesc));

// 解析命令列參數
$options = getopt("", $longopts); 

// 檢查必填參數是否缺失
foreach ($optsdesc as $key => $value) {
    if ($value['required'] === True && empty($options[$key])) {
        $help = $value['help'];
        echo "Error: the following arguments are required: --$key, $help"; // 提示使用者缺少必填參數
        exit(1); 
    }
}

// 擷取命令列參數值
$region = $options["region"]; // 儲存空間所在地區
$bucket = $options["bucket"]; // 儲存空間名稱

// 使用環境變數載入憑證資訊 AccessKeyId 和 AccessKeySecret
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

// 使用SDK的預設配置
$cfg = Oss\Config::loadDefault();

// 設定憑證提供者
$cfg->setCredentialsProvider($credentialsProvider);

// 設定地區
$cfg->setRegion($region);

// 如果提供了終端節點 則設定終端節點
if (isset($options["endpoint"])) {
    $cfg->setEndpoint($options["endpoint"]);
}

// 建立OSS用戶端執行個體
$client = new Oss\Client($cfg);

// 建立初始化儲存空間合規保留原則的請求對象 設定保留天數為3天
$request = new Oss\Models\InitiateBucketWormRequest(
    bucket: $bucket, 
    initiateWormConfiguration: new Oss\Models\InitiateWormConfiguration(
        retentionPeriodInDays: 3 // 保留天數
));

// 調用initiateBucketWorm方法初始化儲存空間的合規保留原則
$result = $client->initiateBucketWorm($request);

// 列印返回結果
printf(
    'status code:' . $result->statusCode . PHP_EOL . // HTTP響應狀態代碼
    'request id:' . $result->requestId . PHP_EOL . // 請求的唯一標識
    'worm id:' . $result->wormId // 合規保留原則的ID
);

Node.js

const OSS = require('ali-oss');

const client = new OSS({
  // yourregion填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為oss-cn-hangzhou。
  region: 'yourregion',
  // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,  
  authorizationV4: true,
  // yourBucketName填寫Bucket名稱。
  bucket: 'yourBucketName',
});
// 建立保留原則。
async function initiateBucketWorm() {
 // yourbucketname填寫儲存空間名稱。
  const bucket = 'yourbucketname'
  // 指定Object保護天數。
  const days = '<Retention Days>'
    const res = await client.initiateBucketWorm(bucket, days)
  console.log(res.wormId)
}

initiateBucketWorm()

Python

import argparse
import alibabacloud_oss_v2 as oss

# 建立命令列參數解析器,並描述指令碼用途:樣本展示如何初始化OSS儲存空間的WORM配置
parser = argparse.ArgumentParser(description="initiate bucket worm sample")

# 添加命令列參數 --region,表示儲存空間所在的地區,必需參數
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# 添加命令列參數 --bucket,表示要操作的儲存空間名稱,必需參數
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# 添加命令列參數 --endpoint,表示其他服務可用來訪問OSS的網域名稱,非必需參數
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# 添加命令列參數 --retention_period_in_days,表示對象保留天數,必需參數
parser.add_argument('--retention_period_in_days', help='The number of days for which objects can be retained.', required=True)

def main():
    # 解析命令列提供的參數,擷取使用者輸入的值
    args = parser.parse_args()

    # 從環境變數中載入訪問OSS所需的認證資訊,用於身分識別驗證
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 使用SDK的預設配置建立設定物件,並設定認證提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    cfg.region = args.region

    # 如果提供了自訂endpoint,則更新設定物件中的endpoint屬性
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # 使用上述配置初始化OSS用戶端,準備與OSS互動
    client = oss.Client(cfg)

    # 發送請求以初始化指定儲存空間的WORM配置
    result = client.initiate_bucket_worm(oss.InitiateBucketWormRequest(
        bucket=args.bucket,  # 儲存空間名
        initiate_worm_configuration=oss.InitiateWormConfiguration(
            retention_period_in_days=int(args.retention_period_in_days),  # 對象保留天數,轉換為整數
        ),
    ))

    # 列印操作結果的狀態代碼、請求ID和WORM ID,以便確認請求狀態
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' worm id: {result.worm_id}'
    )

# 當此指令碼被直接執行時,調用main函數開始處理邏輯
if __name__ == "__main__":
    main()  # 指令碼進入點,控製程序流程從這裡開始

Go

package main

import (
	"log"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
	// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
	if err != nil {
		log.Fatalf("Error creating credentials provider: %v", err)
	}

	// 建立OSSClient執行個體。
	// yourEndpoint填寫Bucket對應的Endpoint,以華東1(杭州)為例,填寫為https://oss-cn-hangzhou.aliyuncs.com。其它Region請按實際情況填寫。
	// yourRegion填寫Bucket所在地區,以華東1(杭州)為例,填寫為cn-hangzhou。其它Region請按實際情況填寫。
	clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
	clientOptions = append(clientOptions, oss.Region("yourRegion"))
	// 設定簽名版本
	clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
	client, err := oss.New("yourEndpoint", "", "", clientOptions...)
	if err != nil {
		log.Fatalf("Error creating OSS client: %v", err)
	}

	// 填寫待配置合規保留原則的Bucket名稱。
	bucketName := "<yourBucketName>"

	// 指定Object保護天數為60天。
	result, err := client.InitiateBucketWorm(bucketName, 60)
	if err != nil {
		log.Fatalf("Error initiating bucket WORM: %v", err)
	}

	log.Println("WORM policy initiated successfully:", result)
}

C++

#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* 初始化OSS帳號資訊。*/
            
    /* yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。*/
    std::string Endpoint = "yourEndpoint";
    /* yourRegion填寫Bucket所在地區對應的Region。以華東1(杭州)為例,Region填寫為cn-hangzhou。*/
    std::string Region = "yourRegion";
    /* 填寫Bucket名稱,例如examplebucket。*/
    std::string BucketName = "examplebucket";

      /* 初始化網路等資源。*/
      InitializeSdk();

      ClientConfiguration conf;
      conf.signatureVersion = SignatureVersionType::V4;
      /* 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);
  
      /* 建立保留原則,指定Object保護天數為1天。*/
      auto outcome = client.InitiateBucketWorm(InitiateBucketWormRequest(BucketName, 1));

      if (outcome.isSuccess()) {      
            std::cout << " InitiateBucketWorm success " << std::endl;
            std::cout << "WormId:" << outcome.result().WormId() << std::endl;
      }
      else {
        /* 異常處理。*/
        std::cout << "InitiateBucketWorm fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return -1;
      }

      /* 釋放網路等資源。*/
      ShutdownSdk();
      return 0;
}

使用命令列工具ossutil

您可以使用命令列工具ossutil來建立WORM策略,ossutil的安裝請參見安裝ossutil

以下命令用於在儲存空間 examplebucket 中建立一條新的 WORM策略,並將WORM的保留期設定為 365 天。

ossutil api initiate-bucket-worm --bucket examplebucket --initiate-worm-configuration "{\"RetentionPeriodInDays\":\"365\"}"

關於該命令的更多資訊,請參見initiate-bucket-worm

相關API

以上操作方式底層基於API實現,如果您的程式自訂要求較高,您可以直接發起REST API請求。直接發起REST API請求需要手動編寫代碼計算簽名。更多資訊,請參見InitiateBucketWorm

與版本控制協同工作

在為Veeam等備份系統提供資料版本保護、追溯電路設計圖等資產的修改記錄,或滿足金融行業合規歸檔要求的情境中,通常需要允許資料持續更新同時確保其所有歷史版本都不可篡改或刪除。為實現這一目標,可為 Bucket 同時建立保留原則並開啟版本控制。版本控制確保對象在被覆蓋或刪除時,其舊版本會作為歷史版本保留,而非物理刪除。而保留原則則為Bucket內所有對象版本設定保護期,在此期間內,任何版本都無法被刪除或修改。

版本控制功能與保留原則功能可同時配置,協同工作遵循以下原則:

  • 功能開啟順序:版本控制與保留原則功能的開啟順序無約束要求,可根據業務需求靈活配置。

  • 狀態轉換約束

    • 開啟保留原則後,版本控制狀態不允許從"開啟"轉為"暫停"。

    • 版本控制處於"暫停"狀態的Bucket可以開啟保留原則,開啟後版本控制狀態可改為"開啟"。

  • 對象版本保護機制

    • 保留原則對Object的所有版本提供保護,在保護期內不允許刪除或篡改任何版本。

    • 允許上傳同名Object產生新版本,但新版本同樣受保留原則保護。

    • 保留原則不作用於刪除標記,刪除標記的清理不受保留原則限制。

  • 資料複製協同

    • 源Bucket與目標Bucket均支援獨立的版本控制和保留原則配置。

    • 複製過程中的版本資訊正常傳輸,目標Bucket根據自身配置進行版本管理。

    • 源Bucket的版本刪除操作不會同步到已開啟保留原則的目標Bucket。

常見問題

保留原則與版本控制同時開啟時,如何處理Object的刪除操作?

保留原則與版本控制同時開啟時,刪除Object的行為如下:

  • 刪除操作會產生刪除標記(Delete Marker),但不會實際刪除Object的歷史版本。

  • 保留原則不對刪除標記進行保護,刪除標記可以被正常處理。

  • 所有Object版本在保留原則保護期內均不可刪除,即使存在刪除標記。

  • 生命週期管理可以正常清理懸空狀態的刪除標記,但無法刪除受保留原則保護的Object版本。

開啟保留原則後,版本控制狀態是否還可以修改?

開啟保留原則後,版本控制狀態的修改存在以下約束:

  • 開啟→暫停:若版本控制狀態為"開啟",鎖定保留原則後不能轉換為"暫停"狀態。

  • 暫停→開啟:若版本控制狀態為"暫停",開啟保留原則後仍可轉換為"開啟"狀態。

  • 未開啟→開啟:未開啟版本控制的Bucket在配置保留原則後可以開啟版本控制。

保留原則與版本控制協同使用是否會增加儲存成本?

會產生額外的儲存成本,主要體現在:

  • 保留原則保護期內所有Object版本都會被保留,無法通過生命週期規則刪除。

  • 版本累積可能導致儲存空間大幅增加,特別是頻繁更新的Object。

  • 建議合理設定保留原則保留期限,並通過生命週期規則管理儲存類型轉換以最佳化成本。

保留原則有哪些優勢?

保留原則提供資料合規儲存,保護周期內資料不可刪除或修改。相比之下,RAM policy和Bucket Policy保護的資料可能被修改或刪除。

什麼情況下需要設定保留原則?

當需要長期儲存且不允許修改或刪除的重要資料,如醫學檔案、技術檔案、合約文書等,建議在指定Bucket內開啟保留原則。

是否支援取消保留原則?

是否支援取消保留原則取決於其狀態。

  • 未提交鎖定:Bucket擁有者和授權使用者可刪除。

  • 已提交鎖定:任何人均無法刪除。

是否支援針對Object設定保留原則?

僅支援針對Bucket設定保留原則,不支援目錄或單個對象。

如何計算Object的保留時間

結合Object的最後修改時間和保留原則的保留周期計算。例如,Bucket A的保留原則為10天,Object最後修改時間為2022年02月15日,則保留時間為2022年02月25日。

如何刪除已開啟保留原則的Bucket ?

  • 未儲存Object:可直接刪除。

  • 已儲存Object且過保護期:先刪除所有Object,再刪除Bucket。

  • 已儲存Object且在保護期內:無法刪除。

如果OSS欠費,但仍有Object處於保留原則的保護期內,這些Object會被保留嗎?

請注意:欠費情況下,即使Bucket內的Object處於保留原則的保護期內,阿里雲仍然會根據欠費停服規則進行資料刪除。

授權的RAM使用者是否可以設定保留原則?

保留原則API已開放,支援RAM policy。授權的RAM使用者可通過控制台、API、SDK等方式建立或刪除保留原則。