Allow login to website only if request comes from another specific website

前端 未结 3 1706
Happy的楠姐
Happy的楠姐 2021-01-14 03:57

I have a PHP/MySQL website (website 1) that has a login system that only asks for a PIN code (just a long numeric string). A user has 2 ways of login in with this code:

相关标签:
3条回答
  • 2021-01-14 04:23

    I'm going to post this answer that I came out with thanks to the other answers/comments made by fellow SO users. I think it's a pretty simple method (simplicity is good in this case), and that it should work, but of course if it has any big flaw I'd be great to know :)

    Like I say in the OP, security (in terms of some savvy user getting around this and using the link directly instead of from website 2) isn't a huge deal here, we can deal with a small number of exceptions.

    Here's the idea:

    • Give the user in website 2 a link to a function in that same domain
    • That function grabs the PIN (i.e. 1234567890) that each user will have, and the current timestamp (i.e. 1417812842), creating a token using those 2 values, using another function that both websites will know (some sort of hashing with salt, for example)
    • Generate a redirect from website 2 to website 1, with a URL that includes the PIN and the token, something like: http://myURL.com/process_login_request.php?pin=123456789&token=abc123def456
    • A function in process_login_request.php, using the same function that was used to generate the token in website 2, will generate a number of tokens for the past X seconds (let's say 10 seconds), using the PIN and the timestamps for the past 10 seconds.
    • If any of the generated tokens match the received token means that the request was OK, and we allow the login

    I think it's easier to implement than to explain though. The idea basically is that we use timestamps in a short period of time (the time between the user "clicks" the link that should take him to website 1 and the time he actually lands on website 1). I said 10 seconds, but we could increase that as necessary if 10 seconds is too short (which I think it shouldn't be).

    0 讨论(0)
  • 2021-01-14 04:29

    The problem is multi-faceted. $_SERVER['HTTP_REFERER'] is available to PHP, but can be spoofed or omitted and is considered unreliable.

    Cross-domain cookies are a bit of a challenge as well; I understand it's possible, but haven't yet found time to implement it (we have a use case at work). At any rate, cookies, are also quite exploitable.

    Possibly your best bet would be to have the link point on "Site A" point to a resource also on "Site A" that sets a random key/token and timestamp into a shared database and fowards the browser to "Site B" with that token. The receiving page on "Site B" would then verify the existence of the key/token in the GET string, check for its existence in the database and possibly match the User-Agent and Referer data and checking that the time was within $smallnum seconds after the timestamp entry for that key/token.

    0 讨论(0)
  • 2021-01-14 04:41

    I think you're looking for a variation of Single Sign On. This is a technique in which an authentication in one site is recognised transparently in another. Here is how it works in your case.

    Normally you would have a link in site2.com like this:

    http://site1.com/login.php?pin=123456789

    However, site1.com cannot tell from the referrer which site it has really come from, since it it can be trivially faked. Of course, that may not matter for your use case, if you only want a simple level of security. But if you want something better, read on!

    You can use a hashing system and a shared secret, to create something that can only have come from one source. Both sites have the same shared secret, stored in a file. We'll call that $sharedSecret. The algorithm goes like this:

    $hash = hashFunction($pin . $sharedSecret);
    

    Then you can do this in site2.com:

    <a
        href="http://site1.com/login.php?pin=<?php echo (int) $pin ?>&amp;hash=<?php echo $hash ?>"
        alt="Authenticated link"
    >
    

    When site1.com sees it, it can get the PIN straight away, repeat the algorithm, and check that the hash really did come from site2.com. If you have several referring sites, then site1.com should store a separate secret for all of them, and then it can securely check the referrer to see which one it should load.

    The shared secret should be substantial enough that it cannot be guessed; I tend to go for around 40-60 characters.

    However, the remaining flaw in this plan is that someone could visit site2.com and steal a link from them, and it would still work, providing they were also willing to fake the referrer every time they wanted access. It may therefore be useful to add a timestamp into the algorithm too:

    // The time is rounded to the nearest 500 seconds, to account for
    // out of sync clocks. Adjust this depending on how long you want links to
    // remain active for
    $time = floor(time() / 500) * 500;
    $hash = hashFunction($pin . $sharedSecret . $time);
    

    Then on site1.com you should compute two hashes:

    • One for floor(time() / 500) * 500
    • One for floor(time() / 500) * 500 - 500

    If the supplied hash matches either, allow the link to unlock the content. This accounts for the possibility that the time went over a +/-500 boundary between one server and the next.

    I haven't mentioned a specific hashing function here. SHA256 should be fine, but note I'm not a cryptographer. If you want more security again, it may be worth checking to ensure someone isn't brute-forcing the system by flooding your system with guesses - though over the internet it is hardly worth their trying.

    0 讨论(0)
提交回复
热议问题