イタズラ投稿者のIPアドレスを、簡単に取得する方法(Laravel)


はじめに

私は未経験からプログラミングを学習して、Laravel等の技術を使用した
自作アプリをポートフォリオとして一般公開していました。

すると幸いにも、多くの方に実際にアプリを利用してもらうことができたものの、
やはりイタズラ投稿や連続投稿等、迷惑な投稿もされるようになりました。

→そんな体験の一部をまとめた記事:
ポートフォリオのアプリを公開したらイタズラされまくった話
(1,000LGTM突破ありがとうございます🙇‍♂️)

そこで、次の対策にも繋げるために、アプリに「投稿者のIPアドレスを取得する機能」を追加することにしました。
調べてみると、Laravelで非常に簡単に実現できることがわかったので、今回はその方法をご紹介いたします。

前提条件

私は、以下の環境等で実現しました。

  • Laravel 6.18.36
  • 既に投稿機能が実装されている

実際に、イタズラ投稿者のIPアドレスを取得してみた

まず初めに、デモンストレーションです。
私が公開しているアプリへの、イタズラ投稿者のIPアドレスを取得してみます。
では、どんなイタズラ投稿があるというと・・

はい!下ネタ全開のイタズラ投稿ですね。笑
このような投稿が、日々ちょくちょく投稿されていました。^^;

ということで、IPアドレスを取得する処理を実装済みなので、
早速IPアドレスが取れたか確認してみます。

※ゲストユーザーというのは、パスワード等を入力しなくても、誰でも簡単にログイン可能なユーザーのことです。

DBの中身を確認してみた

ということで、DBを覗いてみました。

おぉ。。ip_addressカラムにしっかりと、下ネタ投稿者のIPアドレスが取得できていました。
流石にIPアドレスをこのまま載せるのは避けますが、赤色
伏せてる部分が、同一IPアドレスでした。
一方青色で伏せている部分は、それ以外の複数のIPアドレスです。

三日間の投稿の、IPアドレスを調べてみた

2020年1月21日〜23日の投稿を確認してみました。

  • 赤色で伏せてる部分が、全て同一IPアドレスでした。
     1月22日から23日にかけて、下ネタを投稿したり、「おはようございます!」と連続投稿していたことがわかります。

  • 青色で伏せている部分は、それ以外の複数のIPアドレスです。

  • ip_addressカラムの中身が「NULL」となっているものは、IPアドレスを取得する処理が未実装だった頃の投稿です。IPアドレスが取得できていません。

こうして見てみると、下ネタ投稿ユーザーが
二日間に渡って投稿してきていることがわかります。
同一人物だったんか・・・というのがわかるとちょっと面白いですよね。

それでは、いよいよIPアドレス取得機能の実装方法についてご紹介していきます。

IPアドレスの取得方法

これが、とても簡単です。
Requestクラスの、ip()メソッドを利用するだけです。
ユーザーがアプリ上で投稿を行った際に、Controller側でユーザーのIPアドレスを
$request->ip() といった形で扱うことができます。

例えば、投稿機能に関する処理をまとめたControllerである
ArticleController.phpに、
登録処理を定義したstore()メソッドがあるとします。
内容としては、ユーザーが投稿したメッセージを、そのままDBに保存するだけのシンプルな処理です。

ArticleController.php
public function store(ArticleRequest $request, Article $article)
{
    // 投稿をDBに保存
    $user = $request->user();
    $article = $user
                ->articles()
                ->create($request->validated()); // バリデーション済みの値だけ保存
    return redirect()->route('articles.index');
}

※ちなみに、上記のコードでは、$request->validated()で、バリデーション済みの値のみを取得しています。
こちらの方が、$request->all()で値を取得するより安全です。

それでは、storeメソッドの処理の一番最初に、試しにdd( )メソッド$request->ip()を取ってみましょう。
この状態で、アプリから自分で適当な投稿をしてみると、ちゃんと自分のIPアドレスが取得できていることが確認できると思います。

ArticleController.php
public function store(ArticleRequest $request, Article $article)
{
    dd($request->ip());  // 投稿者のIPアドレスが取得できているか確認

    // 投稿をDBに保存
    $user = $request->user();
    $article = $user
                ->articles()
                ->create($request->validated()); // バリデーション済みの値だけ保存
    return redirect()->route('articles.index');
}

