Безопасность аккаунта путем отправки кода по электронной почте вместо SMS: Laravel 5.2

когда мы входим в нашу учетную запись gmail в первый раз или после удаления кэша и cookie, мы получаем окно для ввода кода, который отправляется на наш мобильный телефон.

Я пытаюсь реализовать это, но по электронной почте вместо SMS. Ниже приведен мой подход к реализации этого.

Я по этой ссылке : https://laravel.com/docs/5.2/session

и создать Session table в базе данных. Я также могу видеть свой браузер подробности в записи таблицы сеансов. Я не уверен, что это правильный подход.

Gmail имеет положение отслеживать несколько браузеров. Это означает, что если я в последний раз вошел в систему из Firefox и на этот раз из Chrome, то меня снова попросят код. В будущем меня не попросят заполнить код для Chrome и Firefox, если кэш / cookie не будет удален.

может кто-нибудь дать мне любую ссылку, которая объясняет, как сделать резерв для нескольких браузеров, когда это кэш / cookie спас ? так что я могу отправить по электронной почте код безопасности

3 ответов


вы можете достичь этого, выпустив дополнительный cookie (скажем, browser_cookie), чтобы запомнить уже аутентифицированный браузер.

реализация:

создайте следующую таблицу (browser_management):

token (pk)| user_id (fk) | series_identifier

где:
маркер: хэшированная форма маркера, выданного пользователю (с использованием bcrypt или аналогичного алгоритма) (маркер, выданный пользователю, сам по себе, является непредсказуемым случайным ключом из подходящего большого пространства)
series_identifier : угадываемый случайно сгенерированный ключ из подходящего большого пространства

Всякий раз, когда пользователь входит в систему, проверьте browser_cookie.

Пример 1: пользователь регистрируется в первый раз.
Учитывая, что пользователь входит в систему в первый раз browser_cookie не будет. Таким образом, вы отправите электронное письмо с кодом аутентификации.
После аутентификации создайте два случайных числа для token и series_identifier. Хранить hashed token и series_identifier на browser_management таблица, для пользователя, идентифицированного user_id.
Кроме того, выдайте browser_cookie пользователю с token и series_identifier.

Пример 2: пользователь повторно регистрируется в следующий раз.
Теперь, когда тот же пользователь входит в следующий раз, возьмите token найти запись в browser_management таблица с хэш token.
Если найдено, проверьте, если user_id и series_identifier матчи.
пример 2.1: записи совпадение:
Разрешить пользователю входить в систему без необходимости повторной аутентификации кода электронной почты.
Создайте еще один токен и замените token на cookie а также table С Новым. (Это снизит риск захвата сеанса).
дело 2.2: записи не совпадает:
Выполните действия для проверки подлинности электронной почты и уведомите пользователя о возможной краже.(Например, gmail уведомляет новый браузер входы.)

ссылки:

Улучшена Постоянная Практика Входа В Cookie
каков наилучший способ реализации "Запомнить меня" для веб-сайта?

обновление:

Пример Кода:

миграция:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class browser_management extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('browser_management', function (Blueprint $table) {
            $table->string('token');
            $table->string('user_id');
            $table->string('series_identifier');            
            $table->timestamps();
            $table->primary('token');
            $table->foreign('user_id')->references('id')->on('users');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('users');
    }
}

промежуточное: создать новое промежуточное ПО

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;
use Cookies;

class Email_verification
{
    public function handle($request, Closure $next, $guard = null)
    {
        //retrieve $token from the user's cookie
        $token = $request->cookie('browser_cookie');

        //check id token is present
        if($token == null){
            //if token is not present allow the request to the email_verification
            return $next($request);
        }
        else{
            //Retrieve the series_identifier issued to the user
            $series_identifier = Auth::user()
                                    ->series_identifier(Hash::make($token))
                                    ->first()
                                    ->series_identifier;

            //Check if series_identifier matches            
            if($series_identifier != $request->cookie('series_identifier')){
                //if series_identifier does not match allow the request to the email_verification
                return $next($request);
            }
        }

       return redirect('/dashboard'); //replace this with your route for home page
    }
}

сделайте запись промежуточного ПО в kernel.php

protected $routeMiddleware = [
        'email_verification' => \App\Http\Middleware\Email_verification::class,
        //your middlewares
];

Пользователя Модели: добавьте следующий метод в модель пользователя

// method to retieve series_identifier related to token
public function series_identifier($token){
    return $this->hasMany(Browser_management::class)->where('token',$token);
}

//method to retriev the tokens related to user
public function tokens (){
    return $this->hasMany(Browser_management::class);
}

Модель Browser_management: создайте модель для представления таблицы browser_managements

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;


class Browser_management extends Model
{
    protected $primaryKey = 'token';
    protected $fillable = array('token','series_identifier');

    public function User(){
        return $this->hasOne('App\Models\User');
    }    
}

Методы Проверки Электронной Почты: добавьте следующие методы в AuthController для обработки проверки электронной почты

