---
# System prepended metadata

title: 社群登入串接
tags: [laravel]

---

---
tags: laravel
---
# 社群登入串接

![](https://i.imgur.com/1gSIqz1.png)


使用Laravel官方所提供的Socialite套件來實作社群登入功能

[Laravel Socialite 官網說明](https://laravel.com/docs/7.x/socialite)

#### 套件安裝

在Terminal輸入以下指令：composer require laravel/socialite 

#### 平台支持

目前支持所有主流社群平台，如下:Facebook.Google.GitHub.Bitbucket.Twitter.LinkedIn.GitLab

## 串接流程

#### Step 1.為OAuth服務加入證書帳密和回呼網址，設定於config/services.php

程式碼
```
'facebook' => [
    'client_id' => env('FACEBOOK_ID'),
    'client_secret' => env('FACEBOOK_SECRET'),
    'redirect' => env('FACEBOOK_URL'),
],
'google' => [
    'client_id' => env('GOOGLE_ID'),
    'client_secret' => env('GOOGLE_SECRET'),
    'redirect' => env('GOOGLE_URL'),
],
```

#### Step 2.加入處理社群登入的Action方法

在App\Http\Controllers\Auth\LoginController.php實作以下函式，記得要導入Socialite.Auth.User這三個類別

```
//轉址到社群平台的登入頁面
public function redirectToProvider($provider){
    return Socialite::driver($provider)->redirect();
}

//交由社群平台去呼叫的Call back function
public function handleProviderCallback($provider){
    //透過供應器來取得用戶
    $user = Socialite::driver($provider)->user();
    //透過用戶和供應器名稱來尋找或建立用戶
    $authUser = $this->findOrCreateUser($user,$provider);
    //進行登入並開啟記得我
    Auth::login($authUser,true);

    return redirect($this->redirectTo);
}
    
//假如通過登入提供者驗證後發現使用者已經註冊過，就取得該使用者資料，否則就自動進行簡易註冊動作
public function findOrCreateUser($user,$provider){
    $authUser = User::where('provider_id',$user->id)->first();
    if(!$authUser){
        //可能已經用其他管道註冊過
        $authUser = User::where('email',$user->email)->first();
        if($authUser){
            $authUser->provider = $provider;
            $authUser->provider_id = $user->id;
            $authUser->save();
        }
    }

    if($authUser){
        return $authUser;
    }else{
        $data = [
            'name' => $user->name,
            'email' => $user->email,
            'avatar' => $user->getAvatar(),
            'provider' => $provider,
            $authUser = User::where('provider_id',$user->id)->first()];
        return User::create($data);
    }
}
```

#### Step 3.加入社群登入路由

編輯routes/web.php，加入以下規則

```
\\routes\web.php

Route::get('login/{provider}', 'Auth\LoginController@redirectToProvider');
Route::get('login/{provider}/callback', 'Auth\LoginController@handleProviderCallback');
```

#### Step 4.在登入視圖加入社群登入按鈕

編輯登入頁面，如login.blade.php，加入以下連結

 ```
<a href="{{ url('login/facebook') }}">臉書登入</a>
 <a href="{{ url('login/google') }}">Google+登入</a>
```

#### Step 5.變更users表格

新增 migration檔案AlterSocialiteUsersTable，編輯完執行migrate

```
public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('provider',30)->nullable();
        $table->string('provider_id',100)->nullable();
        $table->string('password')->nullable()->change();
    });
}

public function down()
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropColumn('provider');
        $table->dropColumn('provider_id');
        $table->string('password')->change();
    });
}
```

==記得編輯\\App\\User.php的$fillable白名單屬性，加入provider和provider_id這兩個欄位，否則會無法寫入==

#### Step 6.申請社群平台的API OAuth金鑰

Google: [https://console.developers.google.com/apis](https://console.developers.google.com/apis)
Facebook: [https://developers.facebook.com/apps/](https://developers.facebook.com/apps/)

#### Step 7.將帳密寫進.env檔案裏頭

```
\\.env

FACEBOOK_ID= 臉書金鑰ID
FACEBOOK_SECRET= 臉書金鑰密碼
FACEBOOK_URL={應用網址}/login/Facebook/callback 
GOOGLE_ID= Google金鑰ID
GOOGLE_SECRET= Google金鑰密碼
GOOGLE_URL= {應用網址}/login/google/callback 
```

### API申請

#### 臉書API

網址：https://developers.facebook.com/apps/

Step 1.新增應用程式

![](https://i.imgur.com/qiY9TXV.png)

Step 2.設定>基本資料

應用程式編號為ID，應用程式密鑰為SECRET

![](https://i.imgur.com/fUgcAl5.png)

設定應用程式網域.隱私政策網域(頁面範例如下例).網站網址

Step 3.將應用程式啟用

---

### Policy頁面HTML範例

```
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>隱私權政策頁面</title>
</head>
<body>
    <div class="clear"></div>
    <div class="container clearfix">
        <h1 class="text-center">隱私權政策</h1>
        <p>&emsp;&emsp;非常歡迎您光臨XXX（以下簡稱本網站），為了讓您能夠安心使用本網站的各項服務與資訊，特此向您說明本網站的隱私權保護政策，以保障您的權益，請您詳閱下列內容：
        </p>

        <h3>一、隱私權保護政策的適用範圍</h3>

        <p>&emsp;&emsp;隱私權保護政策內容，包括本網站如何處理在您使用網站服務時收集到的個人識別資料。隱私權保護政策不適用於本網站以外的相關連結網站，也不適用於非本網站所委託或參與管理的人員。</p>

        <h3>二、個人資料的蒐集、處理及利用方式</h3>


        <p>&emsp;&emsp;當您造訪本網站或使用本網站所提供之功能服務時，我們將視該服務功能性質，請您提供必要的個人資料，並在該特定目的範圍內處理及利用您的個人資料；非經您書面同意，本網站不會將個人資料用於其他用途。
        </p>
        <p>&emsp;&emsp;本網站在您使用服務信箱、問卷調查等互動性功能時，會保留您所提供的姓名、電子郵件地址、聯絡方式及使用時間等。於一般瀏覽時，伺服器會自行記錄相關行徑，包括您使用連線設備的IP位址、使用時間、使用的瀏覽器、瀏覽及點選資料記錄等，做為我們增進網站服務的參考依據，此記錄為內部應用，決不對外公佈。
            為提供精確的服務，我們會將收集的問卷調查內容進行統計與分析，分析結果之統計數據或說明文字呈現，除供內部研究外，我們會視需要公佈統計數據及說明文字，但不涉及特定個人之資料。</p>


        <h3>三、資料之保護</h3>

        <p>&emsp;&emsp;本網站主機均設有防火牆、防毒系統等相關的各項資訊安全設備及必要的安全防護措施，加以保護網站及您的個人資料採用嚴格的保護措施，只由經過授權的人員才能接觸您的個人資料，相關處理人員皆簽有保密合約，如有違反保密義務者，將會受到相關的法律處分。
            如因業務需要有必要委託其他單位提供服務時，本網站亦會嚴格要求其遵守保密義務，並且採取必要檢查程序以確定其將確實遵守。</p>

        <h3>四、網站對外的相關連結</h3>

        <p>&emsp;&emsp;本網站的網頁提供其他網站的網路連結，您也可經由本網站所提供的連結，點選進入其他網站。但該連結網站不適用本網站的隱私權保護政策，您必須參考該連結網站中的隱私權保護政策。</p>

        <h3>五、與第三人共用個人資料之政策</h3>

        <p>&emsp;&emsp;本網站絕不會提供、交換、出租或出售任何您的個人資料給其他個人、團體、私人企業或公務機關，但有法律依據或合約義務者，不在此限。</p>

        <p>前項但書之情形包括不限於：</p>

        <ul>
            <li>經由您書面同意。</li>
            <li>法律明文規定。</li>
            <li>為免除您生命、身體、自由或財產上之危險。</li>
            <li>與公務機關或學術研究機構合作，基於公共利益為統計或學術研究而有必要，且資料經過提供者處理或蒐集著依其揭露方式無從識別特定之當事人。</li>
            <li>當您在網站的行為，違反服務條款或可能損害或妨礙網站與其他使用者權益或導致任何人遭受損害時，經網站管理單位研析揭露您的個人資料是為了辨識、聯絡或採取法律行動所必要者。</li>
            <li>有利於您的權益。</li>
            <li>本網站委託廠商協助蒐集、處理或利用您的個人資料時，將對委外廠商或個人善盡監督管理之責。</li>
        </ul>

        <h3>六、Cookie之使用</h3>

        <p>&emsp;&emsp;為了提供您最佳的服務，本網站會在您的電腦中放置並取用我們的Cookie，若您不願接受Cookie的寫入，您可在您使用的瀏覽器功能項中設定隱私權等級為高，即可拒絕Cookie的寫入，但可能會導至網站某些功能無法正常執行
            。</p>

        <h3>七、隱私權保護政策之修正</h3>

        <p>&emsp;&emsp;本網站隱私權保護政策將因應需求隨時進行修正，修正後的條款將刊登於網站上。</p>
    </div>
    </div>
</body>
</html>

```