# nuxtjs と codeigniter で jwt システム構築

laravel や lumen で api サーバー建てることが多く、今回バックエンドは codeigniter でやってみました。

構造

  • フロントエンド nuxt2.11
  • バックエンド codeigniter3.10

# codeigniter 側の設定

ユーザー認証でトークン発行して、その後トークンで認証とってデータやり取りする仕組み。バックとフロントが分離することで、サーバーサイドの仕事がシンプルになります。

# composer firebase php jwt 入れる

jwt 暗号化エンコードとデコード用に自前で作成することも一つの選択肢ですが、自前で作るより時間短縮できるし、バグ修正などの手間もなく、google 製で安心などのメリットがあって firebase のライブラリ使用

composer require firebase/php-jwt

使い方はシンプル

$jwt = JWT::encode($payload, $key);
$decoded = JWT::decode($jwt, $key, array('HS256'));

print_r($decoded);
参考:firebase/php-jwt (opens new window)

Config 設定変更

application/config/config.php

// composer autoload
$config['composer_autoload'] = APPPATH . '../vendor/autoload.php';

// jwt 用エンクリプトキー設定
$config['encryption_key'] = 'abc123';

# MY_Controller 作成

MY_Controller 作成してグローバル関数や設定します。

application/core/MY_Controller.php

<?php
class MY_Controller extends CI_Controller
{
    protected $post;

    public function __construct()
    {
        parent::__construct();

        // cors optionsリクエスト対策
        if ($this->input->method() == 'options') {
            return $this->json([]);
        }

        // json リクエスト array post 変換
        $this->post = $this->input->raw_input_stream ? json_decode($this->input->raw_input_stream) : null;

    }

    public function json(array $response, int $status = 200)
    {
        // json export
        $this->output
            ->set_status_header($status)
            ->set_header('Access-Control-Allow-Origin: http://localhost:3000')
            ->set_header('Access-Control-Allow-Headers: *')
            ->set_header('Access-Control-Request-Method: POST,GET')
            ->set_content_type('application/json', 'utf-8')
            ->set_output(json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES))
            ->_display();
        exit;
    }
}

Auth コントローラー

<?php
defined('BASEPATH') or exit('No direct script access allowed');
use \Firebase\JWT\JWT;

class Auth extends MY_Controller
{
    public function login()
    {

        if (!$this->post) {
            return $this->json(['result' => false]);
        }

        // テスト用トークン発行
        $token = JWT::encode($this->post, $this->config->item('encryption_key'));

        $response = ['result' => true, 'token' => $token];

        $this->json($response);
    }

    public function logout(){

    }

    public function user()
    {
        $token = $this->input->get_request_header('Authorization', true);

        // トークンでデータ返却
        $response = ["user" => ["username" => "asdf", "picture" => "https://github.com/nuxt.png", "level" => 2]];
        $this->json($response);
    }
}

# おまけ:codeigniter index.php 省略

index.php を省略するための htaccess 設定
public/.htaccess の設定

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /

    #Removes access to the system folder by users.
    #Additionally this will allow you to create a System.php controller,
    #previously this would not have been possible.
    #'system' can be replaced if you have renamed your system folder.
    RewriteCond %{REQUEST_URI} ^system.*
    RewriteRule ^(.*)$ /index.php?/$1 [L]

    #When your application folder isn't in the system folder
    #This snippet prevents user access to the application folder
    #Submitted by: Fabdrol
    #Rename 'application' to your applications folder name.
    RewriteCond %{REQUEST_URI} ^application.*
    RewriteRule ^(.*)$ /index.php?/$1 [L]

    #Checks to see if the user is attempting to access a valid file,
    #such as an image or css document, if this isn't true it sends the
    #request to index.php
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php?/$1 [L]
</IfModule>

<IfModule !mod_rewrite.c>
    # If we don't have mod_rewrite installed, all 404's
    # can be sent to index.php, and everything works as normal.
    # Submitted by: ElliotHaughin

    ErrorDocument 404 /index.php
</IfModule>

codeigniter のいいところはシンプルでわかりやすい、作業効率が上がるし、面倒な設定がない、ちょっとしたすぐに実現したいシステムならぴったり

# Nuxtjs 側 auth module 設定

