跟社区学laravel博客实战7--未完成

整个激活流程如下:
1、用户注册成功后,自动生成激活令牌;
2、将激活令牌以链接的形式附带在注册邮件里面,并将邮件发送到用户的注册邮箱上;
3、用户点击注册链接跳到指定路由,路由收到激活令牌参数后映射给相关控制器动作处理;
4、控制器拿到激活令牌并进行验证,验证通过后对该用户进行激活,并将其激活状态设置为已激活;
5、用户激活成功,自动登录;

接下来让我们跟之前一样,新建一个 Git 分支来开发新功能。

git checkout master
git checkout -b account-activation-password-resets

添加字段
在用户的账号激活功能中,我们需要为激活令牌 (activation_token) 和激活状态 (activated) 字段新增一个迁移,来将这两个字段添加到用户表中。由于我们进行的是字段添加操作,因此在命名迁移文件时需要加上前缀,遵照如 add_column_to_table 这样的命名规范,并在生成迁移文件的命令中启用 --table 项目,用于指定对应的数据库表。最终的生成命令如下:

php artisan make:migration add_activation_to_users_table --table=users

使用随机字符来生成用户的激活令牌,因此这里的激活令牌字段需要为 string 类型,在用户成功激活以后,我们还会对激活令牌进行清空,避免用户进行多次使用,因此我们还需要将字段设置为 nullable,代表该字段允许为空。而用户的激活状态只有已激活和未激活两种状态,默认为未激活的状态,因此我们可以将激活状态设置为 boolean 类型,当其值为真时,代表已激活,反之亦然。
现在让我们来为新增的迁移文件加上这两个字段。

database/migrations/[timestamp]_add_activation_to_users_table.php




<?php

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

class AddActivationToUsersTable extends Migration
{
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('activation_token')->nullable();
            $table->boolean('activated')->default(false);
        });
    }

    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('activation_token');
            $table->dropColumn('activated');
        });
    }
}

接着我们还需要运行迁移,将字段加入到用户表中。

php artisan migrate

生成令牌

用户的激活令牌需要在用户创建(注册)之前就先生成好,这样当用户注册成功之后我们才可以将令牌附带到注册链接上,并通过邮件的形式发送给用户。

creating 用于监听模型被创建之前的事件,created 用于监听模型被创建之后的事件。接下来我们要生成的用户激活令牌需要在用户模型创建之前生成,因此需要监听的是 creating 方法。
在用户模型中添加 creating 方法如下(注意顶部 use Illuminate\Support\Str;)

app/Models/User.php





<?php

namespace App\Models;
.
.
.
use Illuminate\Support\Str;

class User extends Authenticatable
{
    .
    .
    .
    protected $hidden = [
        'password', 'remember_token',
    ];

    public static function boot()
    {
        parent::boot();

        static::creating(function ($user) {
            $user->activation_token = Str::random(10);
        });
    }
    .
    .
    .
}

boot 方法会在用户模型类完成初始化之后进行加载,因此我们对事件的监听需要放在该方法中。

现在,我们需要更新模型工厂,将生成的假用户都设为已激活状态:

database/factories/UserFactory.php




<?php

use App\Models\User;
use Illuminate\Support\Str;
use Faker\Generator as Faker;

$factory->define(User::class, function (Faker $faker) {
    $date_time = $faker->date . ' ' . $faker->time;
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'email_verified_at' => now(),
        'activated' => true,
        'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret
        'remember_token' => Str::random(10),
        'created_at' => $date_time,
        'updated_at' => $date_time,
    ];
});

完成之后,我们重置并填充数据库。

php artisan migrate:refresh --seed

邮件程序

对环境配置文件 .env 进行配置,使用 log 邮件驱动的方式来调试邮件发送功能

.
.
.
MAIL_DRIVER=log
.
.
.

激活路由

routes/web.php




<?php

Route::get('/', 'StaticPagesController@home')->name('home');
Route::get('/help', 'StaticPagesController@help')->name('help');
Route::get('/about', 'StaticPagesController@about')->name('about');

