のぐそんブログ

暗いおじさんがシコシコ書くブログです。

Laravelでのjwt-auth利用する為のメモ。

Laravelでのjwt-auth利用する為の自分用のメモです。

Laravelの認証機能を利用してテーブルを作成

$ php artisan make:auth
$ php artisan migrate

jwt-authをインストール

composer require tymon/jwt-auth

configファイル生成

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

config/jwt.phpが作成される。

secretの生成

php artisan jwt:secret

.envファイルにJWT_SECRETが追加されているのを確認する。

app/User.php

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Tymon\JWTAuth\Contracts\JWTSubject;

class User extends Authenticatable implements JWTSubject
{
    use Notifiable;

    protected $fillable = [
        'name', 'email', 'password',
    ];

    protected $hidden = [
        'password', 'remember_token',
    ];

    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    public function getJWTCustomClaims()
    {
        return [];
    }
}

config/auth.php

<?php

return [
    'defaults' => [
        'guard' => 'api',
        'passwords' => 'users',
    ],

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'jwt',
            'provider' => 'users',
        ],
    ],

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],

];

app/Http/Controllers/Api/AuthController.php

<?php
namespace App\Http\Controllers;

class AuthController extends Controller
{
    function login() {
        $credentials = request(['email', 'password']);

        if (!$token = auth('api')->attempt($credentials)) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }

        return $this->respondWithToken($token);
    }

    public function logout()
    {
        auth()->logout();
        return response()->json(['message' => 'ログアウトしました。']);
    }

    public function me()
    {
        return response()->json(auth()->user());
    }

    protected function respondWithToken($token)
    {
        return response()->json([
            'access_token' => $token,
            'token_type' => 'bearer',
            'expires_in' => auth("api")->factory()->getTTL()
        ]);
    }
}

トークンの有効期限は60分に設定されている。 変更するにはconfig/jwt.phpを変更する。

routes/api.php

<?php

use Illuminate\Http\Request;

Route::post('/login', 'Api\AuthController@login');

// ユーザー情報と、ログアウトは認証あり
Route::group(['middleware' => 'auth:api'], function () {
    Route::get('/me', 'Api\AuthController@me');
    Route::post('/logout', 'Api\AuthController@logout');
});

疎通を確認

ユーザーデータを作成

以下を実行。

php artisan make:seeder UsersTableSeeder

以下を設定。

<?php

use Illuminate\Database\Seeder;

class UsersTableSeeder extends Seeder
{
    /#### 
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('users')->insert([
            [
                'email' => 'admin@example.com',
                'password' => bcrypt('password'),
                'remember_token' => null,
                'created_at' => '2018-10-02 14:28:19',
                'updated_at' => '2018-10-02 14:28:19'
            ]
        ]);
    }
}

実行。

php artisan db:seed

テーブルにユーザー情報が追加されているのを確認する。

ログインしてみる

curl http://localhost:8080/api/login -d email=admin@example.com -d password=password

以下が返却されればOK。

{"access_token":"eyJ0e...","token_type":"bearer","expires_in":3600}

アクセストークンを利用してユーザー情報を取得してみる

curl -H "Authorization: Bearer eyJ0e..." http://localhost:8080/api/me

以下が返却されればOK。

{"id":1,"email":"admin@example.com","email_verified_at":null,"created_at":"2018-10-02 14:28:19","updated_at":"2018-10-02 14:28:19"}

ユーザー登録をしてみる

app/Http/Controllers/Api/AuthController.php以下を追加。

    public function register(Request $request)
    {
        $user = new User;
        $user->fill($request->all());
        $user->password = bcrypt($request->password);
        $user->save();
        return $this->publishToken($request);
    }

    protected function publishToken($request)
    {
        $credentials = request(['email', 'password']);

        $token = auth('api')->attempt($credentials);
        return $this->respondWithToken($token);
    }

routes/api.phpに以下を追加

  Route::post('/login', 'Api\AuthController@login');
+ Route::post('/register', 'Api\AuthController@register');

実行

curl http://localhost:8080/api/register -d email=sample@example.com -d password=password

以下が返却されればOK。

{"access_token":"eyJ0eXAi...","token_type":"bearer","expires_in":3600}