nuxt の公式モジュール Auth Module @nuxtjs/auth を使います。@nuxtjs/auth は非常によくできている認証系モジュールです。このモジュール一つで通常のユーザー認証と google 認証 github facebook などはあっという間にできてしまうので、Auth Module 公式サイト (opens new window)確認するだけで使えます。

サポートしているプロバイダー

  • Auth0
  • Facebook
  • Github
  • Google
  • Laravel Passport

# ログイン画面

ユーザー登録のタイミングで google ログイン github ログインなどしてもらって本登録するシステムなので、ログイン画面はローカル認証のみ

<template>
  <b-card class="my-login">
    <b-alert v-if="error" show variant="danger">{{ error + '' }}</b-alert>
    <b-form-group label="Email" label-for="loginID" label-class="text-left">
      <b-form-input id="loginID" v-model="email" type="email" class="bg-danger" required />
    </b-form-group>
    <b-form-group label="Password" label-for="loginPW" label-class="text-left">
      <b-form-input id="loginPW" v-model="password" type="password" required />
    </b-form-group>
    <b-button
      variant="warning"
      :class="['d-block w-100 mt-5',{'animated shake':error}]"
      @click.prevent="login"
    >ログイン</b-button>

    <!-- パスワードを忘れた場合 -->

    <div class="mt-3 small a-divider-break"></div>
    <div class="my-2 small">
      新しいお客様ですか?
      <n-link to="/register">アカウント作成</n-link>
    </div>
    <!-- <div class="my-2 small">
          <n-link to="/register">パスワードを忘れた場合</n-link>
    </div>-->
  </b-card>
</template>

<script>
export default {
  data() {
    return {
      email: null,
      password: null,
      error: null
    };
  },
  methods: {
    async login() {
      this.error = null;
      return this.$auth
        .loginWith("local", {
          data: {
            email: this.email,
            password: this.password
          }
        })
        .catch(e => {
          this.error = e + "";
        });
    }
  }
};
</script>

<style lang="scss" scoped>
.my-login {
  max-width: 320px;
  width: 100%;
  position: fixed;
  left: 50%;
  transform: translate(-50%, -50%);
  bottom: 150px;
}
</style>

# nuxt.config.js 設定

  modules: [
    // Doc: https://bootstrap-vue.js.org
    "bootstrap-vue/nuxt",
    // Doc: https://axios.nuxtjs.org/usage
    "@nuxtjs/axios",
    "@nuxtjs/pwa",
    // Doc: https://github.com/nuxt-community/dotenv-module
    "@nuxtjs/dotenv",
    "@nuxtjs/auth"
  ],
  auth: {
    strategies: {
      local: {
        endpoints: {
          login: {
            url: process.env.API_URL + "/auth/login",
            method: "post",
            properryName: "token"
          },
          logout: {
            url: process.env.API_URL + "/auth/logout",
            method: "post"
          },
          user: {
            url: process.env.API_URL + "/auth/user",
            method: "get",
            propertyName: "user"
          }
        },
        tokenRequired: true,
        tokenName: "Authorization",
        tokenType: false, //Bearer
        sameSite: "None",
        Secure: true
      }
    }
  }

# auth module の使い方

自動的に auth という名前の middleware 作成されるので、該当ページに貼っておくと自動的リダイレクトしてくれます。
デフォルトの設定では、ログインページは/loginログイン後のリダイレクトページは/。トークン切れの場合自動的に/loginへリダイレクトされる仕組み。

ログインしたら返却されたデータは vuex store とクッキーに保存されます。

ログイン後使える vuex store $auth 情報

// Access using $auth
this.$auth.user;

// Access using vuex
this.$store.state.auth.user;

// Access using $auth
this.$auth.loggedIn;

// Access using vuex
this.$store.state.auth.loggedIn;

user はオブジェクト
loggedIn は boolean 型

複数のメソッド

loginWith(strategyName, ...args)

this.$auth
  .loginWith("local" /* .... */)
  .then(() => this.$toast.success("Logged In!"));

login(...args)

this.$auth.login(/* .... */).then(() => this.$toast.success("Logged In!"));

logout(...args)

await this.$auth.logout(/* .... */);

fetchUser()

await this.$auth.fetchUser();

hasScope(scopeName)