Route::get('signup', 'UsersController@create')->name('signup');
Route::resource('users', 'UsersController');

Route::get('login', 'SessionsController@create')->name('login');
Route::post('login', 'SessionsController@store')->name('login');
Route::delete('logout', 'SessionsController@destroy')->name('logout');

Route::get('signup/confirm/{token}', 'UsersController@confirmEmail')->name('confirm_email');

在 Laravel 中,我们使用视图来构建邮件模板,在用户查收邮件时,该模板将作为内容展示视图。接下来我们需要创建一个用于渲染注册邮件的 confirm 视图。

resources/views/emails/confirm.blade.php





<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>注册确认链接</title>
</head>
<body>
  <h1>感谢您在 Weibo App 网站进行注册!</h1>

  <p>
    请点击下面的链接完成注册:
    <a href="{{ route('confirm_email', $user->activation_token) }}">
      {{ route('confirm_email', $user->activation_token) }}
    </a>
  </p>

  <p>
    如果这不是您本人的操作,请忽略此邮件。
  </p>
</body>
</html>

登录时检查是否已激活#
在我们前面章节加入的登录操作中,用户即使没有激活也能够正常登录。接下来我们需要对之前的登录代码进行修改,当用户没有激活时,则视为认证失败,用户将会被重定向至首页,并显示消息提醒去引导用户查收邮件。

app/Http/Controllers/SessionsController.php





<?php

namespace App\Http\Controllers;
.
.
.
class SessionsController extends Controller
{
    .
    .
    .
    public function store(Request $request)
    {
       $credentials = $this->validate($request, [
           'email' => 'required|email|max:255',
           'password' => 'required'
       ]);

       if (Auth::attempt($credentials, $request->has('remember'))) {
            if(Auth::user()->activated) {
               session()->flash('success', '欢迎回来!');
               $fallback = route('users.show', Auth::user());
               return redirect()->intended($fallback);
           } else {
               Auth::logout();
               session()->flash('warning', '你的账号未激活,请检查邮箱中的注册邮件进行激活。');
               return redirect('/');
           }
       } else {
           session()->flash('danger', '很抱歉,您的邮箱和密码不匹配');
           return redirect()->back()->withInput();
       }
    }
    .
    .
    .
}

发送邮件#

接下来我们要开始使用邮箱发送功能,在 Laravel 中,可以通过 Mail 接口的 send 方法来进行邮件发送,

接下来让我们为用户控制器定义一个 sendEmailConfirmationTo 方法,该方法将用于发送邮件给指定用户。我们会在用户注册成功之后调用该方法来发送激活邮件,具体代码实现如下

请注意顶部加载 use Mail;):

app/Http/Controllers/UsersController.php





<?php

namespace App\Http\Controllers;.
.
.
.
use Mail;

class UsersController extends Controller
{
    .
    .
    .
    public function store(Request $request)
    {
        $this->validate($request, [
            'name' => 'required|max:50',
            'email' => 'required|email|unique:users|max:255',
            'password' => 'required|confirmed|min:6'
        ]);

        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => bcrypt($request->password),
        ]);

        $this->sendEmailConfirmationTo($user);
        session()->flash('success', '验证邮件已发送到你的注册邮箱上,请注意查收。');
        return redirect('/');
    }
    .
    .
    .
    protected function sendEmailConfirmationTo($user)
    {
        $view = 'emails.confirm';
        $data = compact('user');
        $from = 'summer@example.com';
        $name = 'Summer';
        $to = $user->email;
        $subject = "感谢注册 Weibo 应用!请确认你的邮箱。";

        Mail::send($view, $data, function ($message) use ($from, $name, $to, $subject) {
            $message->from($from, $name)->to($to)->subject($subject);
        });
    }
}

请注意我们需要调用 use Mail 来引入邮件相关的操作方法。通过上面代码可以看到,我们把之前用户注册成功之后进行的登录操作:

Auth::login($user);

替换为了激活邮箱的发送操作:

$this->sendEmailConfirmationTo($user);