たったこれだけでIPアドレスを取得できてしまうので、Laravelって本当に便利ですね。。

なお、本記事でご紹介する実装の主な手順としては、以下のようになっています。
(あまり難しくありません)

  1. DBのarticlesテーブルに、「ip_address」カラムを追加し、IPアドレスを保存できるようにする。
  2. 上記store()メソッドで、IPアドレスをDBに保存するようコードを編集
  3. fillableにコードを一行追加

※投稿に関する情報を保存するDBのテーブルを、articlesテーブルと定義する場合

IPアドレス取得機能の実装方法

DBのテーブルに、IPアドレス用のカラムを追加

本記事では、以下の前提で実装を進めていきます。

  • ユーザー投稿に関する情報を保存するテーブルを、articlesテーブルとする
  • IPアドレスを保存するカラムを、ip_addressカラムとする

まずカラム追加のマイグレーションファイルを作成します。
ターミナルから以下のコマンドを実行してください。

$ php artisan make:migration add_ip_address_to_articles_table --table=articles

新しいマイグレーションファイルが作成されるので、そちらを以下のように編集してください。

<?php

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

class AddIpAddressToArticlesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        // ここから追記 ーーーーーーーーーーーーーーーーー
        Schema::table('articles', function (Blueprint $table) {
            $table->ipAddress('ip_address')->nullable();
        });
        // 追記ここまで ーーーーーーーーーーーーーーーーー
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        // ここから追記 ーーーーーーーーーーーーーーーーー
        Schema::table('articles', function (Blueprint $table) {
            $table->dropColumn('ip_address');
        // 追記ここまで ーーーーーーーーーーーーーーーーー
        });
    }
}

新しく追加するip_addressカラムの
カラムタイプにはipAddressを指定しており、
またIPアドレスが取得できなかった際にエラーで落ちないようにnullableもかけています。

参考:Laravel 6.x データベース:マイグレーション

マイグレーションファイルの編集が完了したら、マイグレーションを実行します。

$ php artisan migrate

これでDBにip_addressカラムが追加されました。

Controller側に、IPアドレスを保存する処理を追加

先ほど例に出しました、ArtcleController.phpの一行に追記します。

ArticleController.php
public function store(ArticleRequest $request, Article $article)
{
    // 投稿をDBに保存
    $user = $request->user();
    $article = $user
                ->articles()
                ->create($request->validated() + ['ip_address' => $request->ip()]); // 取得したIPアドレスを保存するよう修正
    return redirect()->route('articles.index');
}

ここでは、DBへの保存処理を行うcreate()メソッドの引数を編集しています。
バリデーション済みの値である、
$request->validated()という連想配列に、更に1つ+ 演算子で連想配列の要素を追加しています。
追加された連想配列が、['ip_address' => $request->ip()]です。
'ip_address'というキーに、バリューとして取得したIPアドレス$request->ip()を対応させています。
(今回、取得したIPアドレスはバリデーションにはかけていません。)

fillableを追加

最後に、モデルのArticle.php$fillableに、一行追記します。
(以下のモデルは一例なので、みなさんの環境によって異なると思います。)

Article.php
<?php

namespace App\Models;

use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Article extends Model
{
    protected $fillable = [
        'body',
        'user_id',
        'ip_address', // `ip_address`を追加
    ];

// 〜〜〜〜〜〜〜〜〜 略 〜〜〜〜〜〜〜〜〜

}

以上で、IPアドレスを取得する機能の実装は完了です!
お疲れ様でした!
これで、アプリ上でユーザー投稿があった時に、そのユーザーのIPアドレスをDBに保存できるようになりました。

最後に

今回は、Laravelで簡単に投稿者のIPアドレスを取得する方法をご紹介しました。
IPアドレスを取得した先に繋げる迷惑投稿対策としては、

  • 特定のIPアドレスにアクセス制限をかける
  • 犯罪性の高い悪質な投稿に関しては、プロバイダーに問い合わせる等する

といったものが考えられると思います。

なお、IPアドレス取得機能を実装したアプリを公開する際には、プライバシーポリシー等を作成しておくことが望ましいです。
こちらのサイトで、コピペOKなプライバシーポリシーのテンプレートが公開されているので、ご自身のアプリ用に少し修正したものを作成しておきましょう!
【コピペOK】ブログのプライバシーポリシー書き方&設置方法を公開