Is it possible to reliably know where an HTTP request originated without scripting?
I've been tasked with serving up an image file from our server that is referenced in an html document residing on a number of other servers. To 开发者_开发知识库wit:
file on foo.com:
<img src='http://bar.com/image.jpg'>
When a user goes to foo.com, it displays the image from our server, bar.com. (It actually sends a different image based on what website made the request.)
But here's the catch: they only want visitors of specific companies to be able to retrieve the file (currently identified by the server's domain name, but that's not a requirement).
In a perfect world, you'd just look at the HTTP_REFERER and if it's on the approved list, serve up the file. But as everyone knows, not every user agent supplies the HTTP_REFERER, and it can be spoofed anyway.
It would be better to not have to run javascript or php, but is what we're after even possible without scripting?
If not, is there a way to do this using only javascript in such a way that another website can't spoof their way into downloading the file?
If there's not, how would you approach it using PHP?
In short, no. The only reliable information you have is the IP address that requested the image, but even that may be a proxy. There's no reliable way to figure out what context an image was requested in (i.e. which HTML page the image is embedded in).
What you want is to allow only certain people to access the image. There are two ways to do that:
- filter by requesting IP address if that is known
- require an authenticated session/cookie/Authorization header, i.e. password protect the image
If your webserver supports either of these checks (virtually any server can filter requests by IP), there's no need for scripting. For password authentication you may have to use scripting, depending on how exactly it should work.
(Client-side) Javascript won't be of any use here at all.
Do you have any influence over the approved companies' web apps? If so, I can think of two ways you can accomplish this.
Using your foo/bar examples, where bar.com is your server, and foo.com is one of your approved companies:
1) Instead of the browser making a request to your server, have them make a request to an image handler on foo.com, which in turn makes a HTTP request to your server behind the scenes and returns the image contents back to the client. Foo's outgoing IP address would be on a white-list on your server, so all requests are actually coming from Foo's IP address. The client would see:
<img src="http://foo.com/imagehandler.php" />
2) Much more difficult, but if Foo cannot make the request to your servers, Foo can put a special hash in the query string of the image tag so that when the browser makes a request to your server, you'll know that the URL was built by Foo. You'll need a private key on Foo's server so that it can calculate the hash.
I'd guess the hash would be calculated based on a combination of the brower's IP address, current date/time, and the private key.
So the browser would make a request to foo.com/default.php, and Foo would build the following image tag for the browser:
<img src="http://bar.com/imagehandler.php?hash=393923A423B423F234C34" />
where that number represents the appropriate hash. In Bar's image handler code, you'll need to re-calculate that hash based on the private key which is only known to Foo and Bar, the IP address which is part of the GET request, and the current date/time. If the hash matches, then you can be pretty sure that the browser is looking at foo.com's website, and you can return the image contents.
精彩评论