注册成功提示语改为查看邮箱的提示语。在激活邮件发送成功之后,我们还会将用户重定向至首页,而并非之前的用户个人页。

激活功能

现在的邮箱发送功能已经能够正常使用,接下来让我们完成前面定义的 confirm_email 路由对应的控制器方法 confirmEmail,来完成用户的激活操作。并且在 __construct 方法里开启未登录用户访问权限。

app/Http/Controllers/UsersController.php





<?php

namespace App\Http\Controllers;.
.
.
.
class UsersController extends Controller
{
    public function __construct()
    {

        $this->middleware('auth', [
            'except' => ['show', 'create', 'store', 'index', 'confirmEmail']
        ]);
        .
        .
        .

    }
    .
    .
    .
    public function confirmEmail($token)
    {
        $user = User::where('activation_token', $token)->firstOrFail();

        $user->activated = true;
        $user->activation_token = null;
        $user->save();

        Auth::login($user);
        session()->flash('success', '恭喜你,激活成功!');
        return redirect()->route('users.show', [$user]);
    }
}

Auth 中间件黑名单中,我们增加了 confirmEmail 来开启未登录用户的访问。
在 confirmEmail 中,我们会先根据路由传送过来的 activation_token 参数从数据库中查找相对应的用户,Eloquent 的 where 方法接收两个参数,第一个参数为要进行查找的字段名称,第二个参数为对应的值,查询结果返回的是一个数组,因此我们需要使用 firstOrFail 方法来取出第一个用户,在查询不到指定用户时将返回一个 404 响应。在查询到用户信息后,我们会将该用户的激活状态改为 true,激活令牌设置为空。最后将激活成功的用户进行登录,并在页面上显示消息提示和重定向到个人页面。

现在打开 Laravel 的 Log 文件

storage/logs/laravel.log

 

Git 代码版本控制#
接着让我们将本次更改纳入版本控制中:
$ git add -A
$ git commit -m "用户激活"

 

密码重设

密码重设的步骤如下:

用户点击进入 忘记密码页面;在忘记密码页面 提交邮箱信息;控制器通过该邮箱查找到指定用户并为该用户生成一个密码令牌,接着将该令牌以链接的形式发送到用户提交的邮箱上;用户查看自己个人邮箱,点击重置密码链接跳转到重置密码页面;用户在该页面输入自己的邮箱和密码并提交;控制器对用户的邮箱和密码重置令牌进行匹配,匹配成功则更新用户密码;
了解其中的整个流程之后,接下来的开发就容易多了。
本节我们来开发 1~ 3,下一节开发 4~6 。

 

新增路由#

routes/web.php





.
.
.
Route::get('password/reset',  'PasswordController@showLinkRequestForm')->name('password.request');
Route::post('password/email',  'PasswordController@sendResetLinkEmail')->name('password.email');

Route::get('password/reset/{token}',  'PasswordController@showResetForm')->name('password.reset');
Route::post('password/reset',  'PasswordController@reset')->name('password.update');

四个路由分别是:

showLinkRequestForm —— 填写 Email 的表单 sendResetLinkEmail —— 处理表单提交,成功的话就发送邮件,附带 Token 的链接 showResetForm —— 显示更新密码的表单,包含 tokenreset —— 对提交过来的 token 和 email 数据进行配对,正确的话更新密码


新增忘记密码入口

接下来让我们修改用户的登录页面,添加修改密码的链接,方便忘记密码的用户在第一时间找到入口。

resources/views/sessions/create.blade.php





@extends('layouts.default')
@section('title', '登录')

