📜 ⬆️ ⬇️

Come in! Authentication without login and password, v2

Once it turned out that the audience was not indifferent to such a topic as the creation of one-time (working for some time) links to identify the user.

And especially in the light of what I consider such a solution (which I will publish below) is more acceptable - I decided to write how I see the solution to this problem:

Everything is stored in the database. Mysql only because it is now at hand. For the postgame, oracle and sql server solution will be 99% similar.

Storage table:
')
Copy Source | Copy HTML CREATE TABLE test.one_time_auth( token CHAR (32), user_id INT (11) UNSIGNED NOT NULL , expire DATETIME DEFAULT NULL , PRIMARY KEY (token) ) ENGINE = INNODB
  1. Copy Source | Copy HTML CREATE TABLE test.one_time_auth( token CHAR (32), user_id INT (11) UNSIGNED NOT NULL , expire DATETIME DEFAULT NULL , PRIMARY KEY (token) ) ENGINE = INNODB
  2. Copy Source | Copy HTML CREATE TABLE test.one_time_auth( token CHAR (32), user_id INT (11) UNSIGNED NOT NULL , expire DATETIME DEFAULT NULL , PRIMARY KEY (token) ) ENGINE = INNODB
  3. Copy Source | Copy HTML CREATE TABLE test.one_time_auth( token CHAR (32), user_id INT (11) UNSIGNED NOT NULL , expire DATETIME DEFAULT NULL , PRIMARY KEY (token) ) ENGINE = INNODB
  4. Copy Source | Copy HTML CREATE TABLE test.one_time_auth( token CHAR (32), user_id INT (11) UNSIGNED NOT NULL , expire DATETIME DEFAULT NULL , PRIMARY KEY (token) ) ENGINE = INNODB
  5. Copy Source | Copy HTML CREATE TABLE test.one_time_auth( token CHAR (32), user_id INT (11) UNSIGNED NOT NULL , expire DATETIME DEFAULT NULL , PRIMARY KEY (token) ) ENGINE = INNODB
  6. Copy Source | Copy HTML CREATE TABLE test.one_time_auth( token CHAR (32), user_id INT (11) UNSIGNED NOT NULL , expire DATETIME DEFAULT NULL , PRIMARY KEY (token) ) ENGINE = INNODB
  7. Copy Source | Copy HTML CREATE TABLE test.one_time_auth( token CHAR (32), user_id INT (11) UNSIGNED NOT NULL , expire DATETIME DEFAULT NULL , PRIMARY KEY (token) ) ENGINE = INNODB


Well, now the class itself + an example of working with it. In the example, we first create a token for the period until December 31 of this year, and then we get it.

Copy Source | Copy HTML
  1. <? php
  2. $ db = new PDO ( 'mysql: host = 127.0.0.1; dbname = test' , 'root' );
  3. $ db -> setAttribute ( PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION);
  4. $ auth = new one_time_auth ( $ db );
  5. $ token = $ auth -> remember ( 10 , '2010-12-31' );
  6. $ user_id = $ auth -> remind ( $ token );
  7. echo $ user_id ;
  8. class one_time_auth
  9. {
  10. / ** <br/> * @var PDO <br/> * /
  11. private $ db ;
  12. public function __construct ( PDO $ db )
  13. {
  14. $ this -> db = $ db ;
  15. }
  16. public function remember ( $ user_id , $ expire = null )
  17. {
  18. $ sql = 'INSERT INTO one_time_auth (token, user_id, expire) VALUES (: token,: user_id,: expire)' ;
  19. $ stmt = $ this -> db-> prepare ( $ sql );
  20. while ( true ) {
  21. try {
  22. $ stmt -> execute ( array (
  23. ': token' => $ token = $ this -> generateToken (),
  24. 'user_id' => $ user_id ,
  25. 'expire' => $ expire
  26. ))
  27. break ;
  28. } catch ( PDOException $ e ) {}
  29. }
  30. return $ token ;
  31. }
  32. public function remind ( $ token )
  33. {
  34. $ sql = 'SELECT user_id <br/> FROM one_time_auth <br/> WHERE token =: token <br/> AND (expire IS NULL OR expire <= NOW ()) LIMIT 1' ;
  35. $ stmt = $ this -> db-> prepare ( $ sql );
  36. $ stmt -> execute ( array ( 'token' => $ token ));
  37. if ( $ row = $ stmt -> fetch ()) {
  38. $ stmt = $ this -> db-> prepare ( 'DELETE FROM one_time_auth WHERE token =: token' );
  39. $ stmt -> execute ( array ( 'token' => $ token ));
  40. return $ row [ 'user_id' ];
  41. }
  42. }
  43. private function generateToken ()
  44. {
  45. return md5 (uniqid ( '' , true ));
  46. }
  47. }

PS: the code was written "on the knee" simply as a response to the topic habrahabr.ru/blogs/php/109421

PPS: I would immediately like to clarify about md5 () - this function in this context does not add any “holes”, this is just a way to get a hash. If desired, you can replace with sha1 (), or any other at will. The main idea is that you do not need to be tied to user data.

Source: https://habr.com/ru/post/109454/


All Articles