# 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 のクッキー操作ライブラリ js-cookie
javascript 日本語 shift-js 対応 CSV ダウンロード
ReferenceError: location is not defined
moment.js 使って日本語曜日対応
nodejs 使う時のエラーたち
javascript reduce 連想配列の合計計算覚えよう
Sweet Alert swal に複数 content
javascript 開発で出会った TypeError
Elastic Beanstalk \$\SERVER['REMOTEADDR'] 取得できない
Apache 初期設定メモ
php 開発におけるコーディングルール・規約
codeigniter email ライブラリでメール送信 日本語対応
php curl 使って クリックなしで POST 送信
php date 日付の日数・月数差を計算
PHP empty isset is_null の違い
php Exception エラーキャッチでメール送信
allowurlinclude の設定で ftp_connect()エラー
FlattenException deprecated
Lumen と Laravel 違い比較
Laravel 5.7 の MVC 使う時のメモ
PHP 8 リリース新機能と変更
解決!phpMyAdmin テーブル構造の内容が表示されない問題
Smarty HTTP URL 取得できるサーバー関数
開発時によく使うゼロ埋めパディング作業まとめ
twig 3 人気 PHP テンプレートエンジンがバージョンアップ
javascript で作る html から PDF 変換 pdfmake の日本語対応
Javascript vuejs の validation 正規表現でフォームチェック作ったときのメモ
PHP 7.4 にアップグレードして使えなくなる機能
HTML から PDF に変換 PHP ライブラリ mPDF の設定
php.ini 初期設定のいろいろ
爆速軽量フレームワーク codeigniter PHP 開発
Composer コマンドとオプション
Laravel Error についてのメモ
javascript 楽しく遊ぼう!メッセージつぶやくウシ cowsay