@section('content')
<div class="offset-md-2 col-md-8">
  <div class="card ">
    <div class="card-header">
      <h5>登录</h5>
    </div>
    <div class="card-body">
      @include('shared._errors')

      <form method="POST" action="{{ route('login') }}">
          {{ csrf_field() }}

          <div class="form-group">
            <label for="email">邮箱:</label>
            <input type="text" name="email" class="form-control" value="{{ old('email') }}">
          </div>

          <div class="form-group">
            <label for="password">密码(<a href="{{ route('password.request') }}">忘记密码</a>):</label>
            <input type="password" name="password" class="form-control" value="{{ old('password') }}">
          </div>

          <div class="form-group">
            <div class="form-check">
              <input type="checkbox" class="form-check-input" name="remember" id="exampleCheck1">
              <label class="form-check-label" for="exampleCheck1">记住我</label>
            </div>
          </div>

          <button type="submit" class="btn btn-primary">登录</button>
      </form>

      <hr>

      <p>还没账号?<a href="{{ route('signup') }}">现在注册!</a></p>
    </div>
  </div>
</div>
@stop

忘记密码页面#

创建页面:

resources/views/auth/passwords/email.blade.php





@extends('layouts.default')
@section('title', '重置密码')

@section('content')
<div class="col-md-8 offset-md-2">
  <div class="card ">
    <div class="card-header"><h5>重置密码</h5></div>

    <div class="card-body">
      @if (session('status'))
      <div class="alert alert-success">
        {{ session('status') }}
      </div>
      @endif

      <form class="" method="POST" action="{{ route('password.email') }}">
        {{ csrf_field() }}

        <div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
          <label for="email" class="form-control-label">邮箱地址:</label>

          <input id="email" type="email" class="form-control" name="email" value="{{ old('email') }}" required>

          @if ($errors->has('email'))
            <span class="form-text">
              <strong>{{ $errors->first('email') }}</strong>
            </span>
          @endif
        </div>

        <div class="form-group">
          <button type="submit" class="btn btn-primary">
            发送密码重置邮件
          </button>
        </div>
      </form>
    </div>
  </div>
</div>
@endsection

接下来创建控制器方法:

app/Http/Controllers/PasswordController.php





<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class PasswordController extends Controller
{
    public function showLinkRequestForm()
    {
        return view('auth.passwords.email');
    }
}

访问忘记密码页面 weibo.test/password/reset :

发送重置链接#

在密码重设功能中,我们还会用到一个用来保存密码重置令牌的数据表,Laravel 已为我们生成好了该数据表:
 

database/migrations/2014_10_12_100000_create_password_resets_table.php




<?php

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

class CreatePasswordResetsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('password_resets', function (Blueprint $table) {
            $table->string('email')->index();
            $table->string('token')->index();
            $table->timestamp('created_at');
        });
    }

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

可以看到 Laravel 默认生成的密码重置表有三个字段 email, token, created_at,分别用于生成用户邮箱、密码重置令牌、密码重置令牌的创建时间,并为邮箱和密码重置令牌加上了索引,这样在数据库使用这两个字段进行查找时效率更快。
接下来新增 sendResetLinkEmail() 方法来处理发送找回密码邮件的逻辑:

app/Http/Controllers/PasswordController.php





<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\User;
use Hash;
use Illuminate\Support\Str;
use DB;
use Mail;
use Carbon\Carbon;

class PasswordController extends Controller
{
    public function showLinkRequestForm()
    {
        return view('auth.passwords.email');
    }

    public function sendResetLinkEmail(Request $request)
    {
        // 1. 验证邮箱
        $request->validate(['email' => 'required|email']);
        $email = $request->email;

        // 2. 获取对应用户
        $user = User::where("email", $email)->first();

        // 3. 如果不存在
        if (is_null($user)) {
            session()->flash('danger', '邮箱未注册');
            return redirect()->back()->withInput();
        }

        // 4. 生成 Token,会在视图 emails.reset_link 里拼接链接
        $token = hash_hmac('sha256', Str::random(40), config('app.key'));

        // 5. 入库,使用 updateOrInsert 来保持 Email 唯一
        DB::table('password_resets')->updateOrInsert(['email' => $email], [
            'email' => $email,
            'token' => Hash::make($token),
            'created_at' => new Carbon,
        ]);

        // 6. 将 Token 链接发送给用户
        Mail::send('emails.reset_link', compact('token'), function ($message) use ($email) {
            $message->to($email)->subject("忘记密码");
        });

        session()->flash('success', '重置邮件发送成功,请查收');
        return redirect()->back();
    }
}

