今回は認証部分のコントローラとテンプレートを作成します。
JWT用コントローラ作成
以下にJWTコントローラの全コードを掲載しました。できるだけコメントを多く入れたので内容はコメントを参照してください。
app/Http/Controllers/JWTAuthController.php
[php]
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\View;
use App\Models\User;
use JWTAuth;
use Carbon\Carbon;
use Log;
class JWTAuthController extends Controller
{
/**
* コンストラクター
*/
public function __construct()
{
$this->middleware(‘api’, [‘except’ => [‘regist’,’login’,’reminder’]]);
}
/**
* レスポンス作成
*
* @param string $status httpStatus Number
* @param string $statusText
* @param array $data
* @param string $request
* @return array
*/
protected function buildResponse($status,$statusText,$data,$request){
$response = [
‘status’ => $status,
‘statusText’ => $statusText,
‘data’ => $data,
‘request’ => $request
];
return $response;
}
/**
* ユーザー登録(レジスト)
* name,email,passwordをリクエストパラメータで受け取る必要がある。
*
* @param Request $request
* @return json
*/
public function register(Request $request)
{
// 入力情報のバリデーション
$validator = Validator::make($request->all(), [
‘name’ => ‘required|string|max:255’,
‘email’ => ‘required|string|email|max:255|unique:users’,
‘password’ => ‘required|string|min:8|max:64|confirmed’,
]);
// バリデーションエラーの場合レスポンス
if($validator->fails()){
$response = $this->buildResponse(400,$validator->errors(),”,’register’);
return response()->json($response, $response[‘status’]);
}
$user = new User;
$user->fill($request->all());
// 仮登録用Emailへ移動
$user->verify_email_address = $request->email;
// 仮のEmail。EmailはUniqのためダブらないようにランダムにする。
$user->email = Str::random(32)."@temp.tmp";
// パスワード暗号化
$user->password = bcrypt($request->password);
// 仮登録確認用設定
$user->verify_email = false;
$user->verify_token = Str::random(32);
$user->verify_date = Carbon::now()->toDateTimeString();
// ユーザー情報保存
$user->save();
// TODO:ここにメール送信処理を追加
$this->sendVerifyMail("regist",$user->verify_email_address,$user->verify_token);
// レスポンス作成
$response = $this->buildResponse(200,"OK",”,"register");
Log::info(‘Verify Regist User:’.$user);
return response()->json($response, $response[‘status’]);
}
/**
* WEBアクセス Email認証用メソッド
*
* Emailで届いたトークンを承認する
*
* @param string $token
* @return view
*/
public function verify($token){
$params[‘result’] = "error";
// トークンの有効期限を30分とするため有効な時間を算出
// 現在時間 -30分
$verify_limit = Carbon::now()->subMinute(30)->toDateTimeString();
$user = User::where(‘verify_token’, $token)->where(‘verify_date’, ‘>’, $verify_limit)->first();
if($user){
// 本登録されていない
if(User::where("email", $user->verify_email_address)->first()){
$params[‘result’] = "exist";
Log::info(‘Verify Exist: ‘ .$user->verify_email_address);
}else{
// 仮メールアドレスを本メールに移動
$user->email = $user->verify_email_address;
// 仮メールアドレスを削除
$user->verify_email_address = null;
// 有効なユーザーにする
$user->verify_email = true;
// その他クリーニング
$user->verify_token = null;
$user->verify_date = null;
// 承認日登録
$user->email_verified_at = Carbon::now()->toDateTimeString();
// テーブル保存
$user->save();
$params[‘result’] = "success";
Log::info(‘Verify Success: ‘.$user);
}
}else{
Log::info(‘Verify Not Found: token=’.$token);
}
return view(‘jwt.verify’, $params);
}
/**
* 認証メールを送信する
*
* @param [type] $type
* @param [type] $email
* @param [type] $token
* @return void
*/
public function sendVerifyMail($type, $email, $token)
{
$data = [‘token’ => $token];
if($type == ‘regist’){
Mail::send(‘jwt.emails.user_register’, $data, function($message) use ($email){
$message
->to($email)
->from(config(‘mail.from.address’))
->subject(‘ユーザー登録の確認メール’);
});
}
if($type == ‘reminder’){
Mail::send(‘jwt.emails.user_reminder’, $data, function($message) use ($email){
$message
->to($email)
->from(config(‘mail.from.address’))
->subject(‘パスワード変更確認メール’);
});
}
}
/**
* ログイン
* email,passwordをリクエストパラメータで受け取る必要がある。
*
* @param Request $request
* @return json
*/
public function login(Request $request)
{
// バリデーション
$validator = Validator::make($request->all(), [
‘email’ => ‘required|string|email|max:255’,
‘password’ => ‘required|string|min:8′,
]);
if($validator->fails()){
$response = $this->buildResponse(400,$validator->errors(),”,’login’);
return response()->json($response, $response[‘status’]);
}
// ユーザーの存在確認
$user = User::where(‘email’,$request->email)->where(‘verify_email’, true)->first();
if(!$user){
$response = $this->buildResponse(400,’User not found or not authenticated’,”,’login’);
return response()->json($response, $response[‘status’]);
}
//トークン作成
$token = auth(‘api’)->attempt([‘email’ => $request->email, ‘password’ => $request->password]);
if($token){
$data = [
‘access_token’ => $token,
‘token_type’ => ‘bearer’,
‘expires_in’ => auth(‘api’)->factory()->getTTL() * 60,
];
$response = $this->buildResponse(200,’OK’,$data,’login’);
}else{
$response = $this->buildResponse(400,’Password not found or no user’,” ,’login’);
Log::info(‘Login Auth Token Genarete Error’.$request->email."—-".$request->password);
}
return response()->json($response, $response[‘status’]);
}
/**
* ログアウト
*
* @return json
*/
public function logout()
{
auth()->logout();
$response = $this->buildResponse(200,’OK’,”,’logout’);
return response()->json($response, $response[‘status’]);
}
/**
* リフレッシュ・トークン.
*
* 有効期限超えて使う場合は新しいトークンを取得。
* 再度認証をおこなわずに新しいトークンに更新するには、
* リフレッシュAPIを使用する。
*
* @return jsonRsponse
*/
public function refresh()
{
// リフレッシュトークン取得
$token = auth()->refresh();
if($token){
$data = [
‘access_token’ => $token,
‘token_type’ => ‘bearer’,
‘expires_in’ => auth(‘api’)->factory()->getTTL() * 60,
];
$response = $this->buildResponse(200,’OK’,$data,’refresh’);
}else{
$response = $this->buildResponse(500,’Login Auth Error’,” ,’refresh’);
Log::info(‘Login Auth Token Genarete Error’.$request->email."—-".$request->password);
}
return response()->json($response, $response[‘status’]);
}
/**
* ユーザー情報の取得
*
* @return json
*/
public function me()
{
$user = auth(‘api’)->user();
if(!$user){
$response = $this->buildResponse(401,’Not Found or Unauthorized’,”,’me’);
return response()->json($response, $response[‘status’]);
}
$response = $this->buildResponse(200,’OK’,$user,’me’);
return response()->json($response, $response[‘status’]);
}
/**
* ユーザー情報の更新
*
* @param Request $request
* @return json
*/
public function update(Request $request)
{
$validator = Validator::make($request->all(), [
‘name_kana’ => ‘regex:/^[ア-ン゛゜ァ-ォャ-ョー ]+$/u’,
‘birthday’ => ‘date’,
‘gender’ => ‘in:male,femail’,
‘zip_cd’ => ‘digits:7’,
‘pref_id’ => ‘min:1|max:47’,
‘address1’ => ‘string|max:255’,
‘address2’ => ‘string|max:255’,
‘address3’ => ‘string|max:255’,
‘phone_number’ => ‘regex:/^[0-9]{10,11}$/i’
]);
if($validator->fails()){
$response = $this->buildResponse(400, $validator->errors(), ”, ‘update’);
return response()->json($response, $response[‘status’]);
}
$user = auth(‘api’)->user();
$form = $request->all();
// 更新されると困るものを除外,Usersのfillable宣言以外の項目
unset($form[‘name’]);
unset($form[‘email’]);
unset($form[‘password’]);
$user->fill($form)->save();
$response = $this->buildResponse(200, ‘OK’, $user, ‘update’);
return response()->json($response, $response[‘status’]);
}
/**
* パスワードリマインダー
*
* @param Request $request
* @return json
*/
public function reminder(Request $request){
// ユーザーが存在するか
if($request->email){
$user = User::where(‘email’,$request->email)->first();
}
if(!$user){
$response = $this->buildResponse(400, ‘User Not Found’, ”, ‘reminder’);
Log::info(‘Reminder User:’.’User Not Found’);
return response()->json($response, $response[‘status’]);
}
// verify_token作成し保存
$user->verify_token = Str::random(32);
$user->verify_date = Carbon::now()->toDateTimeString();
$user->save();
// メール送信
$this->sendVerifyMail("reminder",$user->email,$user->verify_token);
// レスポンス作成
$response = $this->buildResponse(200, ‘OK’, ”, ‘reminder’);
Log::info(‘Reminder User:’.$user);
return response()->json($response, $response[‘status’]);
}
/**
* WEBリクエスト パスワード設定画面
*
* @param Request $request
* @return view
*/
public function input_password(Request $request){
$token = $request->id;
$verify_limit = Carbon::now()->subMinute(30)->toDateTimeString();
// tokenが一致するか
$user = User::where(‘verify_token’, $token)->where(‘verify_date’, ‘>’, $verify_limit)->first();
if($user){
return view(‘jwt.input_password’)->with(‘token’,$token);
}
return view(‘jwt.reminder’)->with(‘result’,’error’);
}
/**
* WEBリクエスト パスワードリマインダー
*
* @param Request $request
* @return View
*/
public function password_change(Request $request){
$params[‘result’] = "error";
// 入力情報のバリデーション
$validator = Validator::make($request->all(), [
‘password’ => ‘required|string|min:8|confirmed’,
‘token’ => ‘required’,
]);
$token = $request->token;
// バリデーションエラーの場合レスポンス
if($validator->fails()){
$params[‘message’] = $validator->errors();
Log::info(‘Reminder Error: ‘.$validator->errors());
return redirect(‘/reminder/’.$token)
->withErrors($validator)
->withInput();
}else{
// トークンの有効期限を30分とするため有効な時間を算出
// 現在時間 -30分
$verify_limit = Carbon::now()->subMinute(30)->toDateTimeString();
// tokenが一致するか
$user = User::where(‘verify_token’, $token)->where(‘verify_date’, ‘>’, $verify_limit)->first();
if($user){
// パスワードを変更する
$user->password = bcrypt($request->password);
// その他クリーニング
$user->verify_token = null;
$user->verify_date = null;
// 承認日登録
$user->email_verified_at = Carbon::now()->toDateTimeString();
// テーブル保存
$user->save();
Log::info(‘Reminder Success: ‘.$user);
$params = [‘result’ => ‘success’];
}else{
Log::info(‘Reminder Error: Notfound User’);
$params = [‘result’ => ‘error’];
}
}
return view(‘jwt.reminder’, $params);
}
}
[/php]
ルーティング
APIルーティング
routes/api.php
[php]
Route::prefix(‘auth’)->group(function () {
Route::post(‘register’, ‘JWTAuthController@register’);
Route::post(‘login’, ‘JWTAuthController@login’);
Route::post(‘refresh’, ‘JWTAuthController@refresh’);
Route::get(‘logout’, ‘JWTAuthController@logout’);
Route::get(‘me’, ‘JWTAuthController@me’);
Route::post(‘update’, ‘JWTAuthController@update’);
Route::post(‘reminder’, ‘JWTAuthController@reminder’);
});
[/php]
Webルーティング
routes/web.php
[php]
Route::get(‘/’, function () {
return view(‘welcome’);
});
//Auth::routes(); 通常のログインは禁止します
Route::get(‘/home’, ‘HomeController@index’)->name(‘home’);
Route::get(‘/verify/{id}’, ‘JWTAuthController@verify’);
Route::get(‘/reminder/{id}’, ‘JWTAuthController@input_password’);
Route::post(‘/password_change’, ‘JWTAuthController@password_change’);
[/php]
テンプレートディレクトリ作成
ディレクトリ作成
[bash]
% mkdir resources/views/jwt
% mkdir resources/views/jwt/emails
[/bash]
認証用のEmailテンプレート作成
resources/views/jwt/emails/user_register.blade.php
[php]
<h1>ご利用ありがとうございます。</h1>
<br>
ご利用ありがとうございます。<br>
登録を受け付けました。<br>
<br>
以下のURLをクリックすると登録が完了します。<br>
<br>
<a href="{{ config(‘app.url’) }}/verify/<?php echo $token; ?>">{{ config(‘app.url’) }}/verify/<?php echo $token; ?></a><br>
<br>
クリック後、アプリからログインを行ってください。<br>
<br>
※このURLは登録から30分間有効です。<br>
[/php]
認証完了ページテンプレート作成
resources/views/jwt/verify.blade.php
@if ($result == "success")
認証コードを確認しました
ご登録ありがとうございました。
@elseif($result == "exist")
認証コードエラー
認証コードが間違っているか、すでに登録済みです。
@else
認証コードエラー
認証コードの有効期限が過ぎているか、見つかりませんでした。
@endif
パスワードリマインダー用のメールテンプレートを作成
resources/views/jwt/emails/user_reminder.blade.php
パスワード変更依頼メールです
パスワード変更のご依頼を受け付けました。
以下のURLをクリックしパスワードを変更してください。
">{{ config('app.url') }}/reminder/
クリック後、アプリからログインを行ってください。
※このURLは登録から30分間有効です。
パスワードリマインダーのパスワード変更ページ
resources/views/jwt/input_password.blade.php
パスワードリマインダー
パスワードリマインダーの完了ページ
resources/views/jwt/reminder.blade.php
@if ($result == "success")
パスワードリマインダー
@else
パスワードリマインダー
@endif
>
バリデーションメセージの日本語化
この状態で動作しますが、このままだとバリデーションのメッセージが英語になっています。
こちらの記事を参照されていただきました。ありがとうございます。
Laravelのバリデーションエラーメッセージを5分で日本語化する – Qiita
完成
メールサーバがない場合は.envのMAIL_DRIVERをlogにするとメールを送る代わりにLogに出力してくれます。
メールの設定は.envで行います。
[php]
// ….
MAIL_DRIVER=log // ここを変更
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
//….
[/php]
その他にもmailtrapサービスを使うとメール送信のテストが簡単に行なえます。こちらの利用をがおすすめです。
Mailtrap
コメント