How to POST to HTTPs?

2020-04-02 22:22发布

问题:

Assume i have a form that right now is doing a post:

<form id="post-form" class="post-form" 
      action="/questions/ask/submit" method="post">

You'll notice there is no site in the action, the browser follows where it got the page from.

The browser follows current domain rules when posting

If the current page is...                then the browser will POST to
=======================================  =============
http://stackoverflow.com/questions/ask   http://stackoverflow.com/questions/ask/submit
https://stackoverflow.com/questions/ask  https://stackoverflow.com/questions/ask/submit

But I want to ensure that the browser will always go to the secure page:

http://stackoverflow.com/questions/ask   https://stackoverflow.com/questions/ask/submit

Normally you would try something like:

<form id="post-form" class="post-form" 
      action="https://stackoverflow.com/questions/ask/submit" method="post">

Except that requires knowing the domain and virtual path name of hosting site (e.g. stackoverflow.com). If the site were changed:

  • stackoverflow.net
  • stackoverflow.com/mobile
  • de.stackoverflow.com
  • stackoverflow.co.uk/fr
  • beta.stackoverflow.com

then the form action would have to be updated also:

<form id="post-form" class="post-form" action="https://stackoverflow.net/questions/ask/submit" method="post">

<form id="post-form" class="post-form" action="https://stackoverflow.com/mobile/questions/ask/submit" method="post">

<form id="post-form" class="post-form" action="https://de.stackoverflow.com/questions/ask/submit" method="post">

<form id="post-form" class="post-form" action="https://stackoverflow.co.uk/fr/questions/ask/submit" method="post">

<form id="post-form" class="post-form" action="https://beta.stackoverflow.com/questions/ask/submit" method="post">

How can I instruct the browser to go to https version of a page?


Hypothetical syntax:

<form id="post-form" class="post-form" action="https://./questions/ask/submit" method="post">

302, 303, 307

Originally 302 Found was the code to tell the user agent to go someplace else. The intention was that browsers would simply try again at the new location:

POST /questions/ask/submit

302 Found
Location: /submitquestion

POST /submitquestion

Unfortunately all browsers got it wrong, and would mistakenly always use GET on the new location:

POST /questions/ask/submit

302 Found
Location: /submitquestion

GET /submitquestion

Because browsers got it wrong, two new codes were created:

  • 302 Found: (Legacy deprecated) Try the exact same thing again at the new location; but legacy browsers were switching to GET
  • 303 See Other: Forget whatever the user was doing, and go do a GET on this Location
  • 307 Temporary Redirect: Try the exact same thing again at the new Location (No, seriously, the same thing - i didn't say you could switch to GET. If you were doing a DELETE then go DELETE it over here.)

For example, if the user agent was in the middle of a POST:

| Response               | What agent should do  | What many agents actually do |
|------------------------|-----------------------|------------------------------|
| 302 Found              | POST to new Location  | GET from new Location        |
| 303 See Other          | GET from new Location | GET from new Location        |
| 307 Temporary Redirect | POST to new Location  | POST to new Location         |

Ideally, there would be a way to use 307 Temporary Redirect to tell the user agent to try the POST again on the secure URL:

POST /questions/ask/submit

307 Temporary Redirect
Location: https://beta.stackoverflow.com/questions/ask/submit

POST /questions/ask/submit

and i can get away with that well enough server-side in ASP.net:

if (!Request.IsSecureConnection)
{
   string redirectUrl = Request.Url.ToString().Replace("http:", "https:");
   Response.Redirect(redirectUrl);

   //We don't want to send the client the deprecated 302 code, we want to use 307 telling them that we really want them to continue the POST, PUT, DELETE, etc
   Response.StatusCode = (int)System.Net.HttpStatusCode.TemporaryRedirect;     
   Response.End();
}

But i don't know if you can specify a full uri in a Location.

回答1:

you can change the form's action with javascript:

var form = document.getElementById("post-form");
form.action = location.href.replace(/^http:/, 'https:');

But there are some security considerations, and I would suggest you to redirect your form's url to https. And although you could do it from javascript, you should never trust javascript when it gets to security, so do it from the server (it's also faster, the page doesn't have to be loaded, only the http header)



回答2:

You'd better make sure that if the user has landed on your http page you redirect him to the https equivalent. In your :

<script>
if ((window.location.href.substring(0, 8) != "https://") {
  window.location = location.href.replace(/^http:/, 'https:');
}
</script>