首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >亚马逊SES与Django不在UTC时区

亚马逊SES与Django不在UTC时区
EN

Stack Overflow用户
提问于 2019-03-15 11:56:27
回答 1查看 641关注 0票数 3

我正在开发一个django项目,在美国使用,特别是纽约时区,该系统托管在AWS上,SES发送电子邮件。电子邮件后端使用的是django-任意邮件,它是SES的一个简单包装器,系统使用来自django核心的send_mail

为了支持这一点,我选择了以下Django设置;

代码语言:javascript
复制
EMAIL_BACKEND = "anymail.backends.amazon_ses.EmailBackend"

LANGUAGE_CODE = 'en'
TIME_ZONE = 'America/New_York'
USE_I18N = False
USE_L10N = True
USE_TZ = True

ANYMAIL = {
    "AMAZON_SES_CLIENT_PARAMS": {
        "region_name": AWS_SES_REGION_NAME,
    },
}

使用上述设置,django在启动时调用tzset(),这将修改系统时区。这意味着botocore用于签署SES请求的时间戳不是UTC,因为从消息发送中接收到以下错误;

调用ExpiredToken操作时发生错误( SendRawEmail ):请求中包含的安全令牌过期

通过将设置更改为TIME_ZONE = 'UTC'成功地发送电子邮件。

我只能假设请求是在UTC -4中签名的,然后点击位于UTC的AWS。

django如何在特定的时区运行,但是boto使用UTC时间戳操作呢?

该系统运行在一个码头集装箱(生产前);

  • docker compose 3.4 (unix主机)
  • python 2.7
  • django 1.11
  • django-anymail 3.0
  • 加载LocaleMiddleware
EN

回答 1

Stack Overflow用户

发布于 2019-03-20 07:52:02

我无法用您所描述的设置来重现您所看到的错误,但是我可以通过额外的日志记录向您展示什么是正确的,您可以将其与失败的情况进行比较,试图看看什么是不同的。

为了方便起见,我在Django壳 (python manage.py shell)中运行了这段代码,但是您可以将它放在调试视图或其他适合您的地方。

我们的工作原理是boto使用错误的时区来计算签署API请求的时间戳,所以让我们启用一些涵盖该领域的详细boto3测井

代码语言:javascript
复制
import boto3
boto3.set_stream_logger('botocore.auth')  # log the signature logic
boto3.set_stream_logger('botocore.endpoint')  # log the API request
# boto3.set_stream_logger('botocore.parsers')  # log the API response (if you want)

现在试着发送一个信息:

代码语言:javascript
复制
from django.core.mail import send_mail
send_mail("Test", "testing", None, ['success@simulator.amazonses.com'])

您应该看到如下所示的日志输出:

代码语言:javascript
复制
2019-03-19 20:48:32,321 botocore.endpoint [DEBUG] Setting email timeout as (60, 60)
2019-03-19 20:48:32,580 botocore.endpoint [DEBUG] Making request for OperationModel(name=SendRawEmail) with params: {'body': {'Action': u'SendRawEmail', 'Version': u'2010-12-01', 'RawMessage.Data': [base64 message omitted]'}, 'url': u'https://email.us-east-1.amazonaws.com/', 'headers': {'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', 'User-Agent': 'Boto3/1.9.117 Python/2.7.15 Darwin/18.2.0 Botocore/1.12.117 django-anymail/3.0-amazon-ses'}, 'context': {'auth_type': None, 'client_region': 'us-east-1', 'has_streaming_input': False, 'client_config': <botocore.config.Config object at 0x10dadd1d0>}, 'query_string': '', 'url_path': '/', 'method': u'POST'}
2019-03-19 20:48:32,581 botocore.auth [DEBUG] Calculating signature using v4 auth.
2019-03-19 20:48:32,581 botocore.auth [DEBUG] CanonicalRequest:
POST
/

content-type:application/x-www-form-urlencoded; charset=utf-8
host:email.us-east-1.amazonaws.com
x-amz-date:20190320T064832Z

content-type;host;x-amz-date
[redacted]
2019-03-19 20:48:32,582 botocore.auth [DEBUG] StringToSign:
AWS4-HMAC-SHA256
20190320T064832Z
20190320/us-east-1/ses/aws4_request
[redacted]
2019-03-19 20:48:32,582 botocore.auth [DEBUG] Signature:
[redacted]
2019-03-19 20:48:32,582 botocore.endpoint [DEBUG] Sending http request: <AWSPreparedRequest stream_output=False, method=POST, url=https://email.us-east-1.amazonaws.com/, headers={'Content-Length': '437', 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', 'Authorization': 'AWS4-HMAC-SHA256 Credential=[key id redacted]/20190320/us-east-1/ses/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=[redacted]', 'X-Amz-Date': '20190320T064832Z', 'User-Agent': 'Boto3/1.9.117 Python/2.7.15 Darwin/18.2.0 Botocore/1.12.117 django-anymail/3.0-amazon-ses'}>

这里的重要部分是日期:

代码语言:javascript
复制
2019-03-19 20:48:32,581 botocore.auth [DEBUG] CanonicalRequest:
...
x-amz-date:20190320T064832Z

2019-03-19 20:48:32,582 botocore.auth [DEBUG] StringToSign:
...
20190320T064832Z
20190320/...

2019-03-19 20:48:32,582 botocore.endpoint [DEBUG] Sending http request: <AWSPreparedRequest ...
  headers={
    'Authorization': '.../20190320/...',
    'X-Amz-Date': '20190320T064832Z', ...}>

注意,签名计算都是基于UTC日期(2019-03-20)-not,这是我的Django时区(2019-03-19)中的当前本地日期。

因此,看起来boto3确实使用UTC进行签名计算,尽管存在Django/environment时区。事实上,发送对我来说是没有错误的。

所以问题是,当你看到问题的时候,有什么不同?

  • CanonicalRequest中的x-amz日期是多少?
  • ,实际上是发送消息时的实际UTC日期时间吗?(如果不是,您的码头集装箱中的时钟可能会离得很远。)
  • 同一日期是否在StringToSign中再次正确显示,既作为一个完整的时间戳,也作为一个截断的日期?
  • 它是否再次出现在AWSPreparedRequest头中,包括AuthorizationX-Amz-Date?(如果您看到的是Date头而不是X-Amz-Date,那也会很有趣。)

希望这可以帮助您更接近解决方案,或者至少知道哪些细节对于重现问题至关重要。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55182108

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档