Until iPhone 3.0 is available, I need to send an email with what my iPhone app has generated (an image) and to where the user has chosen.
在iPhone 3.0可用之前,我需要用我的iPhone应用程序生成的(图像)和用户选择的地方发送一封电子邮件。
Two solutions, the skpsmtpmessage library, which is not all there and still buggy; or write my own server to forward the emails. The latter is no problem for me, but the question is how can I be sure that the message is from my iPhone app, and not something else?
有两种解决方案,skpsmtpmessage库,它不是全部,而且仍然有问题;或者写我自己的服务器来转发邮件。后者对我来说不是问题,但问题是,我如何确定消息来自我的iPhone应用程序,而不是别的什么?
I can imagine using SSL, but I still wonder about someone on a jailbroken iPhone taking my app apart and then using the faked connection to run spam through it.
我可以想象使用SSL,但我仍然想知道,iPhone上有人破解了我的应用程序,然后用伪造的连接运行垃圾邮件。
My first thought is to make the server only accept data with an exact set of features (such as exactly 1 jpg image, certain exact JSON data) and reject everything else. It could still be DOSsed of course.
我的第一个想法是让服务器只接受具有一组精确特性的数据(比如精确的1个jpg图像,特定的JSON数据),并拒绝其他的一切。当然,它仍然可以被忽略。
Does this make sense? Has anyone done something similar?
这是否有意义吗?有人做过类似的事情吗?
EDIT: I won't be sending an email to my server, just JSON and the server will generate the actual email.
编辑:我不会向我的服务器发送电子邮件,只要JSON,服务器就会生成实际的电子邮件。
5 个解决方案
#1
3
I'm doing a similar thing on an app I'm working on. You can use a combination of public key encryption, SSL, and the local phone keychain.
我正在开发的一个应用程序上做着类似的事情。您可以使用公钥加密、SSL和本地电话密钥链的组合。
-
First of all, all communications between iPhone and server have to be encrypted. This is pretty straightforward if you use HTTP POST requests and SSL. It also thwarts packet sniffers.
首先,iPhone和服务器之间的所有通信都必须加密。如果您使用HTTP POST请求和SSL,这非常简单。它还可以阻止包嗅探器。
-
When your app comes up it looks inside the local keychain for a public RSA key for the server and a stored hash value. If not found it contacts your server with the UDID of the phone which the server uses (along with system time) to generate a hash. It sends back a copy of the hash and its public key to the phone. The server then creates a record in a local database (say, MYSQL) with the UDID and the hash it sent back so it can use it for verification later.
当应用程序出现时,它会在本地密钥链中查找服务器的公开RSA密钥和存储的散列值。如果没有找到,它会将您的服务器与服务器的UDID联系起来,服务器使用该UDID(以及系统时间)生成散列。它将散列及其公钥的副本发送回电话。然后,服务器在本地数据库(比如MYSQL)中创建一个记录,并将其发送回来,以便稍后进行验证。
-
The app on the iPhone saves the hash and the server's public key in its local secure keychain. This is all handshake stuff behind the scenes, i.e. no user interaction involved. This is only done the first time the app is run.
iPhone上的应用程序将哈希和服务器的公钥保存在本地安全密钥链中。这些都是幕后的握手工作,即不涉及用户交互。这只是第一次运行应用程序。
-
From then on, every time you want to send an email your app formats your message (the image+JSON part), tacks on its own UDID and the hash value it got from the server, then uses the server public key it has in the keychain and RSA encrypts the whole mess. It adds this to the body of an HTTP POST to the server and sends it (via SSL).
从那以后,每当你想要发送电子邮件时,你的应用会格式化你的消息(图像+JSON部分),在它自己的UDID上加上它从服务器获得的散列值,然后使用它在密钥链中拥有的服务器公钥,RSA加密整个混乱。它将此内容添加到HTTP POST的主体,并将其发送到服务器(通过SSL)。
-
The server gets the message, uses its private RSA key to decrypt the message, parses it, looks up the phone UDID in its database and compares the hash values received to the one it saved from that first run to make sure it's a handset with which it has already done a handshake. If verified, it takes the user data and formats it as an SMTP mail message and sends it on its way. It then replies back to the phone with the status.
服务器获取信息,利用其私RSA密钥解密消息,解析它,其数据库中查找电话UDID和比较接收到的散列值的保存从第一个运行以确保它是一个手机,它已经完成握手。如果经过验证,它接受用户数据并将其格式化为SMTP邮件消息并将其发送。然后,它回复到手机的状态。
-
This establishes a two way handshake between phone and server. No user-level accounts were created and it's all behind the scenes. The only information you're saving on the server is the UDID of the phone anonymously so there shouldn't be any privacy issues. The communication is secure (SSL), the server only accepts requests from phones that have gone through the handshake, stored the calculated hash, and to top it off, the whole packet is encrypted through public key encryption.
这建立了电话和服务器之间的双向握手。没有创建用户级的帐户,而且都是在幕后创建的。你在服务器上保存的唯一信息是匿名手机的UDID,所以不应该有任何隐私问题。通信是安全的(SSL),服务器只接受通过握手的电话发出的请求,存储计算的散列,并将其关闭,整个包通过公钥加密进行加密。
-
If you want to keep things interesting, every once in a while you can send back a new calculated hash with your status results and have the phone replace the one in the keychain. That way, even if after all this someone cracks your scheme, they'll have to keep up with changes over time.
如果你想让事情变得有趣,你可以时不时地用你的状态结果发送一个新的计算散列,并让手机替换密钥链中的那个。这样的话,即使这些人破坏了你的计划,他们也必须跟上时代的变化。
-
If the user deletes your app and reinstalls it or moves to a new phone you just do the handshake again. The cost is an extra database record on the server. If this is an issue you can also save the 'last transaction' date with the record on the server then expire idle records every N months and force the phone to go through a fresh handshake (instead of considering it an error message). On second thought, you may want to do this anyway. The cost is a short delay every once in a while as the phone goes through the handshake sequence again.
如果用户删除你的应用程序并重新安装它或移动到一个新的电话,你只需再次进行握手。成本是服务器上的额外数据库记录。如果这是一个问题,您还可以将服务器上的记录保存为“最后的事务”日期,然后每隔N个月过期空闲记录,迫使手机进行一次新的握手(而不是将其视为一条错误消息)。仔细想想,你可能想要这样做。代价是每隔一段时间就有一次短暂的延迟,因为手机会再次通过握手序列。
-
To make it doubly interesting, the server that does that first handshake can be a different server than the one that actually does the work later on. The handshake server also sends back the URL endpoint of where subsequent requests should go and the iphone stores that in the keychain too. So even if your app gets decompiled, all they will get is the URL of the handshake end-point. Since most of the data is stored at runtime in the keychain, static analysis of your code from a jailbroken phone will yield nothing of much value.
更有趣的是,执行第一次握手的服务器可以是与实际执行后续工作的服务器不同的服务器。握手服务器还返回后续请求的URL端点,iphone也将其存储在密钥链中。因此,即使你的应用程序被反编译,他们将得到的只是握手端点的URL。由于大多数数据在运行时存储在密钥链中,因此从破解的手机对代码进行静态分析不会产生任何价值。
-
Also for the sake of performance you may want to consider queuing the request on the server as soon as it's been validated and letting the user get back to what they're doing, then using a cron job to pump out the SMTP messages periodically. The advantage is the user response is better. The disadvantage is that if the email address is bad you have no way to respond back to them unless you get fancy with push notifications. I'd make it a user-preference and let them decide if they want to wait for confirmation.
此外,为了提高性能,您可能希望在验证请求之后,考虑在服务器上对请求进行排队,并让用户返回到他们正在做的事情,然后使用cron作业定期地泵出SMTP消息。优点是用户响应更好。缺点是,如果电子邮件地址不好,除非你喜欢推送通知,否则你无法回复它们。我将它设置为用户偏好,让他们决定是否等待确认。
-
All the technical bits for this already exist on the the iPhone (i.e. no third-party libraries needed) and should be easy to implement on a server with Rails or Django.
所有的技术细节都已经存在于iPhone上(也就是说,不需要第三方库),并且应该很容易在带有Rails或Django的服务器上实现。
#2
2
Making it as exact as possible will definitely lower spam. If you make it do something like http POST to the webserver, then let the webserver generate the message, you'll make it harder to spam. (more likely to require a custom setup on the spammer's part)
使它尽可能准确,将肯定会减少垃圾邮件。如果您让它对webserver执行类似http POST的操作,然后让webserver生成消息,您将使垃圾邮件更难处理。(更可能需要在垃圾邮件发送者部分进行自定义设置)
Some sort of registration system is your best bet, it's far harder to spam if you need to register first, and you can disable accounts that cause problems far more easily.
某种注册系统是你最好的选择,如果你需要先注册的话,垃圾邮件要难得多,而且你可以禁用那些容易引起问题的账户。
You're not going to be able to prevent DDOS from the application side, so I wouldn't worry about it too much, just make sure it's not too easy to make the application send a ton of data or perform complex processing.
您将无法阻止应用程序方面的DDOS,因此我不会太担心它,只需确保应用程序不太容易发送大量数据或执行复杂的处理。
#3
-1
Add an extra email header that contains some sort of key. Only accept emails that have the header set with the correct key. That would prevent random people from hijacking the email server, but might not deter someone who has taken your app apart and discovered the key.
添加一个包含某种密钥的额外邮件头。只接受标题设置正确键的邮件。这将防止随机的人劫持电子邮件服务器,但可能不会阻止某人将你的应用程序拆开并发现了密钥。
To make it more difficult than simply finding your key, you could set keys on a per session basis. Every time the app loads it requests a key from the email server and then uses that key in all email headers sent during that session. That way you could implement behavior tracking and ban malicious users and bots (for example, you could ban any user that sends emails faster than humanly probable).
要使它比简单地找到密钥更加困难,您可以在每个会话基础上设置键。每次应用程序加载它时,它从电子邮件服务器请求一个密钥,然后在该会话期间发送的所有邮件标题中使用该密钥。通过这种方式,您可以实现行为跟踪并禁止恶意用户和机器人(例如,您可以禁止任何发送电子邮件速度超过人类可能速度的用户)。
#4
-1
If possible, make the interface as useless as possible to spammers. If you're generating an e-mail dump of a series of objects, for example, convert the objects to XML and send those in rather than sending the text of the eventual e-mail. Spammers are looking for the weakest link and will move on if they have to put a lot of effort into using your service.
如果可能的话,让界面尽可能对垃圾邮件发送者无效。如果您正在生成一系列对象的电子邮件转储,例如,将对象转换为XML并将其发送进来,而不是发送最终电子邮件的文本。垃圾邮件发送者正在寻找最薄弱的环节,如果他们不得不在使用您的服务上付出很多努力,他们将继续前进。
#5
-1
What's wrong with skpsmtpmessage?
skpsmtpmessage怎么了?
#1
3
I'm doing a similar thing on an app I'm working on. You can use a combination of public key encryption, SSL, and the local phone keychain.
我正在开发的一个应用程序上做着类似的事情。您可以使用公钥加密、SSL和本地电话密钥链的组合。
-
First of all, all communications between iPhone and server have to be encrypted. This is pretty straightforward if you use HTTP POST requests and SSL. It also thwarts packet sniffers.
首先,iPhone和服务器之间的所有通信都必须加密。如果您使用HTTP POST请求和SSL,这非常简单。它还可以阻止包嗅探器。
-
When your app comes up it looks inside the local keychain for a public RSA key for the server and a stored hash value. If not found it contacts your server with the UDID of the phone which the server uses (along with system time) to generate a hash. It sends back a copy of the hash and its public key to the phone. The server then creates a record in a local database (say, MYSQL) with the UDID and the hash it sent back so it can use it for verification later.
当应用程序出现时,它会在本地密钥链中查找服务器的公开RSA密钥和存储的散列值。如果没有找到,它会将您的服务器与服务器的UDID联系起来,服务器使用该UDID(以及系统时间)生成散列。它将散列及其公钥的副本发送回电话。然后,服务器在本地数据库(比如MYSQL)中创建一个记录,并将其发送回来,以便稍后进行验证。
-
The app on the iPhone saves the hash and the server's public key in its local secure keychain. This is all handshake stuff behind the scenes, i.e. no user interaction involved. This is only done the first time the app is run.
iPhone上的应用程序将哈希和服务器的公钥保存在本地安全密钥链中。这些都是幕后的握手工作,即不涉及用户交互。这只是第一次运行应用程序。
-
From then on, every time you want to send an email your app formats your message (the image+JSON part), tacks on its own UDID and the hash value it got from the server, then uses the server public key it has in the keychain and RSA encrypts the whole mess. It adds this to the body of an HTTP POST to the server and sends it (via SSL).
从那以后,每当你想要发送电子邮件时,你的应用会格式化你的消息(图像+JSON部分),在它自己的UDID上加上它从服务器获得的散列值,然后使用它在密钥链中拥有的服务器公钥,RSA加密整个混乱。它将此内容添加到HTTP POST的主体,并将其发送到服务器(通过SSL)。
-
The server gets the message, uses its private RSA key to decrypt the message, parses it, looks up the phone UDID in its database and compares the hash values received to the one it saved from that first run to make sure it's a handset with which it has already done a handshake. If verified, it takes the user data and formats it as an SMTP mail message and sends it on its way. It then replies back to the phone with the status.
服务器获取信息,利用其私RSA密钥解密消息,解析它,其数据库中查找电话UDID和比较接收到的散列值的保存从第一个运行以确保它是一个手机,它已经完成握手。如果经过验证,它接受用户数据并将其格式化为SMTP邮件消息并将其发送。然后,它回复到手机的状态。
-
This establishes a two way handshake between phone and server. No user-level accounts were created and it's all behind the scenes. The only information you're saving on the server is the UDID of the phone anonymously so there shouldn't be any privacy issues. The communication is secure (SSL), the server only accepts requests from phones that have gone through the handshake, stored the calculated hash, and to top it off, the whole packet is encrypted through public key encryption.
这建立了电话和服务器之间的双向握手。没有创建用户级的帐户,而且都是在幕后创建的。你在服务器上保存的唯一信息是匿名手机的UDID,所以不应该有任何隐私问题。通信是安全的(SSL),服务器只接受通过握手的电话发出的请求,存储计算的散列,并将其关闭,整个包通过公钥加密进行加密。
-
If you want to keep things interesting, every once in a while you can send back a new calculated hash with your status results and have the phone replace the one in the keychain. That way, even if after all this someone cracks your scheme, they'll have to keep up with changes over time.
如果你想让事情变得有趣,你可以时不时地用你的状态结果发送一个新的计算散列,并让手机替换密钥链中的那个。这样的话,即使这些人破坏了你的计划,他们也必须跟上时代的变化。
-
If the user deletes your app and reinstalls it or moves to a new phone you just do the handshake again. The cost is an extra database record on the server. If this is an issue you can also save the 'last transaction' date with the record on the server then expire idle records every N months and force the phone to go through a fresh handshake (instead of considering it an error message). On second thought, you may want to do this anyway. The cost is a short delay every once in a while as the phone goes through the handshake sequence again.
如果用户删除你的应用程序并重新安装它或移动到一个新的电话,你只需再次进行握手。成本是服务器上的额外数据库记录。如果这是一个问题,您还可以将服务器上的记录保存为“最后的事务”日期,然后每隔N个月过期空闲记录,迫使手机进行一次新的握手(而不是将其视为一条错误消息)。仔细想想,你可能想要这样做。代价是每隔一段时间就有一次短暂的延迟,因为手机会再次通过握手序列。
-
To make it doubly interesting, the server that does that first handshake can be a different server than the one that actually does the work later on. The handshake server also sends back the URL endpoint of where subsequent requests should go and the iphone stores that in the keychain too. So even if your app gets decompiled, all they will get is the URL of the handshake end-point. Since most of the data is stored at runtime in the keychain, static analysis of your code from a jailbroken phone will yield nothing of much value.
更有趣的是,执行第一次握手的服务器可以是与实际执行后续工作的服务器不同的服务器。握手服务器还返回后续请求的URL端点,iphone也将其存储在密钥链中。因此,即使你的应用程序被反编译,他们将得到的只是握手端点的URL。由于大多数数据在运行时存储在密钥链中,因此从破解的手机对代码进行静态分析不会产生任何价值。
-
Also for the sake of performance you may want to consider queuing the request on the server as soon as it's been validated and letting the user get back to what they're doing, then using a cron job to pump out the SMTP messages periodically. The advantage is the user response is better. The disadvantage is that if the email address is bad you have no way to respond back to them unless you get fancy with push notifications. I'd make it a user-preference and let them decide if they want to wait for confirmation.
此外,为了提高性能,您可能希望在验证请求之后,考虑在服务器上对请求进行排队,并让用户返回到他们正在做的事情,然后使用cron作业定期地泵出SMTP消息。优点是用户响应更好。缺点是,如果电子邮件地址不好,除非你喜欢推送通知,否则你无法回复它们。我将它设置为用户偏好,让他们决定是否等待确认。
-
All the technical bits for this already exist on the the iPhone (i.e. no third-party libraries needed) and should be easy to implement on a server with Rails or Django.
所有的技术细节都已经存在于iPhone上(也就是说,不需要第三方库),并且应该很容易在带有Rails或Django的服务器上实现。
#2
2
Making it as exact as possible will definitely lower spam. If you make it do something like http POST to the webserver, then let the webserver generate the message, you'll make it harder to spam. (more likely to require a custom setup on the spammer's part)
使它尽可能准确,将肯定会减少垃圾邮件。如果您让它对webserver执行类似http POST的操作,然后让webserver生成消息,您将使垃圾邮件更难处理。(更可能需要在垃圾邮件发送者部分进行自定义设置)
Some sort of registration system is your best bet, it's far harder to spam if you need to register first, and you can disable accounts that cause problems far more easily.
某种注册系统是你最好的选择,如果你需要先注册的话,垃圾邮件要难得多,而且你可以禁用那些容易引起问题的账户。
You're not going to be able to prevent DDOS from the application side, so I wouldn't worry about it too much, just make sure it's not too easy to make the application send a ton of data or perform complex processing.
您将无法阻止应用程序方面的DDOS,因此我不会太担心它,只需确保应用程序不太容易发送大量数据或执行复杂的处理。
#3
-1
Add an extra email header that contains some sort of key. Only accept emails that have the header set with the correct key. That would prevent random people from hijacking the email server, but might not deter someone who has taken your app apart and discovered the key.
添加一个包含某种密钥的额外邮件头。只接受标题设置正确键的邮件。这将防止随机的人劫持电子邮件服务器,但可能不会阻止某人将你的应用程序拆开并发现了密钥。
To make it more difficult than simply finding your key, you could set keys on a per session basis. Every time the app loads it requests a key from the email server and then uses that key in all email headers sent during that session. That way you could implement behavior tracking and ban malicious users and bots (for example, you could ban any user that sends emails faster than humanly probable).
要使它比简单地找到密钥更加困难,您可以在每个会话基础上设置键。每次应用程序加载它时,它从电子邮件服务器请求一个密钥,然后在该会话期间发送的所有邮件标题中使用该密钥。通过这种方式,您可以实现行为跟踪并禁止恶意用户和机器人(例如,您可以禁止任何发送电子邮件速度超过人类可能速度的用户)。
#4
-1
If possible, make the interface as useless as possible to spammers. If you're generating an e-mail dump of a series of objects, for example, convert the objects to XML and send those in rather than sending the text of the eventual e-mail. Spammers are looking for the weakest link and will move on if they have to put a lot of effort into using your service.
如果可能的话,让界面尽可能对垃圾邮件发送者无效。如果您正在生成一系列对象的电子邮件转储,例如,将对象转换为XML并将其发送进来,而不是发送最终电子邮件的文本。垃圾邮件发送者正在寻找最薄弱的环节,如果他们不得不在使用您的服务上付出很多努力,他们将继续前进。
#5
-1
What's wrong with skpsmtpmessage?
skpsmtpmessage怎么了?