I want to implement image uploading in my web application which has backend in java and frontend in javasciprt/jquery/html/css and uploading on amazon s3.
I can see Fine-uploader generating a highly randomized key for a file and get that key signed by passing it to signature end point (along with some more headers).
My question is, what if somebody send some other key to signature end point and upload file with that key; in a way, he can try overwriting my already placed file.
How can I implement following logic in fine-uploader-
Fine uploader hit end point for signature
I generate some randomized key on server (sign that key and other headers) and pass signature, policy and key back to the client
Now on same key I do upload and bookeeping
please excuse me for typos and my bad english
While your initial question is a bit unclear, in your comments you have expressed a desire to ensure a user does not tamper with the request/policy, perhaps in an attempt to upload a file with a duplicate name. If you'd like to prevent this, simply query your database (or your bucket using the S3 API) server-side as part of handling the signature POST from Fine Uploader. If a file by that name already exists, then return a 500 response with a JSON message body like this: {"invalid": true}. This signals to Fine Uploader that the policy or request headers are invalid and the upload will be canceled.
Related
I am not being able to access a video stored in my Amazon s3 bucket through my Cloudfront distribution.
I have set the distribution to require signed URLs or signed cookies(generated by "self" user) and configured everything according to the tutorials on Amazon website (generated the key pair for the "self" user, transformed it to .der format using openssl, etc).
Then I followed the steps in this tutorial: http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CFPrivateDistJavaDevelopment.html
I was then able to generate a "canned" signed URL to access the content and it worked, I pasted the URL in chrome and it started playing the video.
Here is the code:
String signedUrlCanned = CloudFrontService.signUrlCanned(
resourceURL,
certificateId,
derPrivateKey,
ServiceUtils.parseIso8601Date("2018-11-14T22:20:00.000Z")
);
But then I decided to create a custom policy signed URL, following the steps in the tutorial and even using the exact same values for the parameters as I used for the canned URL, and it is not working... Here is the code:
String policy = CloudFrontService.buildPolicyForSignedUrl(
null,
ServiceUtils.parseIso8601Date("2018-11-14T22:20:00.000Z"),
null,
null
);
String signedUrl = CloudFrontService.signUrl(
resourceURL,
certificateId,
derPrivateKey,
policy
);
Keep in mind that "resourceURL", "certificateId" and "derPrivateKey" are the same parameters used for the canned URL, and they worked in that case.
The parameters remain unchanged the entire time since I checked that at debug time, and the 3 Strings(signedUrlCanned, policy, signedUrl) share the same scope(they are generated consecutively inside the same method) and there is no other code in between that could change the values of the parameters.
Here is the resulting URL for the custom policy signed URL:
http://d1eanqhguto8v8.cloudfront.net/Fox/Dexter.mp4?Policy=eyJTdGF0ZW1lbnQiOiBbeyJSZXNvdXJjZSI6IioiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE1NDIyMzQwMDB9LCJJcEFkZHJlc3MiOnsiQVdTOlNvdXJjZUlwIjoiMC4wLjAuMC8wIn19fV19&Signature=D9sHG6i9GTZRUGwKZYhmz3xKOQsjEWHJPQTCNywzdX9r~F0yEb58ljBAqRyXbHNgmmGuRppS6s0VkiRcyYi8q~DRDoXLtnp~MBbnnBKbF0Qy3xcx59LF6mXC6lXSou7jqz68y~d0VOoLvnFQl~OR5eSTWRHUO7X42~k3qdIiRH~eqzBwAaV9XnbJcLQ2DEDiW13~sfZJXnRsO6hENSk-aGcWeoF80KoccJ2-nFt0ZpndIFI3V~YXRv~Z3VKKS2ek1MW8SE2xdsOdqXAMkJC2X2maQn~MBzczXBuqEO4qKt42FmZI496TckMWzG-pVs~w-EjIWE2EEOzuXxopav8q~Q__&Key-Pair-Id=APKAIS7ACQJH7KT4YWLQ
You can access it and see the error message, it says that the Key-Pair-Id is missing, which is clearly not true since you can see it's there.
Any suggestions?
Edit: I just noticed that the error actually is a 403 "Access Denied" from Cloudfront. When I open the chrome console, under the Network tab I can see 2 GETs, one for the video that throws the 403 error and the other one tries to get something called "favicon.ico" that i've no idea what could be, and that one throws the "Key-Pair-Id is missing" error. One of my coworkers could access the video and still got the favicon.ico error, so I guess that error doesn't matter since it is not interfering with the video download.
I went to a open lecture about Jersey REST web service and made some notes. Here is what the lecturer said in the lecture, I am quite confuse about it.
i.you will need POST some content to /files/. For example, you
have a file locally called data.json.Posting the content of that file
to your REST service will store the content on the server with a name
it chooses automatically, say 3.json, in a folder chosen by you.
ii.The key thing here is the REST service will need to manage the
files it creates by choosing a name that hasn't been used and return
that name to sender, so the sender can re-download the content it sent
using the name it gets.( The sender do not know which name the content
will be given until it receives the response from the REST service).
For step i, is that means upload a file to the service and save to a new location? What is mean by the service will give it a name automatically?
For step ii, is that means if I send three files into the service, when I call GET /files/1, GET /files/2 and GET /files/3 will return the content of 1.json, 2.json, 3.json respectively? Besides the lecturer said we can use curl command line to post a file to the service.
The lecturer did not provide any example, which made me not understant it clearly.
Is it possible to help me to write a demo about that or provide some examples to me?
you have a file locally called data.json
Alright, simple enough
Posting the content of that file to your REST service will store the content on the server
Sure, saving files. It reads that POST data, and stores it to disk.
a name it chooses automatically
This is a minor detail... It could be stored as the same name, but then you'd have conflicting filenames.
in a folder chosen by you
That point isn't really clear... but, moving on.
the REST service will need to manage the files it creates by choosing a name that hasn't been used
Exactly the earlier point.
and return that [...] to sender
Think about a typical website... You request http://stackoverflow.com. It returns back HTML. Your REST service is just returning a string / file.
return that name to sender, so the sender can re-download the content it sent using the name it gets.( The sender do not know which name the content will be given until it receives the response from the REST service).
The client needs to know the name of the file that was added. Otherwise, you don't know how to request the file; the server had generated its own name for the file you sent to it originally.
if I send three files into the service, when I call GET /files/1, GET /files/2 and GET /files/3 will return the content of 1.json, 2.json, 3.json respectively?
Not quite - The server generated the names of the files. So, a better example would be
POST -d file.json /files
Outputs the text
20160801-21-38.json
And in order to request that file back, you now need to use that value
GET /files/20160801-21-38.json
From a Web API, I receive the following information about an Amazon S3 Bucket I am allowed to upload a File to:
s3_bucket (the Bucket name)
s3_key (the Bucket key)
s3_policy (the Bucket policy)
s3_signature the Bucket signature)
Because I am not the owner of the Bucket, I am provided with the s3_policy and s3_signature values, which, according to the AWS Upload Examples, can be used to authenticate a Put request to a Bucket.
However, in AWS's official Java SDK I'm using, I can't seem to find a way to perform this authentication. My code:
PutObjectRequest putObjectRequest = new PutObjectRequest(s3_bucket, s3_key, fileToUpload);
s3Client.putObject(putObjectRequest);
I do understand that I need to use the s3_signature and s3_policy I'm given at some point, but how do I do so to authenticate my PutObjectRequest?
Thanks in advance,
CrushedPixel
I don't think you're going to use the SDK for this operation. It's possible that the SDK will do what you need at this step, but it seems unlikely, since the SDK would typically take the access key and secret as arguments, and generate the signature, rather than accepting the signature as an argument.
What you describe is an upload policy document, not a bucket policy. That policy, the signature, and your file, would all go into an HTTP POST (not PUT) request of type multipart/form-data -- a form post -- as shown in the documentation page you cited. All you should need is an HTTP user agent.
You'd also need to craft the rest of the form, including all of the other fields in the policy, which you should be able to access by base64-decoding it.
The form also requires the AWSAccessKeyId, which looks something like "AKIAWTFBBQEXAMPLE", which is -- maybe -- what you are calling the "s3_key," although in S3 terminology, the "(object) key" refers to the path and filename.
This seems like an odd set of parameters to receive from a web API, particularly if they are expecting you to generate the form yourself.
I am working on the un-subscribing email service through un-subscribe link for an web application.
Email with un-subscribe link will be generated from a java class using MD5 algorithm. currently, i am appending the email id's in the form of encrypted hash with the link as,
<a href="http://server name/mailid=3f37c9628c8953d3fdfb0f8" >
'3f37c9628c8953d3fdfb0f8' string contains email'id of the user . i am updating the service subscription after validating it.
Does this process is secure ? or should i go for any other algorithms to make it more secure ?
Thanks in advance
You can make the unsubscribe link contain a randomly generated hash that's mapped to the user id internally in your data store.
You can also make the hash invalid after some specified time.
But keshlam has a point. Before you go to all that trouble make sure it's worth it with you context.
i need to implement the email signature with image.As of now we only support the text in email signature which is already working.i need to provide the functionality
where i can insert the image inside mail signature. i can send the email to user within myapplication and also to user on external mail domain like gmail,yahoo etc. When
mail is sent to some user with in my application system, system makes entryt o DB and when receiver receives in inbox (which internally read the mail from db). Now if user
send the mail to external user on gmail it makes use of javax mail api . Similary i can receive the email from external mail domains(gmail,yahoo etc) Now i have
few questions based on tis requirement:-
1)Is there any standard for how the external mail domains like gmail send the image inside signature to another domains like (my application mail domain)?
Another point related to it gmail user can have two images ,one for signature and another image inside body. How will i determine which image belongs to
signature? Is there any defined property for that?
2)Also not able to make out what is the best/consistent approach to send(whether to internal application user or external mail domain user ) the email signature containing
image so that it renders correctly when user receives it?
what I had in my mind for point 2:- i earlier thought i can use solution suggested at How to display an image in jsp?. where
with tag <.img src="/getImage.action?imageId=123">, i can fetch the image from db in action class or servlet and return. But keeping in mind
once i send the mail to the user on gmail , he will not be able to access the servlet.So this approach does not seems to fit in requirement.
Then i came across the another great stackoverflow link base64 encoded images in email signatures where
solution by Tim Medora looked great but again the comment below the solution Gmail doesn't seem to support it again ended my Folks
really i think i should be done if mail domain like gmail,yahoo support the solution suggested by because in that case i can send image as base64 string instead
of image as attachment.
Folks would be really grateful if you can provide me some pointer/approach regarding both points 1 and 2
To include images in the email message, first you have to include the images as MIME attachments in the email. Each of these attachments must have a "Content-ID" header.
--f46d0444ea0d6991ba04b91c92e6
Content-Type: image/gif; name="theImage.gif"
Content-Transfer-Encoding: base64
Content-ID: <theImage#abcd>
[base64 string]
--f46d0444ea0d6991ba04b91c92e6--
2) Then, in the email message, include the Content-ID in the src attribute of the <img> tag.
<img src="cid:theImage#abcd" />
For Gmail to see the embedded image from byte array, I posted an answer on another similar question which is to use ByteArrayDataSource and embed it to the HtmlEmail. Here's the code snippet:
import javax.mail.util.ByteArrayDataSource;
import org.apache.commons.mail.ImageHtmlEmail;
...
ImageHtmlEmail email = new ImageHtmlEmail();
byte[] qrImageBytes = createQRCode(); // get your image byte array
ByteArrayDataSource qrImageDataSource = new ByteArrayDataSource(qrImageBytes, "image/png");
String contentId = email.embed(qrImageDataSource, "QR Image");