VuePressの基礎基礎メモ

VuePressとは

Vue.jsベースの静的サイトジェネレーターです。

静的サイトジェネレーターとは、Markdownなどで書かれたファイルからHTMLやCSS、JSを生成してくれるツールです。 DBの準備などはいらず、全て静的なファイルになる為、簡単に安心なサイトが作成できます。

公式サイトはこちら

続きを読む

Eslintのメモ

Eslintの設定は基本的には"extends": "eslint:recommended"などを利用しているので、あまり個別に設定することはないのですが、 少し変更するときに毎回調べているのでメモしておこうと思います。

有効・無効の設定

内容
0 無効
1 有効(警告)
2 有効(エラー)

オプションの利用

ルールごとに独自のオプションを定義できる場合があります。

//rule: [{"error", "warn", "off"},{option}…]
"semi": ["error", "never"]

設定方法

rulesに設定内容を追加していく。

{
    "rules": {
        "quotes": [2, "double"],
        "curly": 2,
    }
}

rules

詳しくは公式を確認。

semi

セミコロン無しを許容しない

// Bad
var website = "eslint.org"
// Good
var website = "eslint.org";
option

セミコロンの利用を禁止

semi:["error", "never"]


// Bad
var name = "ESLint";
object.method = function() {
    // ...
};

セミコロン無しを禁止

semi: ["error", "always"]


var name = "ESLint"
object.method = function() {
    // ...
}

indent

インデントの設定

"indent": ["error", "tab"] // or "indent": ["error", 2]
// Bad
if (a) {
  b=c;
  function foo(d) {
    e=f;
  }
}

//Good
if (a) {
    b=c;
    function foo(d) {
        e=f;
    }
}

curly

中括弧の規則を指定する。

// Bad
if (foo) foo++;

// Good
if (foo) {
    foo++;
}

accessor-pairs

セッターとゲッターはペアで定義する必要がある

// Bad
var o = {
    set a(value) {
        this.val = value;
    }
};

// Good
var o = {
    set a(value) {
        this.val = value;
    },
    get a() {
        return this.val;
    }
};

dot-notation

ドット表記

// Bad
var x = foo[bar];
// Good
var x = foo.bar;

eqeqeq

型まで判定する

// Bad
if (x == 42) { }
if (obj.getStuff() != undefined) { }

// Good
if (x === 42) { }
if (obj.getStuff() !== undefined) { }

no-alert

alert、confirm、promptを利用しない

// Bad
alert("here!");                          
confirm("Are you sure?");                
prompt("What's your name?", "John Doe");

no-multi-spaces

複数のスペースを許容しない

// Bad
if(foo  === "bar") {}
var a =  1;  

//Good
if(foo === "bar") {}
var a = 1;

no-process-env

process.envの使用を許容しない。

// Bad
if(process.env.NODE_ENV === "development") { /*error Unexpected use of process.env.*/
    //...
}

//Good
var config = require("./config");

if(config.env === "development") {
    //...
}

no-redeclare

同じ変数を複数回定義を許可しない。

// Bad
var a = 3;
var a = 10; /*error "a" is already defined*/

//Good
var a = 3;
// ...
a = 10;

no-console

コンソールの消し忘れ

// Bad
console.log("Made it here.");

no-empty

空のブロックを許容しない

// Bad
if (foo) {
}

no-extra-parens

不要な()を許容しない。

// Bad
var a = (b * c);

no-extra-semi

不要なセミコロンを許容しない。

// Bad
var x = 5;;
function foo() {
    // code
};

valid-jsdoc

JSDocのコメントルールにあっているか

// Bad
// missing type for @param and missing @returns
/**                                 // 2 errors
 * A description
 * @param num1 The first number.
 */
function foo(num1) {
    // ...
}

LaravelのFilesystemsを利用してファイルをアップロード基礎基礎メモ

LaravelのFilesystemsを利用することで、ファイルストレージを簡単に設定することができます。 今回は「Local Storage」に保存してみたいと思います。

PHP初心者の私には割と時間がかかってしまったので忘れないようにメモしておきます。

S3に保存するのを試したメモはこちらです。

