自動化無しに生活無し

WEBとかAIとかLinux関係をひたすら書く備忘録系ブログ

【Laravel】IPアドレスを取得して、DBへ記録する【犯罪・不正利用の抑止、荒らし対策などに】

thumbnail

クライアントのIPアドレスを記録できれば、認証が無くても犯罪行為の抑止につながるし、事案が発生してもすぐに対応できるだろう。

本記事ではLaravelにクライアントのIPアドレスを記録する方法を解説する。

コードは『初心者でもlaravelを使い、45分でCRUD簡易掲示板を作る【Restful対応】』から流用している。

IPアドレスのカラムを追加(モデル編集とマイグレーションファイル作成)

まずマイグレーションファイルを追加する。

php artisan make:migration add_ipaddress --table=topics

生成されるマイグレーションファイル(database/migrations/XXXX_XX_XX_XXXXXX_add_ipaddress.php)に下記を記入。

<?php

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

class AddIpaddress extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('topics', function (Blueprint $table) {
            $table->ipAddress("ip")->default("0.0.0.0");
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('topics', function (Blueprint $table) {
            //
        });
    }
}

IPアドレスを記録するので、ipAddress()を指定。後から追加するカラムなので、デフォルトを指定しておく。

これをマイグレーションする。

php artisan migrate 

モデル(/app/Topic.php)も書き換える。これを忘れてしまうとIPアドレスは記録されず、常にバリデーションエラーになってしまう。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Topic extends Model
{
    protected $fillable = [
        "name","content","ip"
    ];
}

これでDB側は準備OK、続いて投稿する時にIPアドレスをセットする機能部を書く。

Requestで事前にIPアドレスをセットした上でバリデーションをする

投稿されたコメントをバリデーションする前に、サーバーが取得したクライアントのIPアドレスをセットし、コメントと一緒にバリデーションさせる必要がある。

そこで、出てくるのが、RequestprepareForValidation()バリデーションをする前に、指定したクライアントから送られたデータを書き換えたり、追加したりする事ができる。

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class CreateTopicRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'name'      => 'required|max:15',
            'content'   => 'required|max:2000',
            'ip'        => 'required',
        ];
    }

    public function messages() {
        return [
            'name.required'     => '名前を入力してください',
            'name.max'          => '名前は15文字でお願いします。',
            'content.required'  => 'コメントを入力してください',
            'content.max'       => 'コメントは2000文字でお願いします。',
        ];
    }



    public function getIp(){
        foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key){
            if (array_key_exists($key, $_SERVER) === true){
                foreach (explode(',', $_SERVER[$key]) as $ip){
                    $ip = trim($ip); // just to be safe
                    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){
                        return $ip;
                    }
                }
            }
        }
        return request()->ip(); // it will return server ip when no client ip found
    }

    #IPアドレスを入れる
    protected function prepareForValidation()
    {
        $this->merge([
            "ip" => $this->getIp(),
        ]);
    }



}

IPアドレスの取得に関しては、Stackoverflowからそのままコードを流用させていただいた。Laravel 5.x系以降であれば問題なく動作する模様。

デプロイ先のサーバーがプロキシサーバーなどを使っていたとしても、クライアントのIPアドレスを取得する事ができるので、どんな環境であってもこれでOK。

後は、取得したIPアドレスをprepareForValidation()でバリデーション前にセットし、バリデーションさせ、コントローラで保存する。

動かすとこうなる

ビューで表示するように仕立てておけば、こんなふうになる。

黒塗りしているが、確認くんで出てきたIPアドレスと同じものが表示されている。成功だ。

Herokuにデプロイしたが、これで問題なくIPアドレスが取得できる。

結論

このIPアドレスの記録と表示によって、犯罪行為や迷惑行為の抑止につながるだろう。そもそも事案が起きにくくなるので、法的手続きなどの管理の手間の削減も期待できる。

バリデーション前に何らかのデータをセットする事はよくあることなので、覚えておくと何かと役に立つだろう。

参照元:https://stackoverflow.com/questions/33268683/how-to-get-client-ip-address-in-laravel-5

スポンサーリンク

シェアボタン

Twitter LINEで送る Facebook はてなブログ