请仔细阅读代码中的注释。
需要注意的是,我们发送给用户的链接里的 Token 与存放在数据库里的 token 并非同一个值。这么做是为了增加安全的门槛。
接下来创建 emails.reset_link 模板:

resources/views/emails/reset_link.blade.php





<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>找回密码</title>
</head>
<body>
  <h1>您正在尝试找回密码</h1>

  <p>
    请点击以下链接进入下一步操作:
    <a href="{{ route('password.reset', $token) }}">
      {{ route('password.reset', $token) }}
    </a>
  </p>

  <p>
    如果这不是您本人的操作,请忽略此邮件。
  </p>
</body>
</html>

测试一下#

重新访问忘记密码页面 weibo.test/password/reset ,并填入正确的用户 Email 来找回密码:

 

Git 代码版本控制#

接着让我们将本次更改纳入版本控制中:
$ git add -A
$ git commit -m "发送找回密码链接"

 

重置密码
重温下相关的两个控制器方法:

showResetForm —— 显示更新密码的表单,隐藏 token 到表单数据 reset —— 对提交过来的 token 和 email 数据进行配对,正确的话更新密码
控制器方法#

上节我们成功提交邮箱,会发送带验证信息的链接到用户的邮箱中。
打开 Log 文件,可见类似的:
storage/logs/laravel.log

提示找不到控制器方法,接下来创建:

app/Http/Controllers/PasswordController.php





.
.
.    

    public function showResetForm(Request $request)
    {
        $token = $request->route()->parameter('token');
        return view('auth.passwords.reset', compact('token'));
    }
}

接下来创建 reset.blade.php 视图:

resources/views/auth/passwords/reset.blade.php





@extends('layouts.default')
@section('title', '更新密码')

@section('content')
<div class="offset-md-1 col-md-10">
  <div class="card">
    <div class="card-header">
        <h5>更新密码</h5>
    </div>

    <div class="card-body">
      <form method="POST" action="{{ route('password.update') }}">
        @csrf

        <input type="hidden" name="token" value="{{ $token }}">

        <div class="form-group row">
          <label for="email" class="col-md-4 col-form-label text-md-right">Email 地址</label>

          <div class="col-md-6">
            <input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ $email ?? old('email') }}" required autofocus>

            @if ($errors->has('email'))
            <span class="invalid-feedback" role="alert">
              <strong>{{ $errors->first('email') }}</strong>
            </span>
            @endif
          </div>
        </div>

        <div class="form-group row">
          <label for="password" class="col-md-4 col-form-label text-md-right">密码</label>

          <div class="col-md-6">
            <input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required>

            @if ($errors->has('password'))
            <span class="invalid-feedback" role="alert">
              <strong>{{ $errors->first('password') }}</strong>
            </span>
            @endif
          </div>
        </div>

        <div class="form-group row">
          <label for="password-confirm" class="col-md-4 col-form-label text-md-right">确认密码</label>

          <div class="col-md-6">
            <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required>
          </div>
        </div>

        <div class="form-group row mb-0">
          <div class="col-md-6 offset-md-4">
            <button type="submit" class="btn btn-primary">
              重置密码
            </button>
          </div>
        </div>
      </form>
    </div>
  </div>
</div>
@endsection

我们在用户进行表单提交时,会将密码重置的令牌信息通过隐藏输入框一同提交给密码控制器的 getReset 进行处理。

<input type="hidden" name="token" value="{{ $token }}">

重置密码#

接下来是处理重置密码的控制器方法:

app/Http/Controllers/PasswordController.php