Filesystemの設定

Filesystemの設定はconfig/filesystems.phpにあります。 local、public、s3の設定がされています。

disk 概要
local storage/app/に保存される。
ブラウザからのアクセスは不可。
public storage/app/publicに保存される。
ブラウザからのアクセスは可。
ただしpublic/storageからstorage/app/publicへのシンボリックリンクを貼る必要がある
s3 割愛

      

フロント側

Vue.jsを利用しています。 UIは以下のような感じ。

<template>
  <div>
    <input type="file" name="file" @change="selectedFile">
    <button type="button" @click="upload">登録</button>
  </div>
</template>

<script>
  import axios from 'axios'
  export default {
    name: 'Upload',
    data(){
      return {
        uploadFile:null
      }
    },
    methods: {
      selectedFile:(e) => {
        let files = e.target.files
        if (files.length) this.uploadFile = files[0]
      },
      upload:() => {
        let data = new FormData()
        data.append('file', this.uploadFile)
        axios.post('/api/upload',data)
      }
    }
  }
</script>

API

Controllerだけ記載します。

<?php

namespace App\Http\Controllers\Api;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\User;

class  UserController extends Controller
{
    public function upload(Request $request,$id)
    {
        $user = User::find($id);

        $thumbnail = $request->file('file');
        $filename = time() . '.' . $thumbnail->getClientOriginalExtension();

        // strage/app/public配下に保存される
        $path =$thumbnail->storeAs('', $filename, ['disk' => 'public']);
        $user->thumbnail = $path;
        $user->save();

        return $path;
    }

}

storeAsを利用することで、保存するファイルに任意のファイル名を設定することができます。 第1引数 ・・・ 設定ファイルの指定しているrootディレクトリからのパス 第2引数 ・・・保存する際のファイル名 第3引数 ・・・利用するストレージ(local、public…など)

$thumbnail->storeAs('', $filename, ['disk' => 'public']);

シンボリックリンクを設定

保存するストレージにpublicを設定しても、ブラウザからアクセスすることはできません。 public/storage から storage/app/public へのリンボリックリンクを貼る必要があります。

当たり前なのかもしれませんが、シンボリックリンクは、Dockerや、Vagrantを利用している場合は内部で貼る必要があります。

$docker-compose exec --user=laradock workspace bash
$ php artisan storage:link

これで、http://hogehoge/storage/ファイル名 でアップロードしたファイルにアクセスすることができます。

もし、シンボリックリンクをはるときに以下のエラーが出た場合は/publicフォルダの中のstorageを削除してから、もう一度実行してみてください。

   ErrorException  : symlink(): No such file or directory

手順

cd public
rm storage
php artisan storage:link

dockerイメージを再構築した際のphp-fpmのエラーメモ

Laradocを利用して、以下のコマンドでdockerイメージを作成した際に、エラーが発生したのメモです。

docker-compose up -d --build nginx mysql workspace 

error

E: Failed to fetch http://security-cdn.debian.org/debian-security/pool/updates/main/g/ghostscript/libgs9_9.26a~dfsg-0+deb9u2_amd64.deb  404  Not Found
E: Failed to fetch http://security-cdn.debian.org/debian-security/pool/updates/main/g/ghostscript/ghostscript_9.26a~dfsg-0+deb9u2_amd64.deb  404  Not Found
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?
ERROR: Service 'php-fpm' failed to build: The command '/bin/sh -c if [ ${INSTALL_IMAGEMAGICK} = true ]; then     apt-get install -y libmagickwand-dev imagemagick &&     pecl install imagick &&     docker-php-ext-enable imagick ;fi' returned a non-zero code: 100

修正箇所

laradock/php-fpm/DockerfileのImageMagickの箇所を以下に変更。

###########################################################################
# ImageMagick:
###########################################################################

USER root

ARG INSTALL_IMAGEMAGICK=false

RUN if [ ${INSTALL_IMAGEMAGICK} = true ]; then \
    rm -rf /var/lib/apt/lists/* && \
    apt-get update && \
    apt-get install -y libmagickwand-dev imagemagick && \
    pecl install imagick && \
    docker-php-ext-enable imagick \
;fi