Browser-Based Uploads Using POST - ruby

I'm trying to create a client side uploads using POST with Signature Version 4 of AWS.
According to the documents
When i'm generating the signature on the server side I get an exact match with AWS signature mentioned in this example page.
However when I use it to upload the page I get this error:
SignatureDoesNotMatchThe request signature we calculated does not match the signature you provided. Check your key and signing method
This is the code I've used:
OpenSSL::HMAC.hexdigest('sha256', signing_key(string_to_sign), string_to_sign)
# step 2 in the aws documentation
def signing_key(encoded_policy)
# generate the correct date
date = extract_encoded_policy_date(encoded_policy)
date = time_adjust(date)
# encode all the fields by the algorithm
date_key = OpenSSL::HMAC.digest('sha256',"AWS4#{#secret_access_key}", date.strftime("%Y%m%d"))
date_region_key = OpenSSL::HMAC.digest('sha256',date_key, #region)
date_region_service_key = OpenSSL::HMAC.digest('sha256',date_region_key, #service)
signing_key = OpenSSL::HMAC.digest('sha256',date_region_service_key, 'aws4_request')
signing_key
end
def time_adjust(date)
time = Time.parse(date)
time += time.utc_offset
time.utc
end
After a little search in the net, i've encountered this article. Iv'e implemented this code and the upload succeeded.
signature = OpenSSL::HMAC.digest( OpenSSL::Digest::Digest.new('sha1'), #secret_access_key, string_to_sign)
Base64.encode64(signature).gsub("\n","")```
This is a small Demo for the client side code.
here is some literature I've found useful:
General description
Some code snippets from AWS
What is the differences between the two?
How can I get the first option to work and upload my files?
Is the example in the AWS page no longer valid?

After a research and comparing the AWS post example i found out that there were some redundant fields in the form that made AWS think i'm using SHA1.
After removing the AWSAccessKeyId field from the form and renaming some other fields I managed to make the AWS4 work.
This is the updated Demo
<form id="myForm" action="http://yourbucket.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
<input type="hidden" id="key" name="key" value="uploads/${filename}"/>
<input type="hidden" id="acl" name="acl" value="YOUR_ACL_OPTION"/>
<input type="hidden" name="success_action_redirect" value="http://google.com" />
<input type="hidden" id="type" name="Content-Type" value="MIME_TYPE"/>
<input type="hidden" name="x-amz-meta-uuid" value="14365123651274" />
<input type="hidden" name="X-Amz-Credential" value="YOUR_CREDENTIALS" />
<input type="hidden" name="X-Amz-Algorithm" value="AWS4-HMAC-SHA256" />
<input type="hidden" id="date" name="X-Amz-Date" value="" />
<input type="hidden" name="x-amz-meta-tag" value="" />
<input type="hidden" id="policy" name="Policy" value="YOUR_POLICY_DOCUMENT_BASE64_ENCODED"/>
<input type="hidden" id="signature" name="X-Amz-Signature" value="YOUR_CALCULATED_SIGNATURE"/>
<input name="file" id="file" type="file"/>
<input id="btn_submit" class="btn btn-warning" type="submit" value="Upload File to S3">
</form>

Related

Thymeleaf handling null object in Asterisk

I have a Spring boot App with a Thymeleaf Template in which I define a th:object="${guest}" and I try to access it with the Asterisk syntax like th:value="*{lastName}".
If th:object="${guest} is null it produces an Error: Property or field 'firstName' cannot be found on null. I understand why the error appears. But what is the best way to handle it?
Since I am using th:object="${guest} to prefill values in an form. My current working solution is:
<form th:if="${guest}" th:object="${guest}" ... >
<form th:unless="${guest} ... >
and this is the part I do not understand why can't Thmyleafe workout in the Asterisk that the object is null? But the th:if / th:unless statment gets that th:object is null. There is no case in which accessing an attribute of a null Object is suitable.
And if the object is not there at all it is fine.
Is there a better way with less code?
I also tried:
th:value="*{lastName}?:_" - same error.
th:object="${guest}:?_" - this cant be parsed at all.
Is there a way without the th:if / th:unless. The optimal solution would be to do it in one line so everything stays clean. Can I somehow parse an if in the th:object${}
I could not find something in the documentation or else on the web. Only if Asterisk or ${..} is null
Full Code:
The Fragment:
<form th:fragment="guest_form">
<input type="text" id="firstName" name="firstName" placeholder="Vorname" th:value="*{firstName}" required />
<input type="text" id="lastName" name="lastName" placeholder="Nachname" th:value="*{lastName}" required />
<input type="tel" id="phone" name="phone" placeholder="Telefon Nummer" th:value="*{phone}" />
<input type="email" id="email" name="email" placeholder="Emailadresse" th:value="*{email}" />
<input type="street" id="street" name="street" placeholder="Straße" th:value="*{street}" />
<input type="city" id="city" name="city" placeholder="Stadt" th:value="*{city}" />
<input type="zip" id="zip" name="zip" placeholder="Postleitzahl" th:value="*{zip}" />
<input type="hidden" name="code" th:value="${code}" />
<input th:replace="::csrf_token" />
<input type="submit" id="submitButton" value="Bestätigen" />
</form>
The fragment use:
<form th:include=" fragments/fragments.html::guest_form" th:if="${guest}" th:object="${guest}" action="/register" method="POST"></form>
<form th:include="fragments/fragments.html::guest_form" th:unless="${guest}" action="/register" method="POST"></form>
The function:
#PostMapping("/register")
public String register(#RequestParam String code, Model model, HttpSession session,
RedirectAttributes redirectAttributes, #ModelAttribute("guest") #Valid Guest g,
BindingResult bindingResult) {
model.addAttribute("guest", g);
model.addAttribute("code", code);
// form is not fine
if (bindingResult.hasErrors()) {
return "guest/register";
}
// form is not fine
guestRepo.save(g);
Booking booking = new Booking(g, invRepo.findByCode(code).get());
bookingRepo.save(booking);
session.setAttribute(saBooking, booking);
return "redirect:/ticket";
}
g can be null because you can get redirect to this url - to fill out the form - in this moment g is null. I think I could check if g == null an then Guest g = new Guest(); but this doesnt target my question...

How to set default value in thymeleaf th:field

I have a form and I want to set default value in the field below but it's not working.
<span>ID User:</span>
<input type="text" th:value="${session.name}" th:field="*{userid}" th:errorclass="field-error" />
</div>
<div>
<span class="name-in">ID Room:</span>
<input type="text" th:value="${id}" th:field="*{room}" th:errorclass="field-error" />
</div>
I read some topic about this problem and I try to change as given below
th:attr="value = ${session.name}"
But It's still not working. Field ID User is empty. I don't know how to solve this problem.
Although your question contain less information, but i think you want to put default value for all field. If you like to do so change
`<input type="text" th:value="${session.name}" th:field="*{userid}" th:errorclass="field-error" />`
to
<input type="text" name="userid" value="as your wish" th:errorclass="field-error" />
Instead of changing the html, you should instead set the value of *{userid} in your controller. That way you can keep your html the same:
// Controller
modelObject.setUserId(session.name);
// HTML
<input type="text" th:field="*{userid}" th:errorclass="field-error" />

Override generated checkbox-name (via asp-for)

I want to change the name of a view-inputfield that is generated by an "asp-for" tag. This works when I add a "name=newname" with input fields of type 'text' or 'number'. But not when the inputfield is of type 'checkbox'. Then the "name=newname" is ignored. Any ideas why this is and how to solve it when using asp-for? I'm using AspNetCore.Mvc 1.0.0-rc2-final.
<input type="number" asp-for="#item.StatementSeqNr" name="StatementSeqNr" class="form-control" /> produces correct name:
<input name="StatementSeqNr" class="form-control" type="number" data-val="true" id="item_StatementSeqNr" value="5" />
<input type="checkbox" asp-for="#item.StatementActive" name="StatementActive" /> produces incorrect name:
<input checked="checked" data-val="true" id="item_StatementActive" name="item.StatementActive" type="checkbox" value="true" />
This is currently not possible with the new TagHelpers.
You can achieve this by using the HtmlHelpers instead of the TagHelpers. They are still fully supported in asp.net core:
#Html.EditorFor(item => item.StatementActive, null, "StatementActive")

How do I programmatically download a file behind Oracle's OTN login page?

I'm trying to create a Chocolatey package for the Oracle WebLogic Server binaries. I know that I must pass a special cookie for the "license acceptance". But, I'm getting stuck trying to get past the login form. I've been researching how to get it done with wget or curl and I'm trying to map that to System.Net.WebClient, where applicable.
I have the following so far, which works for other Oracle downloads with license acceptance (like the JDK).
$url = "http://download.oracle.com/otn/nt/middleware/12c/wls/1212/wls1212_dev.zip"
$temp = Join-Path $ENV:TEMP "oracle-weblogic-server.zip"
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
$client.Headers.Add("Cookie", "gpw_e24=http://www.oracle.com")
$client = New-Object System.Net.WebClient
$client.DownloadFile($url, $temp)
I've read in a few places that the Oracle download page supports "basic" authentication. Which should mean setting a NetworkCredential. So, I set this before downloading...
$client.Credentials = New-Object System.Net.NetworkCredential("username", "password")
But, the response seems to contain a login page! (here is a fragment of the form). UPDATE: I think only the Oracle support portal supports basic authentication :(
<form action="https://login.oracle.com/mysso/signon.jsp" method="post" name="myForm">
<input type="hidden" name="v" value="v1.4">
<input type="hidden" name="p_submit_url" value="https://login.oracle.com:443/sso/auth">
<input type="hidden" name="p_cancel_url" value="https://edelivery.oracle.com">
<input type="hidden" name="p_error_code" value="">
<input type="hidden" name="ssousername" value="">
<input type="hidden" name="subscribername" value="">
<input type="hidden" name="authn_try_count" value="0">
<input type="hidden" name="contextType" value="external">
<input type="hidden" name="username" value="string">
<input type="hidden" name="contextValue" value="/oam">
<input type="hidden" name="password" value="sercure_string">
<input type="hidden" name="challenge_url" value="https://login.oracle.com/mysso/signon.jsp">
<input type="hidden" name="request_id" value="903089276773533395">
</form>
I also tried writing the authorization header directly, but I got the same result.
$client.Headers.Add("Authorization", "Basic " + [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("${username}:${password}")))
I stumbled on an old message about OTN not allowing command-line authentication. I don't know how to verify that, but other sites are saying the same thing (they might be parroting one source, though). But, I swear I've seen people POSTing credentials with wget and --post-data, I can't find it now.
I played with the WebClient.UploadValues to no avail. Maybe I'm picking the wrong names or the wrong URL? I have noticed some redirects in the responses and when I'm manually watching the traffic (Inspect Element | Network in Chrome). But, I don't know what do with this information!
$login = "https://login.oracle.com/mysso/signon.jsp"
$data = New-Object System.Collections.Specialized.NameValueCollection
$data.Add("username", "username")
$data.Add("password", "password")
$client.UploadValues($login, "POST", $data)
So, first, and most importantly, is there any way to login to OTN from the command line. Second, how do I do it with WebClient?
This method could possibly get you into trouble as it seems like the required login is there to specifically ensure it's a human on the other end.

Form Mobile Validation - after other functions have run

I need some help with the following issue. I am pretty new to JavaScript so this one is pretty tough for me. Any help would be greatly appreciated!
We have a form for registration that is already in use and I need to make some amends to it to enhance its usability. The form itself already contains several validation scripts and I need to add in a new one - an error message to appear next to the mobile field. I am unable to amend the form HTML itself so I have to do everything by javascript – I need to bind the new function to the submit button so that it fires AFTER all the other validations (field highlight, pop ups), but before the page turns over.
Here is the form (I have just left in the feild i need to amend) :
<form method="post" action="#" id="register_form" class="validate">
<input type="hidden" name="page" value="" />
<input type="hidden" name="unregistered" value="false" />
<fieldset>
<legend>I am a new online customer</legend>
<div class="element">
<label for="mobile_number">Mobile:**</label>
<input name="mobileNumber" type="text" id="mobile_number" title="Please enter at least one number" class="text validate {validate:{minLength:10, eitherOr:'#telephone_number', messages:{minLength:'Please enter a valid phone number (at least #NUM digits long)', eitherOr:'Please enter either your Telephone or Mobile number'}}}" />
</div>
<div class="element continue_shopping_cont submit">
<button type="submit" class="submit button small_button"><span>Register</span></button>
</div>
<input type="hidden" name="secure_from" value="" />
</fieldset>
</form>
Could someone help show me how i am supposed to do this and how is best to target this field?

Resources