.
.
.
    public function reset(Request $request)
    {
        // 1. 验证数据是否合规
        $request->validate([
            'token' => 'required',
            'email' => 'required|email',
            'password' => 'required|confirmed|min:8',
        ]);
        $email = $request->email;
        $token = $request->token;
        // 找回密码链接的有效时间
        $expires = 60 * 10;

        // 2. 获取对应用户
        $user = User::where("email", $email)->first();

        // 3. 如果不存在
        if (is_null($user)) {
            session()->flash('danger', '邮箱未注册');
            return redirect()->back()->withInput();
        }

        // 4. 读取重置的记录
        $record = (array) DB::table('password_resets')->where('email', $email)->first();

        // 5. 记录存在
        if ($record) {
            // 5.1. 检查是否过期
            if (Carbon::parse($record['created_at'])->addSeconds($expires)->isPast()) {
                session()->flash('danger', '链接已过期,请重新尝试');
                return redirect()->back();
            }

            // 5.2. 检查是否正确
            if ( ! Hash::check($token, $record['token'])) {
                session()->flash('danger', '令牌错误');
                return redirect()->back();
            }

            // 5.3. 一切正常,更新用户密码
            $user->update(['password' => bcrypt($request->password)]);

            // 5.4. 提示用户更新成功
            session()->flash('success', '密码重置成功,请使用新密码登录');
            return redirect()->route('login');
        }

        // 6. 记录不存在
        session()->flash('danger', '未找到重置记录');
        return redirect()->back();
    }
}

至此,整个用户密码重设功能便完成了。
Git 代码版本控制#

接着让我们将本次更改纳入版本控制中:
$ git add -A
$ git commit -m "重置密码"

 

限流是在一定时间内,限制用户对应用某个链接进行访问的次数。
一般来讲,服务器限流会出于以下两个目的:

安全 —— 例如登录表单限制访问次数以此来防止暴力破解用户密码;资源控制 —— 例如找回密码页面,会有类似数据库查询、发送邮件等比较消耗资源的操作,限流可以对资源浪费进行有效控制。
本节中,我们将对以下路由进行限流,对应规则如下:

注册 —— 一个小时内只能提交 10 次请求;登录 —— 10 分钟内只能尝试 10 次发送密码重置邮件 —— 10 分钟内只能尝试 3 次
限流功能#

Laravel 中内置了限流的中间件,见:

app/Http/Kernel.php




.
.
.
    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    ];
}

以上 throttle 就是限流的中间件。
我们先来测试如何使用,打开忘记密码的控制器:

app/Http/Controllers/PasswordController.php





.
.
.
class PasswordController extends Controller
{
    public function __construct()
    {
        $this->middleware('throttle:2,1', [
            'only' => ['showLinkRequestForm']
        ]);
    }
.
.
.

以上针对控制器方法 showLinkRequestForm() 做了限流,一分钟内只能允许访问两次。
打开对应的链接 weibo.test/password/reset ,连续刷新三次(超过两次)

就是超过限流后用户会看见的页面。
限流密码重置邮件#

发送密码重置邮件,限流规则为 —— 10 分钟内只能尝试 3 次:

app/Http/Controllers/PasswordController.php





.
.
.
class PasswordController extends Controller
{
    public function __construct()
    {
        $this->middleware('throttle:3,10', [
            'only' => ['sendResetLinkEmail']
        ]);
    }
.
.
.

登录限流#

规则是 10 分钟内只能尝试 10 次:

规则是 10 分钟内只能尝试 10 次:





.
.
.
class SessionsController extends Controller
{
    public function __construct()
    {
        $this->middleware('guest', [
            'only' => ['create']
        ]);

        // 限流 10 分钟十次
        $this->middleware('throttle:10,10', [
            'only' => ['store']
        ]);
    }
.
.
.

注册限流#

规则是一个小时内只能提交 10 次请求:

app/Http/Controllers/UsersController.php





.
.
.
class UsersController extends Controller
{
    public function __construct()
    {
        .
        .
        .

        // 限流 一个小时内只能提交 10 次请求;
        $this->middleware('throttle:10,60', [
            'only' => ['store']
        ]);
    }
.
.
.

代码版本#

开始下一节之前,我们先来为代码做下版本标记:
$ git add .
$ git commit -m "访问限流"

 

暂时未提供生产环境下的邮件发送

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值