public function getVerification(Request $request){
    //Create a random string to represent the token to be sent to user via email. 
    //You can use any string as we are going to hash it in our DB
    $token = str_random(16);

    //Generate random string to represent series_identifier
    $series_identifier = str_random(64);

    //Issue cookie to user with the generated series_identifier
    Cookie::queue('series_identifier', $series_identifier,43200,null,null,true,true);

    //Store the hashed token and series_identifier ini DB
    Auth::user()->tokens()->create(['token'=>Hash::make($token)]);

    //Your code to send an email for authentication

    //return the view with form asking for token
    return view('auth.email_verification');
}

public function postVerification(Request $request){
    //Retrieve the series_identifier issued to the user in above method
    $series_identifier = $request->cookie('series_identifier');

    //Retrieve the token associated with the series_identifier
    $token = Auth::user()
                ->tokens()
                ->where('series_identifier',$series_identifier)
                ->first()
                ->value('token');

    //Check if the user's token's hash matches our token entry
    if(Hash::check($request->token,$token)){
        // If token matched, issue the cookie with token id in it. Which we can use in future to authenticate the user
        Cookie::queue('token', $token,43200,null,null,true,true);
        return redirect('dashboard');
    }

    //If token did not match, redirect user bak to the form with error
    return redirect()->back()
                ->with('msg','Tokens did not match');
}

маршруты: добавить эти маршруты для обработки электронной почты запросы на проверку. Мы также добавим к нему промежуточное ПО email_verification.

Route::get('/auth/email_verification',`AuthController@getVerification')->middleware('email_verification');
Route::post('/auth/email_verification',`AuthController@postVerification')->middleware('email_verification');<br/>

обновление 2:

относительно потока gmail..
Я сделал следующие шаги:
1) Войдите в gmail с последующей 2-шаговой проверкой.
2)выход
3)Очистить кэш ссылке
4)войти снова

когда я снова вошел в систему, после очистить кэш, он не попросил меня 2-step проверка.

хотя, если вы очистить cookies, он попросит 2-ступенчатую проверку. причина:
Все пользовательские данные, которые идентифицируют пользователя (здесь token) хранится в cookies. И если вы очистите куки, сервер не будет иметь механизма для идентификации пользователя.

обновление 3:

Gmail просит 2-шаг проверки:
Прежде всего Gmail или любой другой веб-сайт не уведомление об очистке кэша
Как дано здесь:

кэш-это не что иное, как место на вашем жестком диске, где браузер сохраняет вещи, которые он загрузил один раз, если они нужны снова.

теперь cookies-это небольшие текстовые файлы, выдаваемые сервером для хранения информации, связанной с пользователем. Как дано здесь

основной целью cookie является идентификация пользователей и возможно, подготовить индивидуальные веб-страницы или сохранить информацию для входа на сайт для вас.

таким образом, в основном, когда вы очищаете куки в своем браузере, веб-сервер не получит никаких пользовательских данных. Таким образом, пользователь будет считаться гостем и будет рассматриваться соответственно.


создайте дополнительную таблицу (помимо сессионной)

что-то вроде

UserId | UserAgent / IP

и когда они идут для входа в систему, проверьте, что против их текущих значений в $_SERVER массив. Если там все хорошо, если не прерывать логин, и отправить им ссылку для подтверждения новых данных. Вероятно, вы захотите сделать какой-то ajax в исходном логине, чтобы проверить, когда они вошли в систему, а затем, как только это произойдет, сделайте перенаправление туда, где они уходили.

смысла.

Как я сказал в комментариях для ремонтопригодности, я бы сам справился с этим и не использовал сторонние API, данные достаточно легко проверить. Эта часть относительно тривиальна, продолжая процесс входа в систему не так много.


OP, если я понимаю вас ясно, вы просто хотите понять, как реализовать таблицу сеансов laravel, чтобы вы могли иметь несколько входа от одного пользователя в одном браузере:

Schema::create('sessions', function ($table) {
    $table->string('id')->unique();
    $table->integer('user_id')->nullable();
    $table->string('ip_address', 45)->nullable();
    $table->text('user_agent')->nullable();
    $table->text('payload');
    $table->integer('last_activity');
});

пока этот вопрос был ответил Раньше здесь Я добавлю, что вы можете легко достичь этой функции в вашем фактическом методе входа в систему без изменения ваших основных файлов.

для этого вы можете следовать следующей логике

перед входом в систему проверьте вручную, Если заголовок агента пользователя запроса совпадает с заголовком агента пользователя сеанса в сеансе, т. е.:

public function authenticate()
{
    $data = Input::all();
    $user = User::where('email', '=', $data['email'])->first();
    if($user != null)
    {
         //check if user agent different from session
         if($request->header('User-Agent') != session('user_agent'))
         {
             //do some extra login/password validation check
         }
         if(Auth::attempt($data))
         {
             //here you now may manually update the session ID on db
         }
    }
}

вам придется сделать значительно больше работы, чем это, но я надеюсь, что вы получите концепцию.