22
17

More than 5 years have passed since last update.

Laravel5.3でソーシャル連携ウェブサービスの土台を作る(Socialite/Twitter)

Last updated at Posted at 2016-12-04

これ、「Laravel5.2でソーシャル連携ウェブサービスの土台を作る。 」のLaravel5.3バージョンです。

5.3ではroutingの設定がフォルダとmiddleware別のファイルに別れたりしました。
laravel/socialiteも前は生のまんま使ったのですが、今回は、socialiteproviders/twitterという、socialite用のプロバイダのライブラリを使いました。
5.2ではAuthControllerとしてログインや会員周りが一つのコントローラーになっていましたが、5.3では4つのControllerに分割されています。(ForgotPasswordController.php、LoginController.php、RegisterController.php、ResetPasswordController.php)

ちょいちょい変わってそうなので、ひととおり実装しました。

プロジェクトの初期化

  • 最新のLaravelを落とすと5.3になります。(2017/8/23現在5.4が最新です)
composer create-project --prefer-dist laravel/laravel アプリ名

Homesteadで仮想環境作る

  • laravel用の仮想環境のライブラリをrequireする
cd アプリ名
composer require laravel/homestead --dev
  • 仮想環境用の設定を自動作成
php vendor/bin/homestead make
  • IPとhost名の設定、Hostsの設定

プロジェクト直下にHomestead.yamlってファイルができるので、IPの設定を見る。

Homestead.yaml
ip: "192.168.10.10"
memory: 2048
cpus: 1
hostname: アプリのドメイン名
name: アプリ名

hostnameをアプリのドメイン名を好きな名前に変えて、/etc/hostsに レコードをたす。

192.168.10.10 アプリのドメイン名
  • 仮想環境起動
vagrant up

これで待っているとboxのDownloadと仮想マシンの初期化がされます。
Laravelのhomesteadは、ここにホスティングされてます。(一応)
https://atlas.hashicorp.com/laravel/boxes/homestead

  • なんかvagrant sshができなかったので、いろいろ調べてたら、Ubuntuの問題っぽかった。これ↓したらなおった。
config.vm.provider :virtualbox do |vb|
    vb.customize ["modifyvm", :id, "--cableconnected1", "on"]
end

参考:Vagrant で bento/ubuntu-16.04 を vagrant up すると Connection timeout になってしまう

ログイン機能を作る

  • 最初に.envにアプリのURLを書いておく
APP_URL=https://アプリのドメイン名

  • ユーザー名などで絵文字とか入る可能性があるので、dbのcharsetをutf8mb4に変えておく。
62
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
  • vagrantに入る
vagrant ssh
  • アプリのディレクトリにcdして、Laravelに最初から用意されている認証用のmigrationとルーティングの設定を実行する
cd アプリ名 
php artisan make:auth
php artisan migrate

出来上がったものを確認して見る

実行するとルーティングができてるので、みて見ると、Controllerとか出来上がってる。

php artisan route:list
Domain Method URI Name Action Middleware
GET/HEAD / Closure web
GET/HEAD api/user Closure api,auth:api
GET/HEAD home App\Http\Controllers\HomeController@index web,auth
GET/HEAD login login App\Http\Controllers\Auth\LoginController@showLoginForm web,guest
POST login App\Http\Controllers\Auth\LoginController@login web,guest
POST logout logout App\Http\Controllers\Auth\LoginController@logout web
POST password/email App\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail web,guest
GET/HEAD password/reset App\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm web,guest
POST password/reset App\Http\Controllers\Auth\ResetPasswordController@reset web,guest
GET/HEAD password/reset/{token} App\Http\Controllers\Auth\ResetPasswordController@showResetForm web,guest
GET/HEAD register register App\Http\Controllers\Auth\RegisterController@showRegistrationForm web,guest
POST register App\Http\Controllers\Auth\RegisterController@register web,guest

