Безопасность аккаунта путем отправки кода по электронной почте вместо 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
}
}
}
вам придется сделать значительно больше работы, чем это, но я надеюсь, что вы получите концепцию.