angularjs 只允许一种身份验证机制;只允许X-Amz-Algorithm查询参数..?

i1icjdpr  于 12个月前  发布在  Angular
关注(0)|答案(9)|浏览(256)

我正在尝试向amazonS3预签名的URL发送PUT请求。即使我只有一个PUT请求,我的请求似乎也被调用了两次。第一个请求返回200 OK,第二个返回400 Bad Request
下面是我的代码:

var req = {
    method: 'PUT',
    url: presignedUrl,
    headers: {
        'Content-Type': 'text/csv'
    },
    data: <some file in base64 format>
};

$http(req).success(function(result) {
    console.log('SUCCESS!');
}).error(function(error) {
    console.log('FAILED!', error);
});

字符串
400 Bad Request错误详细信息:

<?xml version="1.0" encoding="UTF-8"?>
<Error>
   <Code>InvalidArgument</Code>
   <Message>Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter, Signature query string parameter or the Authorization header should be specified</Message>
   <ArgumentName>Authorization</ArgumentName>
   <ArgumentValue>Bearer someToken</ArgumentValue>
   <RequestId>someRequestId</RequestId>
   <HostId>someHostId</HostId>
</Error>


我不明白的是,为什么它返回400?以及解决方法是什么?

eqzww0vc

eqzww0vc1#

您的客户端可能正在发送一个使用Authorization标头的初始请求,该请求将使用302进行响应。该响应包括一个具有Signature参数的Location标头。问题在于,初始请求的标头将被复制到后续的重定向请求中,因此它包含Authorization和Signature。如果您从后续请求中删除Authorization,则应该没有问题。
这发生在我身上,但在Java / HttpClient环境中。我可以用Java提供解决方案的细节,但不幸的是不是AngularJS。

hwazgwia

hwazgwia2#

对于Google用户,如果您通过Cloudfront发送签名(签名v4)的S3请求,并且您的Cloudfront Origin设置中的“Restrict Bucket Access”设置为“Yes”,Cloudfront将向您的请求添加Authorization标头,您将收到此错误。由于您已经对请求进行了签名,因此您应该能够关闭此设置,而不会牺牲任何安全性。

bd1hkmkf

bd1hkmkf3#

我知道这可能太晚了,但就像@mlohbihler说的,对我来说,这个错误的原因是我在Angular中设置的http拦截器发送的Authorization头。本质上,我没有正确过滤AWS S3域,以避免它自动获取JWT授权头。

lc8prwob

lc8prwob4#

此外,400“无效参数”可能是由于S3::Presigner的配置/凭据错误而出现的,该Presigner正在对URL进行预签名以开始。一旦您通过400,您可能会遇到501“未实现”响应,就像我一样。通过指定Content-Length头(指定here作为必需的头)可以解决它。希望这有助于@arjuncc,它解决了我在测试带有预签名URL的S3图像上传时遇到的 Postman 问题。

0lvr5msh

0lvr5msh5#

消息说只允许一个身份验证。这可能是你在URL中发送一个作为auth参数,另一个作为Authorization头。

cx6n0qe3

cx6n0qe36#

我也面临着同样的错误,所以删除授权,你可以这样做,这将工作!

const uploadAxios = axios.create({
    headers: {
      Accept: 'application/json',
      Authorization: undefined,
    },
  });

  const uploadFileToPresignedUrl = async (uploadUrl, fileType, file) => {
    try {
      const response = await uploadAxios.put(uploadUrl, file, {
        headers: {
          'Content-Type': fileType,
        },
      });

      console.log('headers ', response.headers);
    } catch (error) {
      console.error('PUT request failed:', error);
    }
  };

字符串

nkcskrwz

nkcskrwz7#

import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:scavenger_inc_flutter/utils/AuthUtils.dart';
import 'package:scavenger_inc_flutter/utils/URLS.dart';

class ApiClient {
  static Dio dio;

  static Dio getClient() {
    if (dio == null) {
      dio = new Dio();
      dio.httpClientAdapter = new CustomHttpAdapter();
    }
    return dio;
  }
}

class CustomHttpAdapter extends HttpClientAdapter {
  DefaultHttpClientAdapter _adapter = DefaultHttpClientAdapter();

  @override
  void close({bool force = false}) {
    _adapter.close(force: force);
  }

  @override
  Future<ResponseBody> fetch(RequestOptions options,
      Stream<List<int>> requestStream, Future<dynamic> cancelFuture) async {
    String url = options.uri.toString();
    if (url.contains(URLS.IP_ADDRESS) && await AuthUtils.isLoggedIn()) {
      options.followRedirects = false;
      options.headers.addAll({"Authorization": await AuthUtils.getJwtToken()});
    }
    final response = await _adapter.fetch(options, requestStream, cancelFuture);

    if (response.statusCode == 302 || response.statusCode == 307) {
      String redirect = (response.headers["location"][0]);
      if(!redirect.contains(URLS.IP_ADDRESS)) {
        options.path = redirect;
        options.headers.clear();
      }
      return await fetch(options, requestStream, cancelFuture);
    }

    return response;
  }
}

字符串
1.我不允许重定向。
1.使用响应对象检查它是否被重定向。
1.如果是302或307(HTTP重定向代码),我会在清除Auth Header后重新发送请求。
1.我使用了一个额外的检查,只有当路径包含我的特定域URL(或IP地址在这个例子中)发送头。
以上所有,使用Dio中的CustomHttpAdapter。也可以用于图像,通过将ResponseType更改为bytes。

让我知道如果这对你有帮助!

v2g6jxz6

v2g6jxz68#

我使用的是django restframework,我在REST API中应用了Token authentication,我使用在django API的请求头中传递token(使用了Browser的ModHeader扩展,它会自动将Token放在请求头的Authorization中),直到这里一切都很好。
但是,当点击 * 图像/文件 *(现在显示的s3网址).授权自动获得通过.因此,问题.
链接看起来与此类似。
https://. s3.amazonaws.com/media//small_image.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=XXXXXXXXXXXXXXXXXXXXX%2F20210317%2Fap-south-XXXXXXXXFaws4_request&X-Amz-Date=XXXXXXXXXXXXXXX&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
我锁定ModHeader扩展,仅在向REST API请求时传递授权令牌,而不是向S3资源请求时。即,在向S3资源请求时不传递任何其他授权。
这是个愚蠢的错误,但如果有帮助的话.

oyjwcjzk

oyjwcjzk9#

Flutter:如果您在使用http dart包时遇到这种情况,请升级到Flutter v2.10!

dart issue tracker中的相关bug:

-->这些问题已在dart 2.16中得到修复,该版本已随Flutter v2.10!https://medium.com/dartlang/dart-2-16-improved-tooling-and-platform-handling-dd87abd6bad1一起提供

相关问题