ざっと動いてるか動作確認

この状態で、アクセスhttp://アプリ名/して見ると、ログインリンクとかついてる。作りやすいな〜。もうソーシャル連携とかいいのでは〜って気分になってくる。

トップページ

スクリーンショット 2016-11-28 2.59.51.png

会員登録画面

スクリーンショット 2016-11-28 3.06.05.png

ログイン画面

スクリーンショット 2016-11-28 3.05.51.png

パスワードリセット

スクリーンショット 2016-11-28 3.18.07.png

ソーシャル連携を作る

laravelの公式ライブラリのSocialiteでソーシャル連携を作る
https://github.com/laravel/socialite

Twitter経由のログインとユーザー登録

ユーザー登録はメアドで登録ってのも全然ありだが、最初はtwitter経由で登録してあとからTwitter連携外すとか、よくやると思うので、そのようにする。

このサイトの言うこと聞いとけば大体できそう。

Using Twitter Authentication For Login in Laravel 5

socialiteのインストール

composer require laravel/socialite

ライブラリの読み込み

config/app.php

'providers' => [
    // Other service providers...

    Laravel\Socialite\SocialiteServiceProvider::class,
],
config/app.php

'aliases' => [
    snip...
    // Other service providers...

    'Socialite' => Laravel\Socialite\Facades\Socialite::class,
],

twitter用のproviderインストール

参考:Socialite Providers

composer require socialiteproviders/twitter

ライブラリの読み込み

config/app.php

'providers' => [
    // Other service providers...
    Laravel\Socialite\SocialiteServiceProvider::class,
    \SocialiteProviders\Manager\ServiceProvider::class, // ←これ追加
],

イベントリスナーにとうろく

app/Providers/EventServiceProvider.php
    protected $listen = [
//        'App\Events\SomeEvent' => [
//            'App\Listeners\EventListener',
//        ],
        \SocialiteProviders\Manager\SocialiteWasCalled::class => [
            // add your listeners (aka providers) here
            'SocialiteProviders\Twitter\TwitterExtendSocialite@handle',
        ],
    ];

最初から書いてある'App\Events\SomeEvent'...のところは、よくわからないけどコメントアウトした。

oauth APIのキーを.envに書く。

oauth APIのキーとかはここからとる。
https://apps.twitter.com/

TWITTER_CLIENT_ID=XXXXXXX
TWITTER_CLIENT_SECRET=XXXXXXXXXXXXXXXXXXXXX

configのservice.phpに設定を追加

config/service.php
    'twitter' => [
        'client_id' => env('TWITTER_CLIENT_ID'),
        'client_secret' => env('TWITTER_CLIENT_SECRET'),
        'redirect' => env('URL') . '/twitter/login'
    ],

twitterのSocialiteFactoryが動くようにする。

AppServiceProvider.phpに起動function作成

app/Providers/AppServiceProvider.php

    private function bootTwitterSocialite()
    {
        $twitter = $this->app->make('Laravel\Socialite\Contracts\Factory');
        $twitter->extend(
            'spotify',
            function ($app) use ($twitter) {
                $config = $app['config']['services.twitter'];
                return $twitter->buildProvider(TwitterProvider::class, $config);
            }
        );
    }

twitter用のControllerを作る。

app/Http/Controllers/Auth/TwitterAuthController.php
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Laravel\Socialite\Facades\Socialite;

class TwitterAuthController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest', ['except' => 'logout']);
    }

    public function redirectToProvider()
    {
        return Socialite::with('twitter')->redirect();
    }

    public function handleProviderCallback()
    {
        $user = Socialite::with('twitter')->user();
        // $user->token;
        // 初めて来た人はユーザー登録、すでにIDがあるひとは、とってくる
        $authUser = $this->findOrCreateUser($user);
        // その後ログイン
        Auth::login($authUser, true);
        return redirect('home');
    }

    /**
     * Return user if exists; create and return if doesn't
     *
     * @param $twitterUser
     * @return User
     */
    private function findOrCreateUser($twitterUser)
    {
        $authUser = User::where('twitter_id', $twitterUser->id)->first();

        if ($authUser){
            return $authUser;
        }

        // ここは後で書き直します。
    }
}