// Returns is a computed boolean
this.$auth.hasScope("admin");
2020-01-23
  • javascript
  • php

関連記事

Javascript 非同期処理 async と await のメモ
Laravel メンテナンスモード
Laravel でカテゴリー作成 テーブル構築と再帰クエリ
Laravel を API サーバーとしての初期設定
javascript  指定場所にスムーズにスクロールする方法
Nuxt.js と Ant Design Vue 2 テーマカスタマイズ
react 強制的にレンダリングする方法
Laravel リクエストログ出力
JavaScript ライブラリ aos.js 使ってスクロール連動アニメーション
Carbon で php date 日付の日数・月数差を計算
Laravel 429 Too Many Requests
Laravel Email バリデーションについて
Laravel Sanctum 使って API トークン JWT 認証と SPA 認証
Jsconfig と Tsconfig
Laravel logger でエラーログを chatwork に自動送信
php CSV データ取得は fgetcsv 使う
Laravel tinker 使って DB データベース接続とコマンド
Laravel Test についてのメモ
Laravel Log の基本設定&使い方
Exception: Class 'ZipArchive' not found
Cookie localStorage sessionStorage の違い
Javascript var let const 変数宣言の違い
Laravel Sail で Docker 環境構築
PHP 文字列長さ・文字列の幅を取得方法
Codeigniter 画像アップロードとリサイズ
Javascript 電話番号フォーマット
Laravel Lumen Faker 日本語設定
国際化 i18n と地域化 L10N
大きいファイルをスライス分割してアップロード
javascript 文字列と配列検索 indexOf findIndex find some includes 関数の違い
Javascript DataTables で excel 風 table 作る
javascript 配列 重複排除
laravel method の基本 get post put options
vuejs back to top button component 作成
bootstrap vuejs 使って generate する際に babel が icons ファイル max 500KB エラー
Laravel schedule 設定
Class 'Imagick' not found Error
Laravel eloquent model の規約
PHP mbconvertkana 全角半角英数カナ変換
Codeigniter APPPATH BASEPATH FCPATH 各種パスと URL 取得
Nuxtjs 動的なルーティング静的ページ自動生成
Laravel timestamp() auto update 有効化無効化
Lumen8 で JWT ユーザー認証
キーコード取得 & キーコード一覧
Laravel toSql パラメータ付きで出力
Lumen8 で API 開発
php Exception エラーキャッチでメール送信
Sweet Alert swal に複数 content
Smarty HTTP URL 取得できるサーバー関数
Laravel blade foreach loop と current url
laravel session を制する
moment.js 使って日本語曜日対応
PHP empty isset is_null の違い
PHP 8 リリース新機能と変更
javascript 開発で出会った TypeError
FlattenException deprecated
php.ini 初期設定のいろいろ
Laravel 5.1 から 8.1 にバージョンアップ
PHP 7.4 にアップグレードして使えなくなる機能
開発時によく使うゼロ埋めパディング作業まとめ
ReferenceError: location is not defined
vuejs で omisejapan の決済フォーム作成した時のメモ
ブラウザーで動く javascript のクッキー操作ライブラリ js-cookie
解決!phpMyAdmin テーブル構造の内容が表示されない問題
codeigniter email ライブラリでメール送信 日本語対応
javascript reduce 連想配列の合計計算覚えよう
Composer コマンドとオプション
爆速軽量フレームワーク codeigniter PHP 開発
nodejs 使う時のエラーたち
Lumen と Laravel 違い比較
javascript で作る html から PDF 変換 pdfmake の日本語対応
HTML から PDF に変換 PHP ライブラリ mPDF の設定
javascript 楽しく遊ぼう!メッセージつぶやくウシ cowsay
twig 3 人気 PHP テンプレートエンジンがバージョンアップ
Javascript vuejs の validation 正規表現でフォームチェック作ったときのメモ
正規表現一覧 よく使う検索・置換のパターン
javascript password generator ランダム文字列パスワード作成
javascript 日本語 shift-js 対応 CSV ダウンロード
Apache 初期設定メモ
開発におけるコーディングルール・規約
Laravel Error についてのメモ
laravel に vuejs 使うための初期設定
php curl 使って クリックなしで POST 送信
allowurlinclude の設定で ftp_connect()エラー