Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: 6.20.0 #1280

Merged
merged 7 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ module.exports = {
}
],
'no-buffer-constructor': [2],
'no-void': 'warn',
'comma-dangle': [0],
'import/prefer-default-export': [0]
}
Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [6.20.0](https://github.com/ali-sdk/ali-oss/compare/v6.19.0...v6.20.0) (2024-01-19)

### Features

* support v4 signature ([#1277](https://github.com/ali-sdk/ali-oss/issues/1277)) ([8bbe9b1](https://github.com/ali-sdk/ali-oss/commit/8bbe9b1ac8aa34c1564a1ad11549b67fc1db7f3a))

## [6.19.0](https://github.com/ali-sdk/ali-oss/compare/v6.18.1...v6.19.0) (2023-12-18)

### Features

* verify object names strictly when signing URLs and enabled by default ([#1265](https://github.com/ali-sdk/ali-oss/issues/1265)) ([ff03bbb](https://github.com/ali-sdk/ali-oss/pull/1265/commits/ff03bbb62b041dd34d30ca2503745ba5d7c0a216))
* verify object names strictly when signing URLs and enabled by default ([#1265](https://github.com/ali-sdk/ali-oss/issues/1265)) ([830e36e](https://github.com/ali-sdk/ali-oss/commit/830e36ea143b57e09e42d0634bc0c4d07474a2a5))

### [6.18.1](https://github.com/ali-sdk/ali-oss/compare/v6.18.0...v6.18.1) (2023-09-08)

Expand Down
85 changes: 85 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ options:
- [proxy] {String | Object}, proxy agent uri or options, default is null.
- [retryMax] {Number}, used by auto retry send request count when request error is net error or timeout. **_NOTE:_** Not support `put` with stream, `putStream`, `append` with stream because the stream can only be consumed once
- [maxSockets] {Number} Maximum number of sockets to allow per host. Default is infinity
- [authorizationV4] {Boolean} Use V4 signature. Default is false.

example:

Expand Down Expand Up @@ -435,6 +436,42 @@ for (let i = 0; i <= store.options.retryMax; i++) {
}
```

6. use V4 signature, and use optional additionalHeaders option which type is a string array, and the values inside need to be included in the header.

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

const store = new OSS({
accessKeyId: 'your access key',
accessKeySecret: 'your access secret',
bucket: 'your bucket name',
region: 'oss-cn-hangzhou',
authorizationV4: true
});

try {
const bucketInfo = await store.getBucketInfo('your bucket name');
console.log(bucketInfo);
} catch (e) {
console.log(e);
}

try {
const putObjectResult = await store.put('your bucket name', 'your object name', {
headers: {
// The headers of this request
'header1': 'value1',
'header2': 'value2'
},
// The keys of the request headers that need to be calculated into the V4 signature. Please ensure that these additional headers are included in the request headers.
additionalHeaders: ['additional header1', 'additional header2']
});
console.log(putObjectResult);
} catch (e) {
console.log(e);
}
```

## Bucket Operations

### .listBuckets(query[, options])
Expand Down Expand Up @@ -2739,6 +2776,54 @@ const url = await store.asyncSignatureUrl('ossdemo.png', {
console.log(url);
```

### .signatureUrlV4(method, expires[, request, objectName, additionalHeaders])

Generate a signed URL for V4 of an OSS resource and share the URL to allow authorized third-party users to access the resource.

parameters:

- method {string} the HTTP method
- expires {number} the signed URL will expire after the set number of seconds
- [request] {Object} optional request parameters
- [headers] {Object} headers of http requests, please make sure these request headers are set during the actual request
- [queries] {Object} queries of the signed URL, please ensure that if the query only has key, the value is set to null
- [objectName] {string} object name
- [additionalHeaders] {string[]} the keys of the request headers that need to be calculated into the V4 signature, please ensure that these additional headers are included in the request headers

Success will return signature url.

example:

```js
// GetObject
const getObjectUrl = await store.signatureUrlV4('GET', 60, undefined, 'your obejct name');
console.log(getObjectUrl);
// --------------------------------------------------
const getObjectUrl = await store.signatureUrlV4('GET', 60, {
headers: {
'Cache-Control': 'no-cache'
},
queries: {
versionId: 'version ID of your object'
}
}, 'your obejct name', ['Cache-Control']);
console.log(getObjectUrl);

// -------------------------------------------------
// PutObject
const putObejctUrl = await store.signatureUrlV4('PUT', 60, undefined, 'your obejct name');
console.log(putObejctUrl);
// --------------------------------------------------
const putObejctUrl = await store.signatureUrlV4('PUT', 60, {
headers: {
'Content-Type': 'text/plain',
'Content-MD5': 'xxx',
'Content-Length': 1
}
}, 'your obejct name', ['Content-Length']);
console.log(putObejctUrl);
```

### .putACL(name, acl[, options])

Set object's ACL.
Expand Down
1 change: 1 addition & 0 deletions lib/browser/bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ proto._bucketRequestParams = function _bucketRequestParams(method, bucket, subre
method,
bucket,
subres,
additionalHeaders: options && options.additionalHeaders,
timeout: options && options.timeout,
ctx: options && options.ctx
};
Expand Down
29 changes: 29 additions & 0 deletions lib/browser/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const { getReqUrl } = require('../common/client/getReqUrl');
const { setSTSToken } = require('../common/utils/setSTSToken');
const { retry } = require('../common/utils/retry');
const { isFunction } = require('../common/utils/isFunction');
const { getStandardRegion } = require('../common/utils/getStandardRegion');

const globalHttpAgent = new AgentKeepalive();

Expand Down Expand Up @@ -191,6 +192,34 @@ proto.authorization = function authorization(method, resource, subres, headers)
);
};

/**
* get authorization header v4
*
* @param {string} method
* @param {Object} requestParams
* @param {Object} requestParams.headers
* @param {(string|string[]|Object)} [requestParams.queries]
* @param {string} [bucketName]
* @param {string} [objectName]
* @param {string[]} [additionalHeaders]
* @return {string}
*
* @api private
*/
proto.authorizationV4 = function authorizationV4(method, requestParams, bucketName, objectName, additionalHeaders) {
return signUtils.authorizationV4(
this.options.accessKeyId,
this.options.accessKeySecret,
getStandardRegion(this.options.region),
method,
requestParams,
bucketName,
objectName,
additionalHeaders,
this.options.headerEncoding
);
};

/**
* request oss server
* @param {Object} params
Expand Down
2 changes: 2 additions & 0 deletions lib/browser/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ merge(proto, require('../common/object/getObjectUrl'));
merge(proto, require('../common/object/generateObjectUrl'));
merge(proto, require('../common/object/signatureUrl'));
merge(proto, require('../common/object/asyncSignatureUrl'));
merge(proto, require('../common/object/signatureUrlV4'));

proto.putMeta = async function putMeta(name, meta, options) {
const copyResult = await this.copy(name, name, {
Expand Down Expand Up @@ -340,6 +341,7 @@ proto._objectRequestParams = function _objectRequestParams(method, name, options
bucket: this.options.bucket,
method,
subres: options && options.subres,
additionalHeaders: options && options.additionalHeaders,
timeout: options && options.timeout,
ctx: options && options.ctx
};
Expand Down
1 change: 1 addition & 0 deletions lib/bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ proto._bucketRequestParams = function _bucketRequestParams(method, bucket, subre
method,
bucket,
subres,
additionalHeaders: options && options.additionalHeaders,
timeout: options && options.timeout,
ctx: options && options.ctx
};
Expand Down
29 changes: 29 additions & 0 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const { getReqUrl } = require('./common/client/getReqUrl');
const { setSTSToken } = require('./common/utils/setSTSToken');
const { retry } = require('./common/utils/retry');
const { isFunction } = require('./common/utils/isFunction');
const { getStandardRegion } = require('./common/utils/getStandardRegion');

const globalHttpAgent = new AgentKeepalive();
const globalHttpsAgent = new HttpsAgentKeepalive();
Expand Down Expand Up @@ -157,6 +158,34 @@ proto.authorization = function authorization(method, resource, subres, headers)
);
};

/**
* get authorization header v4
*
* @param {string} method
* @param {Object} requestParams
* @param {Object} requestParams.headers
* @param {Object} [requestParams.queries]
* @param {string} [bucketName]
* @param {string} [objectName]
* @param {string[]} [additionalHeaders]
* @return {string}
*
* @api private
*/
proto.authorizationV4 = function authorizationV4(method, requestParams, bucketName, objectName, additionalHeaders) {
return signUtils.authorizationV4(
this.options.accessKeyId,
this.options.accessKeySecret,
getStandardRegion(this.options.region),
method,
requestParams,
bucketName,
objectName,
additionalHeaders,
this.options.headerEncoding
);
};

/**
* request oss server
* @param {Object} params
Expand Down
3 changes: 2 additions & 1 deletion lib/common/client/initOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ module.exports = function (options) {
headerEncoding: 'utf-8',
refreshSTSToken: null,
refreshSTSTokenInterval: 60000 * 5,
retryMax: 0
retryMax: 0,
authorizationV4: false // 启用v4签名,默认关闭
},
options
);
Expand Down
1 change: 1 addition & 0 deletions lib/common/object/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ merge(proto, require('./generateObjectUrl'));
merge(proto, require('./getObjectUrl'));
merge(proto, require('./signatureUrl'));
merge(proto, require('./asyncSignatureUrl'));
merge(proto, require('./signatureUrlV4'));
70 changes: 70 additions & 0 deletions lib/common/object/signatureUrlV4.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const dateFormat = require('dateformat');
const urlUtil = require('url');

const signHelper = require('../../common/signUtils');
const { setSTSToken } = require('../utils/setSTSToken');
const { isFunction } = require('../utils/isFunction');
const { getStandardRegion } = require('../utils/getStandardRegion');

const proto = exports;

/**
* signatureUrlV4
*
* @param {string} method
* @param {number} expires
* @param {Object} [request]
* @param {Object} [request.headers]
* @param {Object} [request.queries]
* @param {string} [objectName]
* @param {string[]} [additionalHeaders]
*/
proto.signatureUrlV4 = async function signatureUrlV4(method, expires, request, objectName, additionalHeaders) {
const headers = (request && request.headers) || {};
const queries = { ...((request && request.queries) || {}) };
const date = new Date();
const formattedDate = dateFormat(date, "UTC:yyyymmdd'T'HHMMss'Z'");
const onlyDate = formattedDate.split('T')[0];
const fixedAdditionalHeaders = signHelper.fixAdditionalHeaders(additionalHeaders);
const region = getStandardRegion(this.options.region);

if (fixedAdditionalHeaders.length > 0) {
queries['x-oss-additional-headers'] = fixedAdditionalHeaders.join(';');
}
queries['x-oss-credential'] = `${this.options.accessKeyId}/${onlyDate}/${region}/oss/aliyun_v4_request`;
queries['x-oss-date'] = formattedDate;
queries['x-oss-expires'] = expires;
queries['x-oss-signature-version'] = 'OSS4-HMAC-SHA256';

if (this.options.stsToken && isFunction(this.options.refreshSTSToken)) {
await setSTSToken.call(this);
}

if (this.options.stsToken) {
queries['x-oss-security-token'] = this.options.stsToken;
}

const canonicalRequest = signHelper.getCanonicalRequest(
method,
{
headers,
queries
},
this.options.bucket,
objectName,
fixedAdditionalHeaders
);
const stringToSign = signHelper.getStringToSign(region, formattedDate, canonicalRequest);

queries['x-oss-signature'] = signHelper.getSignatureV4(this.options.accessKeySecret, onlyDate, region, stringToSign);

const signedUrl = urlUtil.parse(
this._getReqUrl({
bucket: this.options.bucket,
object: objectName
})
);
signedUrl.query = { ...queries };

return signedUrl.format();
};
Loading
Loading