ツイッター経由のloginとcallbackのルーティング追加

routes/web.php
Route::get('twitter/login', 'Auth\TwitterAuthController@redirectToProvider');
Route::get('twitter/callback', 'Auth\TwitterAuthController@handleProviderCallback');

ツイッターのアカウント情報を保存するテーブルを作る

ログイン後にaccess_tokenとsecret、ユーザーIDなどを入れるテーブルを作る。

php artisan make:migration create_twitter_users_table

マイグレーションファイルの編集

database/migrations/日付_create_twitter_users_table.php
<?php

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

class CreateTwitterUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('twitter_users', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id');
            $table->bigInteger('twitter_user_id');
            $table->string('email')->nullable();
            $table->string('name');
            $table->string('nickname');
            $table->string('avatar',1024);
            $table->string('token',1024);
            $table->string('token_secret',1024);
            $table->timestamps();
        });
    }

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

カラム名がこの感じになってるのは、socialiteprovidersのなかみるとわかるけど、
vendor/socialiteproviders/twitter/src/Server.php
いろんなプロバイダでフィールドが違うのを共通化してる。

もしかして、provider_accounts ってTableつくればよかっただけかも、、。provider_nameとか入れて。

php artisan migrate

modelにrelationを入れておく

app/User.php
    public function twitter_users()
    {
        return $this->hasMany('App\TwitterUser');
    }
app/TwitterUser.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class TwitterUser extends Model
{

    /**
     * Get the user that owns the twitter user.
     */
    public function user()
    {
        return $this->belongsTo('App\User');
    }

}

保存するフィールドのmassassignmentを設定しておく。

app/TwitterUser.php
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['twitter_user_id','email','name',
        'nickname','avatar','token','token_secret',];

準備完了なので、ControllerのfindOrCreateUserを書き直します。

こんな感じ。

app/Http/Controllers/Auth/TwitterAuthController.php

    /**
     * Return user if exists; create and return if doesn't
     *
     * @param $twitterUser
     * @return User
     */
    private function findOrCreateUser($twitterUser)
    {
        $twitterUser = TwitterUser::where('twitter_user_id', $twitter_account->id)->first();
        if($twitterUser) {
            $authUser = $twitterUser->user;
            if ($authUser){
                return $authUser;
            }
            throw new \Exception("twitter userがいるけどuserテーブルに紐づいていない");
        }

        $user = User::create([
            'name' => $twitter_account->name,
            'email' => str_random(16)."@example.com", //仮で入れる
            'password' => bcrypt(str_random(16)), //仮で入れる
        ]);

        $twitter_user = new TwitterUser([
            'twitter_user_id' => $twitter_account->id,
            'email' => $twitter_account->email,
            'name' => $twitter_account->name,
            'nickname' => $twitter_account->nickname,
            'avatar' => $twitter_account->avatar,
            'token' => $twitter_account->token,
            'token_secret' => $twitter_account->tokenSecret,
        ]);

        $user->twitter_users()->save($twitter_user);
        return $user;
    }
}

これで、https://あぷりのURL/twitter/loginにアクセスすると、新規ユーザーを作成し、ログインまたは既存ユーザーでtwitteridがあったら普通にログイン。
ができるようになります。

twitter経由のログインの場合、メールアドレスとパスワードを仮で設定してあるので、メアドからログインできないようになっていますので適宜ユーザビリティ〜あげちゃってください。

ソースコードはgithubにアップしました。

https://github.com/maimai-swap/laravel5.3-twitter-oauth
ダウンロードしてそのまま使えると思います。

22
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
17