How to implement JWT Auth About Restful API in Laravel 5.5
来源:互联网 发布:开淘宝店一个月能赚多少钱 编辑:程序博客网 时间:2024/06/05 19:08
How to implement JWT Auth About Restful API in Laravel 5.5
[myth@contoso ~]$ cd /home/myth/www && laravel new meeting
[root@contoso ~]# cat > /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.10.20 contoso.edu
[root@contoso ~]# cat > /etc/httpd/conf.d/httpd-vhosts.conf
<Directory "/home/myth/www/meeting">
Options +Indexes +FollowSymLinks
Order allow,deny
Allow from all
AllowOverride All
Require all granted
</Directory>
<VirtualHost *:80>
ServerAdmin zhengzizhi@126.com
DocumentRoot "/home/myth/www/meeting/public"
ServerName contoso.edu
ServerAlias contoso.edu
ErrorLog "/home/myth/log/httpd/contoso-edu-error_log"
CustomLog "/home/myth/log/httpd/contoso-edu-access_log" common
</VirtualHost>
/home/myth/www/meeting/routes/api.php
//Route::middleware('auth:api')->get('/user', function (Request $request) {
// return $request->user();
//});
Route::group(['prefix' => 'v1'], function() {
Route::resource('meeting', 'MeetingController', [
'except' => ['create', 'edit']
]);
Route::resource('meeting/registration', 'RegisterController', [
'only' => ['store', 'destroy']
]);
Route::post('/user/register', [
'uses' => 'AuthController@store'
]);
Route::post('/user/signin', [
'uses' => 'AuthController@signin'
]);
});
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan make:controller MeetingController --resource
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan make:controller RegisterController --resource
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan make:controller AuthController --resource
[myth@contoso meeting]$ php artisan route:list
+--------+-----------+--------------------------------------------+----------------------+-------------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+-----------+--------------------------------------------+----------------------+-------------------------------------------------+------------+
| | GET|HEAD | / | | Closure | web |
| | GET|HEAD | api/v1/meeting | meeting.index | App\Http\Controllers\MeetingController@index | api |
| | POST | api/v1/meeting | meeting.store | App\Http\Controllers\MeetingController@store | api |
| | POST | api/v1/meeting/registration | registration.store | App\Http\Controllers\RegisterController@store | api |
| | DELETE | api/v1/meeting/registration/{registration} | registration.destroy | App\Http\Controllers\RegisterController@destroy | api |
| | GET|HEAD | api/v1/meeting/{meeting} | meeting.show | App\Http\Controllers\MeetingController@show | api |
| | PUT|PATCH | api/v1/meeting/{meeting} | meeting.update | App\Http\Controllers\MeetingController@update | api |
| | DELETE | api/v1/meeting/{meeting} | meeting.destroy | App\Http\Controllers\MeetingController@destroy | api |
| | POST | api/v1/user/register | | App\Http\Controllers\AuthController@store | api |
| | POST | api/v1/user/signin | | App\Http\Controllers\AuthController@signin | api |
+--------+-----------+--------------------------------------------+----------------------+-------------------------------------------------+------------+
[myth@contoso meeting]$
/home/myth/www/meeting/app/Http/Controllers/MeetingController.php
public function store(Request $request) {
$title = $request->input('title');
$description = $request->input('description');
$time = $request->input('time');
$user_id = $request->input('user_id');
$meeting = [
'title' => $title,
'description' => $description,
'time' => $time,
'user_id' => $user_id,
'view_meeting' => [
'href' => 'api/v1/meeting/1',
'method' => 'GET'
],
];
$response = [
'msg' => 'Meeting created',
'data' => $meeting,
];
return response()->json($response, 201);
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting
Body
Key Value
title 年终总结大会
description 年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。
time 2017-12-30 9:30:00
user_id 1
https://laravel.com/docs/5.5/validation#available-validation-rules
/home/myth/www/meeting/.env
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:60rT/eLdGKXnDXg1UYtPVVOB0KgpDTJMuMMgaAAqkpA=
APP_DEBUG=true
APP_LOG_LEVEL=debug
APP_URL=http://localhost
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=meetingdb
DB_USERNAME=root
DB_PASSWORD=123456
BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
SESSION_LIFETIME=120
QUEUE_DRIVER=sync
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan make:model Meeting -m
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan make:migration create_meeting_user_table --create=meeting_user
/home/myth/www/meeting/database/migrations/2017_12_18_090430_create_meetings_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateMeetingsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('meetings', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('meetings');
}
}
/home/myth/www/meeting/database/migrations/2017_12_18_090445_create_meeting_user_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateMeetingUserTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('meeting_user', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('meeting_user');
}
}
定义表结构字段类型:
/home/myth/www/meeting/database/migrations/2017_12_18_090445_create_meeting_user_table.php
public function up()
{
Schema::create('meeting_user', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->integer('meeting_id')->unsigned();
$table->timestamps();
});
}
/home/myth/www/meeting/database/migrations/2017_12_18_090430_create_meetings_table.php
public function up()
{
Schema::create('meetings', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('description');
$table->timestamp('time');
$table->timestamps();
});
}
[myth@contoso meeting]$ cd /home/myth/www/meeting && php artisan migrate
Migrating: 2017_12_18_090430_create_meetings_table
Migrated: 2017_12_18_090430_create_meetings_table
Migrating: 2017_12_18_090445_create_meeting_user_table
Migrated: 2017_12_18_090445_create_meeting_user_table
/home/myth/www/meeting/app/User.php
public function meetings() {
return $this->belongsToMany(Meeting::class);
}
/home/myth/www/meeting/app/Meeting.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Meeting extends Model {
protected $fillable = ['title', 'description', 'time'];
public function users() {
return $this->belongsToMany(User::class);
}
}
/home/myth/www/meeting/app/Http/Controllers/AuthController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
class AuthController extends Controller {
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request) {
$this->validate($request, [
'name' => 'required',
'email' => 'required|email',
'password' => 'required|min:5',
]);
$name = $request->input('name');
$email = $request->input('email');
$password = $request->input('password');
$user = new User([
'name' => $name,
'email' => $email,
'password' => bcrypt($password),
]);
if ($user->save()) {
$user->signin = [
'href' => 'api/v1/user/signin',
'method' => 'POST',
'params' => 'email,password',
];
$response = [
'msg' => 'User created',
'user' => $user,
];
return response()->json($response, 201);
}
$response = [
'msg' => 'An error occurred',
];
return response()->json($response, 404);
}
/**
*
* @param \Illuminate\Http\Request $request
*/
public function signin(Request $request) {
//
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/user/register
Body
Key Value
name John
email john@126.com
password 123456
# /home/myth/www/meeting/app/Http/Controllers/MeetingController.php
<?php
namespace App\Http\Controllers;
use App\Meeting;
use Illuminate\Http\Request;
class MeetingController extends Controller {
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index() {
$meetings = Meeting::all();
foreach ($meetings as $meeting) {
$meeting->view_meeting = [
'href' => 'api/v1/meeting/' . $meeting->id,
'method' => 'GET'
];
}
$response = [
'msg' => 'List of all Meetings',
'meetings' => $meetings
];
return response()->json($response, 200);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request) {
$this->validate($request, [
'title' => 'required',
'description' => 'required',
'time' => 'required',
'user_id' => 'required',
]);
$title = $request->input('title');
$description = $request->input('description');
$time = $request->input('time');
$user_id = $request->input('user_id');
$meeting = new Meeting([
'title' => $title,
'description' => $description,
'time' => $time,
]);
if ($meeting->save()) {
$meeting->users()->attach($user_id);
$meeting->view_meeting = [
'href' => 'api/v1/meeting/' . $meeting->id,
'method' => 'GET'
];
$message = [
'message' => 'Meeting created',
'meeting' => $meeting,
];
return response()->json($message, 201);
}
$response = [
'message' => 'Error during creating'
];
return response()->json($response, 404);
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id) {
$meeting = Meeting::with('users')->where('id', $id)->firstOrFail();
$meeting->view_meetings = [
'href' => 'api/v1/meeting',
'method' => 'GET'
];
$response = [
'message' => 'Meeting information',
'meeting' => $meeting
];
return response()->json($response, 200);
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id) {
$this->validate($request, [
'title' => 'required',
'description' => 'required',
'time' => 'required',
'user_id' => 'required'
]);
$title = $request->input('title');
$description = $request->input('description');
$time = $request->input('time');
$user_id = $request->input('user_id');
$meeting = Meeting::with('users')->findOrFail($id);
if (!$meeting->users()->where('users.id', $user_id)->first()) {
return response()->json(['message' => 'user not registered for meeting, update not successful'], 401);
};
$meeting->time = $time;
$meeting->title = $title;
$meeting->description = $description;
if (!$meeting->update()) {
return response()->json([
'message' => 'Error during update'
], 404);
}
$meeting->view_meeting = [
'href' => 'api/v1/meeting/' . $meeting->id,
'method' => 'GET'
];
$response = [
'message' => 'Meeting Updated',
'meeting' => $meeting
];
return response()->json($response, 200);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id) {
$meeting = Meeting::findOrFail($id);
$users = $meeting->users;
$meeting->users()->detach();
if(!$meeting->delete()){
foreach ($users as $user){
$meeting->users()->attach($user);
}
return response()->json([
'message' => 'Deletion Failed'
], 404);
}
$response = [
'message' => 'Meeting deleted',
'create' => [
'href' => 'api/v1/meeting',
'method' => 'POST',
'params' => 'title, description, time'
]
];
return response()->json($response, 200);
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting
Body
Key Value
title 年终总结大会
description 年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。
time 2017-12-30 9:30:00
user_id 1
Output:
{
"message": "Meeting created",
"meeting": {
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 9:30:00",
"updated_at": "2017-12-18 15:27:29",
"created_at": "2017-12-18 15:27:29",
"id": 4,
"view_meeting": {
"href": "api/v1/meeting/4",
"method": "GET"
}
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
GET http://contoso.edu/api/v1/meeting/4
Output:
{
"message": "Meeting information",
"meeting": {
"id": 4,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-18 15:27:29",
"updated_at": "2017-12-18 15:27:29",
"view_meetings": {
"href": "api/v1/meeting",
"method": "GET"
},
"users": [
{
"id": 1,
"name": "John",
"email": "john@126.com",
"created_at": "2017-12-18 13:50:39",
"updated_at": "2017-12-18 13:50:39",
"pivot": {
"meeting_id": 4,
"user_id": 1
}
}
]
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
GET http://contoso.edu/api/v1/meeting
Output:
{
"msg": "List of all Meetings",
"meetings": [
{
"id": 4,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-18 15:27:29",
"updated_at": "2017-12-18 15:27:29",
"view_meeting": {
"href": "api/v1/meeting/4",
"method": "GET"
}
}
]
}
测试工具:Postman 模拟HTML网页界面的修改记录,把会议时间改为2017-12-30 14:30:00
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting/4
Body
Key Value
_method PATCH
title 年终总结大会
description 年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。
time 2017-12-30 14:30:00
user_id 1
Output:
{
"message": "Meeting Updated",
"meeting": {
"id": 4,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 14:30:00",
"created_at": "2017-12-18 15:27:29",
"updated_at": "2017-12-18 15:53:39",
"view_meeting": {
"href": "api/v1/meeting/4",
"method": "GET"
},
"users": [
{
"id": 1,
"name": "John",
"email": "john@126.com",
"created_at": "2017-12-18 13:50:39",
"updated_at": "2017-12-18 13:50:39",
"pivot": {
"meeting_id": 4,
"user_id": 1
}
}
]
}
}
测试工具:Postman 模拟HTML网页界面的删除记录
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting/4
Body
Key Value
_method DELETE
Output:
{
"message": "Meeting deleted",
"create": {
"href": "api/v1/meeting",
"method": "POST",
"params": "title, description, time"
}
}
# /home/myth/www/meeting/app/Http/Controllers/RegisterController.php
<?php
namespace App\Http\Controllers;
use App\User;
use App\Meeting;
use Illuminate\Http\Request;
class RegisterController extends Controller {
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request) {
$this->validate($request, [
'meeting_id' => 'required',
'user_id' => 'required',
]);
$meeting_id = $request->input('meeting_id');
$user_id = $request->input('user_id');
$meeting = Meeting::findOrFail($meeting_id);
$user = User::findOrFail($user_id);
$message = [
'message' => 'User is already registered for meeting',
'user' => $user,
'meeting' => $meeting,
'unregister' => [
'href' => 'api/v1/meeting/registration/' . $meeting->id,
'method' => 'DELETE',
]
];
if ($meeting->users()->where('users.id', $user->id)->first()) {
return response()->json($message, 404);
};
$user->meetings()->attach($meeting);
$response = [
'message' => 'User registered for meeting',
'meeting' => $meeting,
'user' => $user,
'unregister' => [
'href' => 'api/v1/meeting/registration/' . $meeting->id,
'method' => 'DELETE'
]
];
return response()->json($response, 201);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id) {
$meeting = Meeting::findOrFail($id);
$meeting->users()->detach();
$response = [
'message' => 'User unregistered for meeting',
'meeting' => $meeting,
'user' => 'tbd',
'register' => [
'href' => 'api/v1/meeting/registration',
'method' => 'POST',
'params' => 'user_id, meeting_id'
]
];
return response()->json($response, 200);
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting
Body
Key Value
title 年终总结大会
description 年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。
time 2017-12-30 9:30:00
user_id 1
Output:
{
"message": "Meeting created",
"meeting": {
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 9:30:00",
"updated_at": "2017-12-19 05:23:46",
"created_at": "2017-12-19 05:23:46",
"id": 5,
"view_meeting": {
"href": "api/v1/meeting/5",
"method": "GET"
}
}
}
测试工具:Postman 至少添加1条meeting记录,
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting/registration
Body
Key Value
user_id 1
meeting_id 5
Output:
{
"message": "User is already registered for meeting",
"user": {
"id": 1,
"name": "John",
"email": "john@126.com",
"created_at": "2017-12-18 13:50:39",
"updated_at": "2017-12-18 13:50:39"
},
"meeting": {
"id": 5,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-19 05:23:46",
"updated_at": "2017-12-19 05:23:46"
},
"unregister": {
"href": "api/v1/meeting/registration/5",
"method": "DELETE"
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/user/register
Body
Key Value
name Jack
email jack@136.com
password 123456
Output:
{
"msg": "User created",
"user": {
"name": "Jack",
"email": "jack@136.com",
"updated_at": "2017-12-19 05:34:44",
"created_at": "2017-12-19 05:34:44",
"id": 2,
"signin": {
"href": "api/v1/user/signin",
"method": "POST",
"params": "email,password"
}
}
}
测试工具:Postman 至少需要添加1条meeting记录,
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting/registration
Body
Key Value
user_id 2
meeting_id 5
Output:
{
"message": "User registered for meeting",
"meeting": {
"id": 5,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-19 05:23:46",
"updated_at": "2017-12-19 05:23:46"
},
"user": {
"id": 2,
"name": "Jack",
"email": "jack@136.com",
"created_at": "2017-12-19 05:34:44",
"updated_at": "2017-12-19 05:34:44"
},
"unregister": {
"href": "api/v1/meeting/registration/5",
"method": "DELETE"
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
GET http://contoso.edu/api/v1/meeting/5
Output:
{
"message": "Meeting information",
"meeting": {
"id": 5,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-19 05:23:46",
"updated_at": "2017-12-19 05:23:46",
"view_meetings": {
"href": "api/v1/meeting",
"method": "GET"
},
"users": [
{
"id": 1,
"name": "John",
"email": "john@126.com",
"created_at": "2017-12-18 13:50:39",
"updated_at": "2017-12-18 13:50:39",
"pivot": {
"meeting_id": 5,
"user_id": 1
}
},
{
"id": 2,
"name": "Jack",
"email": "jack@136.com",
"created_at": "2017-12-19 05:34:44",
"updated_at": "2017-12-19 05:34:44",
"pivot": {
"meeting_id": 5,
"user_id": 2
}
}
]
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting/registration/1
Body
Key Value
_method DELETE
Output:
{
"message": "User unregistered for meeting",
"meeting": {
"id": 5,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-19 05:23:46",
"updated_at": "2017-12-19 05:23:46"
},
"user": "tbd",
"register": {
"href": "api/v1/meeting/registration",
"method": "POST",
"params": "user_id, meeting_id"
}
}
select * from `meetings` where `meetings`.`id` = '5' limit 1;
delete from `meeting_user` where `meeting_id` = 5;
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting/5
Output:
{
"message": "Meeting information",
"meeting": {
"id": 5,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-19 05:23:46",
"updated_at": "2017-12-19 05:23:46",
"view_meetings": {
"href": "api/v1/meeting",
"method": "GET"
},
"users": []
}
}
https://github.com/barryvdh/laravel-cors
如何在Laravel5.5框架中使用JWT(Json Web Token) Auth
[myth@contoso ~]$ cd /home/myth/www/meeting && composer require barryvdh/laravel-cors # 安装需要的插件
Using version ^0.10.0 for barryvdh/laravel-cors
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
- Installing barryvdh/laravel-cors (v0.10.0): Downloading (100%)
Writing lock file
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: barryvdh/laravel-cors
Package manifest generated successfully.
[myth@contoso meeting]$
/home/myth/www/meeting/config/app.php
'providers' => [
... ...
... ...
/*
* Package Service Providers...
*/
Barryvdh\Cors\ServiceProvider::class,
... ...
... ...
],
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider"
Copied File [/vendor/barryvdh/laravel-cors/config/cors.php] To [/config/cors.php]
Publishing complete.
[myth@contoso meeting]$
/home/myth/www/meeting/app/Http/Kernel.php
$app->routeMiddleware([
// ...
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'cors' => \Barryvdh\Cors\HandleCors::class,
]);
https://github.com/tymondesigns/jwt-auth
https://github.com/tymondesigns/jwt-auth/wiki
https://github.com/tymondesigns/jwt-auth/wiki/Installation
/home/myth/www/meeting/config/app.php
'providers' => [
... ...
... ...
/*
* Package Service Providers...
*/
Barryvdh\Cors\ServiceProvider::class,
Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class,
... ...
... ...
],
[myth@contoso ~]$ cd /home/myth/www/meeting && composer require tymon/jwt-auth
Using version ^0.5.12 for tymon/jwt-auth
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 4 installs, 0 updates, 0 removals
- Installing symfony/polyfill-util (v1.6.0): Downloading (100%)
- Installing symfony/polyfill-php56 (v1.6.0): Downloading (100%)
- Installing namshi/jose (7.2.3): Downloading (100%)
- Installing tymon/jwt-auth (0.5.12): Downloading (100%)
namshi/jose suggests installing phpseclib/phpseclib (Allows to use Phpseclib as crypto engine, use version ^2.0.)
Writing lock file
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: barryvdh/laravel-cors
Package manifest generated successfully.
[myth@contoso meeting]$
/home/myth/www/meeting/config/app.php
'aliases' => [
... ...
... ...
'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class,
],
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"
Copied File [/vendor/tymon/jwt-auth/src/config/config.php] To [/config/jwt.php]
Publishing complete.
[myth@contoso meeting]$
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan jwt:generate
In BoundMethod.php line 135:
Method Tymon\JWTAuth\Commands\JWTGenerateCommand::handle() does not exist
[myth@contoso meeting]$
解决办法是扩展一个public function handle()方法:
/home/myth/www/meeting/vendor/tymon/jwt-auth/src/Commands/JWTGenerateCommand.php
public function handle(){
$this->fire();
}
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan jwt:generate
jwt-auth secret [Vrw8j8w4tyrmwYKIffIgMy0Vs4evIpWZ] set successfully.
[myth@contoso meeting]$
命令执行成功后,删掉刚刚扩展进来的public function handle()方法
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan make:middleware VerifyJWTToken
Middleware created successfully.
[myth@contoso meeting]$
# /home/myth/www/meeting/app/Http/Middleware/VerifyJWTToken.php
<?php
namespace App\Http\Middleware;
use Closure;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
class VerifyJWTToken {
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next) {
try {
$user = JWTAuth::toUser($request->input('token'));
} catch (JWTException $e) {
if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException) {
return response()->json(['token_expired'], $e->getStatusCode());
} else if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException) {
return response()->json(['token_invalid'], $e->getStatusCode());
} else {
return response()->json(['error' => 'Token is required']);
}
}
return $next($request);
}
}
/home/myth/www/meeting/app/Http/Kernel.php
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'cors' => \Barryvdh\Cors\HandleCors::class,
'jwt.auth' => \App\Http\Middleware\VerifyJWTToken::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];
/home/myth/www/meeting/app/Http/Controllers/AuthController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use JWTAuth;
use JWTAuthException;
use App\User;
class AuthController extends Controller {
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request) {
$this->validate($request, [
'name' => 'required',
'email' => 'required|email',
'password' => 'required|min:5'
]);
$name = $request->input('name');
$email = $request->input('email');
$password = $request->input('password');
$user = new User([
'name' => $name,
'email' => $email,
'password' => bcrypt($password)
]);
// JWTAuth
$credentials = [
'email' => $email,
'password' => $password
];
if ($user->save()) {
$token = null;
try {
if (!$token = JWTAuth::attempt($credentials)) {
return response()->json([
'message' => 'Email or Password are incorrect',
], 404);
}
} catch (JWTAuthException $e) {
return response()->json([
'message' => 'failed_to_create_token',
], 404);
}
$user->signin = [
'href' => 'api/v1/user/signin',
'method' => 'POST',
'params' => 'email, password'
];
$response = [
'message' => 'User created',
'user' => $user,
'token' => $token
];
return response()->json($response, 201);
}
$response = [
'message' => 'An error occurred'
];
return response()->json($response, 404);
}
/**
*
* @param \Illuminate\Http\Request $request
*/
public function signin(Request $request) {
//
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/user/register
Body
Key Value
name Jim
email jim@136.com
password 123456
Output:
{
"message": "User created",
"user": {
"name": "Jim",
"email": "jim@136.com",
"updated_at": "2017-12-19 08:19:42",
"created_at": "2017-12-19 08:19:42",
"id": 3,
"signin": {
"href": "api/v1/user/signin",
"method": "POST",
"params": "email, password"
}
},
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjMsImlzcyI6Imh0dHA6Ly9jb250b3NvLmVkdS9hcGkvdjEvdXNlci9yZWdpc3RlciIsImlhdCI6MTUxMzY3MTU4MiwiZXhwIjoxNTEzNjc1MTgyLCJuYmYiOjE1MTM2NzE1ODIsImp0aSI6IlFabTVjV1FHcHExQjlFRE4ifQ.d_EviHE2hNnq47CGEwp5wkj_A5DWIlR5bEZs4oi_11Q"
}
/home/myth/www/meeting/app/Http/Controllers/AuthController.php
public function signin(Request $request) {
$this->validate($request, [
'email' => 'required|email',
'password' => 'required|min:5'
]);
$email = $request->input('email');
$password = $request->input('password');
if ($user = User::where('email', $email)->first()) {
$credentials = [
'email' => $email,
'password' => $password
];
$token = null;
try {
if (!$token = JWTAuth::attempt($credentials)) {
return response()->json([
'message' => 'Email or Password are incorrect',
], 404);
}
} catch (JWTAuthException $e) {
return response()->json([
'message' => 'failed_to_create_token',
], 404);
}
$response = [
'message' => 'User signin',
'user' => $user,
'token' => $token
];
return response()->json($response, 201);
}
$response = [
'message' => 'An error occurred'
];
return response()->json($response, 404);
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/user/signin
Body
Key Value
email jim@136.com
password 123456
Output:
{
"message": "User signin",
"user": {
"id": 3,
"name": "Jim",
"email": "jim@136.com",
"created_at": "2017-12-19 08:19:42",
"updated_at": "2017-12-19 08:19:42"
},
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjMsImlzcyI6Imh0dHA6Ly9jb250b3NvLmVkdS9hcGkvdjEvdXNlci9zaWduaW4iLCJpYXQiOjE1MTM2NzQzMTIsImV4cCI6MTUxMzY3NzkxMiwibmJmIjoxNTEzNjc0MzEyLCJqdGkiOiJncWg0OFI3OE54NGpQVGNzIn0.cr3qSgEGXPvvZEzlH2MJnaUILXpcMq9APoWn6rKpB_o"
}
# /home/myth/www/meeting/app/Http/Controllers/MeetingController.php
public function __construct() {
$this->middleware('jwt.auth');
}
# /home/myth/www/meeting/routes/api.php 插入'middleware' => 'cors'
<?php
use Illuminate\Http\Request;
Route::group(['prefix' => 'v1', 'middleware' => 'cors'], function() {
Route::resource('meeting', 'MeetingController', [
'except' => ['create', 'edit']
]);
Route::resource('meeting/registration', 'RegisterController', [
'only' => ['store', 'destroy']
]);
Route::post('/user/register', [
'uses' => 'AuthController@store'
]);
Route::post('/user/signin', [
'uses' => 'AuthController@signin'
]);
});
# /home/myth/www/meeting/app/Http/Controllers/RegisterController.php
use JWTAuth;
public function __construct() {
$this->middleware('jwt.auth');
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/user/signin
Body
Key Value
email jim@136.com
password 123456
Output:
{
"message": "User signin",
"user": {
"id": 3,
"name": "Jim",
"email": "jim@136.com",
"created_at": "2017-12-19 08:19:42",
"updated_at": "2017-12-19 08:19:42"
},
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjMsImlzcyI6Imh0dHA6Ly9jb250b3NvLmVkdS9hcGkvdjEvdXNlci9zaWduaW4iLCJpYXQiOjE1MTM2NzY2NzQsImV4cCI6MTUxMzY4MDI3NCwibmJmIjoxNTEzNjc2Njc0LCJqdGkiOiJzd3ZRdlMxbmJmdEZvWVpVIn0.vxMRIK091bvv8HjimmsThahWg4zwgizdzJGfBNViaag"
}
测试工具:Postman
Headers
Key Value
Accept application/json
GET http://contoso.edu/api/v1/meeting
Body
Key Value
Output:
{
"error": "Token is required"
}
使用登录api接口获得的Token再一次提交请求:
Headers
Key Value
Accept application/json
GET http://contoso.edu/api/v1/meeting
点击Params
Key Value
token eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjMsImlzcyI6Imh0dHA6Ly9jb250b3NvLmVkdS9hcGkvdjEvdXNlci9zaWduaW4iLCJpYXQiOjE1MTM2NzY2NzQsImV4cCI6MTUxMzY4MDI3NCwibmJmIjoxNTEzNjc2Njc0LCJqdGkiOiJzd3ZRdlMxbmJmdEZvWVpVIn0.vxMRIK091bvv8HjimmsThahWg4zwgizdzJGfBNViaag
Output:
{
"msg": "List of all Meetings",
"meetings": [
{
"id": 5,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-19 05:23:46",
"updated_at": "2017-12-19 05:23:46",
"view_meeting": {
"href": "api/v1/meeting/5",
"method": "GET"
}
}
]
}
等价于链接(Token值来自登录成功后返回的Token):
http://contoso.edu/api/v1/meeting?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjMsImlzcyI6Imh0dHA6Ly9jb250b3NvLmVkdS9hcGkvdjEvdXNlci9zaWduaW4iLCJpYXQiOjE1MTM2NzY2NzQsImV4cCI6MTUxMzY4MDI3NCwibmJmIjoxNTEzNjc2Njc0LCJqdGkiOiJzd3ZRdlMxbmJmdEZvWVpVIn0.vxMRIK091bvv8HjimmsThahWg4zwgizdzJGfBNViaag
# /home/myth/www/meeting/app/Http/Controllers/MeetingController.php
public function __construct() {
//$this->middleware('jwt.auth');
$this->middleware(
'jwt.auth', ['except' => ['index', 'show']]
);
}
测试工具:Postman
Headers
Key Value
Accept application/json
GET http://contoso.edu/api/v1/meeting
Output:
{
"message": "Meeting information",
"meeting": {
"id": 5,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-19 05:23:46",
"updated_at": "2017-12-19 05:23:46",
"view_meetings": {
"href": "api/v1/meeting",
"method": "GET"
},
"users": []
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting
Body
Key Value
title 每周例会
description 汇报上周工作内容和末完成的工作,收集同事们合理化的建议和解决问题的办法,安排本周工作计划。
time 2017-12-18 9:30:00
user_id 2
Output:
{
"error": "Token is required"
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/user/signin
Body
Key Value
email jack@136.com
password 123456
Output:
{
"message": "User signin",
"user": {
"id": 2,
"name": "Jack",
"email": "jack@136.com",
"created_at": "2017-12-19 05:34:44",
"updated_at": "2017-12-19 05:34:44"
},
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIsImlzcyI6Imh0dHA6Ly9jb250b3NvLmVkdS9hcGkvdjEvdXNlci9zaWduaW4iLCJpYXQiOjE1MTM2ODkwNjQsImV4cCI6MTUxMzY5MjY2NCwibmJmIjoxNTEzNjg5MDY0LCJqdGkiOiJUNVdJZGJ0dW9oVlV4a05GIn0.mpylls1GOU0iLIyftcLrBjlkU8jatzZTsHql0NXED84"
}
测试工具:Postman 使用登录返回的Token来创建新记录
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting
Body
Key Value
title 每周例会
description 汇报上周工作内容和末完成的工作,收集同事们合理化的建议和解决问题的办法,安排本周工作计划。
time 2017-12-18 9:30:00
user_id 2
token eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIsImlzcyI6Imh0dHA6Ly9jb250b3NvLmVkdS9hcGkvdjEvdXNlci9zaWduaW4iLCJpYXQiOjE1MTM2ODkwNjQsImV4cCI6MTUxMzY5MjY2NCwibmJmIjoxNTEzNjg5MDY0LCJqdGkiOiJUNVdJZGJ0dW9oVlV4a05GIn0.mpylls1GOU0iLIyftcLrBjlkU8jatzZTsHql0NXED84
Output:
{
"message": "Meeting created",
"meeting": {
"title": "每周例会",
"description": "汇报上周工作内容和末完成的工作,收集同事们合理化的建议和解决问题的办法,安排本周工作计划。",
"time": "2017-12-18 9:30:00",
"updated_at": "2017-12-19 13:12:58",
"created_at": "2017-12-19 13:12:58",
"id": 6,
"view_meeting": {
"href": "api/v1/meeting/6",
"method": "GET"
}
}
}
# /home/myth/www/meeting/app/Http/Controllers/RegisterController.php
public function destroy($id) {
$user = JWTAuth::toUser($request['token']);
$meeting = Meeting::findOrFail($id);
$meeting->users()->detach($user->id);
$response = [
'message' => 'User unregistered for meeting',
'meeting' => $meeting,
'user' => 'tbd',
'register' => [
'href' => 'api/v1/meeting/registration',
'method' => 'POST',
'params' => 'user_id, meeting_id'
]
];
return response()->json($response, 200);
}
[myth@contoso ~]$ cd /home/myth/www && laravel new meeting
[root@contoso ~]# cat > /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.10.20 contoso.edu
[root@contoso ~]# cat > /etc/httpd/conf.d/httpd-vhosts.conf
<Directory "/home/myth/www/meeting">
Options +Indexes +FollowSymLinks
Order allow,deny
Allow from all
AllowOverride All
Require all granted
</Directory>
<VirtualHost *:80>
ServerAdmin zhengzizhi@126.com
DocumentRoot "/home/myth/www/meeting/public"
ServerName contoso.edu
ServerAlias contoso.edu
ErrorLog "/home/myth/log/httpd/contoso-edu-error_log"
CustomLog "/home/myth/log/httpd/contoso-edu-access_log" common
</VirtualHost>
/home/myth/www/meeting/routes/api.php
//Route::middleware('auth:api')->get('/user', function (Request $request) {
// return $request->user();
//});
Route::group(['prefix' => 'v1'], function() {
Route::resource('meeting', 'MeetingController', [
'except' => ['create', 'edit']
]);
Route::resource('meeting/registration', 'RegisterController', [
'only' => ['store', 'destroy']
]);
Route::post('/user/register', [
'uses' => 'AuthController@store'
]);
Route::post('/user/signin', [
'uses' => 'AuthController@signin'
]);
});
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan make:controller MeetingController --resource
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan make:controller RegisterController --resource
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan make:controller AuthController --resource
[myth@contoso meeting]$ php artisan route:list
+--------+-----------+--------------------------------------------+----------------------+-------------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+-----------+--------------------------------------------+----------------------+-------------------------------------------------+------------+
| | GET|HEAD | / | | Closure | web |
| | GET|HEAD | api/v1/meeting | meeting.index | App\Http\Controllers\MeetingController@index | api |
| | POST | api/v1/meeting | meeting.store | App\Http\Controllers\MeetingController@store | api |
| | POST | api/v1/meeting/registration | registration.store | App\Http\Controllers\RegisterController@store | api |
| | DELETE | api/v1/meeting/registration/{registration} | registration.destroy | App\Http\Controllers\RegisterController@destroy | api |
| | GET|HEAD | api/v1/meeting/{meeting} | meeting.show | App\Http\Controllers\MeetingController@show | api |
| | PUT|PATCH | api/v1/meeting/{meeting} | meeting.update | App\Http\Controllers\MeetingController@update | api |
| | DELETE | api/v1/meeting/{meeting} | meeting.destroy | App\Http\Controllers\MeetingController@destroy | api |
| | POST | api/v1/user/register | | App\Http\Controllers\AuthController@store | api |
| | POST | api/v1/user/signin | | App\Http\Controllers\AuthController@signin | api |
+--------+-----------+--------------------------------------------+----------------------+-------------------------------------------------+------------+
[myth@contoso meeting]$
/home/myth/www/meeting/app/Http/Controllers/MeetingController.php
public function store(Request $request) {
$title = $request->input('title');
$description = $request->input('description');
$time = $request->input('time');
$user_id = $request->input('user_id');
$meeting = [
'title' => $title,
'description' => $description,
'time' => $time,
'user_id' => $user_id,
'view_meeting' => [
'href' => 'api/v1/meeting/1',
'method' => 'GET'
],
];
$response = [
'msg' => 'Meeting created',
'data' => $meeting,
];
return response()->json($response, 201);
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting
Body
Key Value
title 年终总结大会
description 年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。
time 2017-12-30 9:30:00
user_id 1
https://laravel.com/docs/5.5/validation#available-validation-rules
/home/myth/www/meeting/.env
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:60rT/eLdGKXnDXg1UYtPVVOB0KgpDTJMuMMgaAAqkpA=
APP_DEBUG=true
APP_LOG_LEVEL=debug
APP_URL=http://localhost
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=meetingdb
DB_USERNAME=root
DB_PASSWORD=123456
BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
SESSION_LIFETIME=120
QUEUE_DRIVER=sync
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan make:model Meeting -m
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan make:migration create_meeting_user_table --create=meeting_user
/home/myth/www/meeting/database/migrations/2017_12_18_090430_create_meetings_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateMeetingsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('meetings', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('meetings');
}
}
/home/myth/www/meeting/database/migrations/2017_12_18_090445_create_meeting_user_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateMeetingUserTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('meeting_user', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('meeting_user');
}
}
定义表结构字段类型:
/home/myth/www/meeting/database/migrations/2017_12_18_090445_create_meeting_user_table.php
public function up()
{
Schema::create('meeting_user', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->integer('meeting_id')->unsigned();
$table->timestamps();
});
}
/home/myth/www/meeting/database/migrations/2017_12_18_090430_create_meetings_table.php
public function up()
{
Schema::create('meetings', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('description');
$table->timestamp('time');
$table->timestamps();
});
}
[myth@contoso meeting]$ cd /home/myth/www/meeting && php artisan migrate
Migrating: 2017_12_18_090430_create_meetings_table
Migrated: 2017_12_18_090430_create_meetings_table
Migrating: 2017_12_18_090445_create_meeting_user_table
Migrated: 2017_12_18_090445_create_meeting_user_table
/home/myth/www/meeting/app/User.php
public function meetings() {
return $this->belongsToMany(Meeting::class);
}
/home/myth/www/meeting/app/Meeting.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Meeting extends Model {
protected $fillable = ['title', 'description', 'time'];
public function users() {
return $this->belongsToMany(User::class);
}
}
/home/myth/www/meeting/app/Http/Controllers/AuthController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
class AuthController extends Controller {
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request) {
$this->validate($request, [
'name' => 'required',
'email' => 'required|email',
'password' => 'required|min:5',
]);
$name = $request->input('name');
$email = $request->input('email');
$password = $request->input('password');
$user = new User([
'name' => $name,
'email' => $email,
'password' => bcrypt($password),
]);
if ($user->save()) {
$user->signin = [
'href' => 'api/v1/user/signin',
'method' => 'POST',
'params' => 'email,password',
];
$response = [
'msg' => 'User created',
'user' => $user,
];
return response()->json($response, 201);
}
$response = [
'msg' => 'An error occurred',
];
return response()->json($response, 404);
}
/**
*
* @param \Illuminate\Http\Request $request
*/
public function signin(Request $request) {
//
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/user/register
Body
Key Value
name John
email john@126.com
password 123456
# /home/myth/www/meeting/app/Http/Controllers/MeetingController.php
<?php
namespace App\Http\Controllers;
use App\Meeting;
use Illuminate\Http\Request;
class MeetingController extends Controller {
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index() {
$meetings = Meeting::all();
foreach ($meetings as $meeting) {
$meeting->view_meeting = [
'href' => 'api/v1/meeting/' . $meeting->id,
'method' => 'GET'
];
}
$response = [
'msg' => 'List of all Meetings',
'meetings' => $meetings
];
return response()->json($response, 200);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request) {
$this->validate($request, [
'title' => 'required',
'description' => 'required',
'time' => 'required',
'user_id' => 'required',
]);
$title = $request->input('title');
$description = $request->input('description');
$time = $request->input('time');
$user_id = $request->input('user_id');
$meeting = new Meeting([
'title' => $title,
'description' => $description,
'time' => $time,
]);
if ($meeting->save()) {
$meeting->users()->attach($user_id);
$meeting->view_meeting = [
'href' => 'api/v1/meeting/' . $meeting->id,
'method' => 'GET'
];
$message = [
'message' => 'Meeting created',
'meeting' => $meeting,
];
return response()->json($message, 201);
}
$response = [
'message' => 'Error during creating'
];
return response()->json($response, 404);
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id) {
$meeting = Meeting::with('users')->where('id', $id)->firstOrFail();
$meeting->view_meetings = [
'href' => 'api/v1/meeting',
'method' => 'GET'
];
$response = [
'message' => 'Meeting information',
'meeting' => $meeting
];
return response()->json($response, 200);
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id) {
$this->validate($request, [
'title' => 'required',
'description' => 'required',
'time' => 'required',
'user_id' => 'required'
]);
$title = $request->input('title');
$description = $request->input('description');
$time = $request->input('time');
$user_id = $request->input('user_id');
$meeting = Meeting::with('users')->findOrFail($id);
if (!$meeting->users()->where('users.id', $user_id)->first()) {
return response()->json(['message' => 'user not registered for meeting, update not successful'], 401);
};
$meeting->time = $time;
$meeting->title = $title;
$meeting->description = $description;
if (!$meeting->update()) {
return response()->json([
'message' => 'Error during update'
], 404);
}
$meeting->view_meeting = [
'href' => 'api/v1/meeting/' . $meeting->id,
'method' => 'GET'
];
$response = [
'message' => 'Meeting Updated',
'meeting' => $meeting
];
return response()->json($response, 200);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id) {
$meeting = Meeting::findOrFail($id);
$users = $meeting->users;
$meeting->users()->detach();
if(!$meeting->delete()){
foreach ($users as $user){
$meeting->users()->attach($user);
}
return response()->json([
'message' => 'Deletion Failed'
], 404);
}
$response = [
'message' => 'Meeting deleted',
'create' => [
'href' => 'api/v1/meeting',
'method' => 'POST',
'params' => 'title, description, time'
]
];
return response()->json($response, 200);
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting
Body
Key Value
title 年终总结大会
description 年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。
time 2017-12-30 9:30:00
user_id 1
Output:
{
"message": "Meeting created",
"meeting": {
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 9:30:00",
"updated_at": "2017-12-18 15:27:29",
"created_at": "2017-12-18 15:27:29",
"id": 4,
"view_meeting": {
"href": "api/v1/meeting/4",
"method": "GET"
}
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
GET http://contoso.edu/api/v1/meeting/4
Output:
{
"message": "Meeting information",
"meeting": {
"id": 4,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-18 15:27:29",
"updated_at": "2017-12-18 15:27:29",
"view_meetings": {
"href": "api/v1/meeting",
"method": "GET"
},
"users": [
{
"id": 1,
"name": "John",
"email": "john@126.com",
"created_at": "2017-12-18 13:50:39",
"updated_at": "2017-12-18 13:50:39",
"pivot": {
"meeting_id": 4,
"user_id": 1
}
}
]
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
GET http://contoso.edu/api/v1/meeting
Output:
{
"msg": "List of all Meetings",
"meetings": [
{
"id": 4,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-18 15:27:29",
"updated_at": "2017-12-18 15:27:29",
"view_meeting": {
"href": "api/v1/meeting/4",
"method": "GET"
}
}
]
}
测试工具:Postman 模拟HTML网页界面的修改记录,把会议时间改为2017-12-30 14:30:00
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting/4
Body
Key Value
_method PATCH
title 年终总结大会
description 年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。
time 2017-12-30 14:30:00
user_id 1
Output:
{
"message": "Meeting Updated",
"meeting": {
"id": 4,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 14:30:00",
"created_at": "2017-12-18 15:27:29",
"updated_at": "2017-12-18 15:53:39",
"view_meeting": {
"href": "api/v1/meeting/4",
"method": "GET"
},
"users": [
{
"id": 1,
"name": "John",
"email": "john@126.com",
"created_at": "2017-12-18 13:50:39",
"updated_at": "2017-12-18 13:50:39",
"pivot": {
"meeting_id": 4,
"user_id": 1
}
}
]
}
}
测试工具:Postman 模拟HTML网页界面的删除记录
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting/4
Body
Key Value
_method DELETE
Output:
{
"message": "Meeting deleted",
"create": {
"href": "api/v1/meeting",
"method": "POST",
"params": "title, description, time"
}
}
# /home/myth/www/meeting/app/Http/Controllers/RegisterController.php
<?php
namespace App\Http\Controllers;
use App\User;
use App\Meeting;
use Illuminate\Http\Request;
class RegisterController extends Controller {
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request) {
$this->validate($request, [
'meeting_id' => 'required',
'user_id' => 'required',
]);
$meeting_id = $request->input('meeting_id');
$user_id = $request->input('user_id');
$meeting = Meeting::findOrFail($meeting_id);
$user = User::findOrFail($user_id);
$message = [
'message' => 'User is already registered for meeting',
'user' => $user,
'meeting' => $meeting,
'unregister' => [
'href' => 'api/v1/meeting/registration/' . $meeting->id,
'method' => 'DELETE',
]
];
if ($meeting->users()->where('users.id', $user->id)->first()) {
return response()->json($message, 404);
};
$user->meetings()->attach($meeting);
$response = [
'message' => 'User registered for meeting',
'meeting' => $meeting,
'user' => $user,
'unregister' => [
'href' => 'api/v1/meeting/registration/' . $meeting->id,
'method' => 'DELETE'
]
];
return response()->json($response, 201);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id) {
$meeting = Meeting::findOrFail($id);
$meeting->users()->detach();
$response = [
'message' => 'User unregistered for meeting',
'meeting' => $meeting,
'user' => 'tbd',
'register' => [
'href' => 'api/v1/meeting/registration',
'method' => 'POST',
'params' => 'user_id, meeting_id'
]
];
return response()->json($response, 200);
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting
Body
Key Value
title 年终总结大会
description 年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。
time 2017-12-30 9:30:00
user_id 1
Output:
{
"message": "Meeting created",
"meeting": {
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 9:30:00",
"updated_at": "2017-12-19 05:23:46",
"created_at": "2017-12-19 05:23:46",
"id": 5,
"view_meeting": {
"href": "api/v1/meeting/5",
"method": "GET"
}
}
}
测试工具:Postman 至少添加1条meeting记录,
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting/registration
Body
Key Value
user_id 1
meeting_id 5
Output:
{
"message": "User is already registered for meeting",
"user": {
"id": 1,
"name": "John",
"email": "john@126.com",
"created_at": "2017-12-18 13:50:39",
"updated_at": "2017-12-18 13:50:39"
},
"meeting": {
"id": 5,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-19 05:23:46",
"updated_at": "2017-12-19 05:23:46"
},
"unregister": {
"href": "api/v1/meeting/registration/5",
"method": "DELETE"
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/user/register
Body
Key Value
name Jack
email jack@136.com
password 123456
Output:
{
"msg": "User created",
"user": {
"name": "Jack",
"email": "jack@136.com",
"updated_at": "2017-12-19 05:34:44",
"created_at": "2017-12-19 05:34:44",
"id": 2,
"signin": {
"href": "api/v1/user/signin",
"method": "POST",
"params": "email,password"
}
}
}
测试工具:Postman 至少需要添加1条meeting记录,
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting/registration
Body
Key Value
user_id 2
meeting_id 5
Output:
{
"message": "User registered for meeting",
"meeting": {
"id": 5,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-19 05:23:46",
"updated_at": "2017-12-19 05:23:46"
},
"user": {
"id": 2,
"name": "Jack",
"email": "jack@136.com",
"created_at": "2017-12-19 05:34:44",
"updated_at": "2017-12-19 05:34:44"
},
"unregister": {
"href": "api/v1/meeting/registration/5",
"method": "DELETE"
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
GET http://contoso.edu/api/v1/meeting/5
Output:
{
"message": "Meeting information",
"meeting": {
"id": 5,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-19 05:23:46",
"updated_at": "2017-12-19 05:23:46",
"view_meetings": {
"href": "api/v1/meeting",
"method": "GET"
},
"users": [
{
"id": 1,
"name": "John",
"email": "john@126.com",
"created_at": "2017-12-18 13:50:39",
"updated_at": "2017-12-18 13:50:39",
"pivot": {
"meeting_id": 5,
"user_id": 1
}
},
{
"id": 2,
"name": "Jack",
"email": "jack@136.com",
"created_at": "2017-12-19 05:34:44",
"updated_at": "2017-12-19 05:34:44",
"pivot": {
"meeting_id": 5,
"user_id": 2
}
}
]
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting/registration/1
Body
Key Value
_method DELETE
Output:
{
"message": "User unregistered for meeting",
"meeting": {
"id": 5,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-19 05:23:46",
"updated_at": "2017-12-19 05:23:46"
},
"user": "tbd",
"register": {
"href": "api/v1/meeting/registration",
"method": "POST",
"params": "user_id, meeting_id"
}
}
select * from `meetings` where `meetings`.`id` = '5' limit 1;
delete from `meeting_user` where `meeting_id` = 5;
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting/5
Output:
{
"message": "Meeting information",
"meeting": {
"id": 5,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-19 05:23:46",
"updated_at": "2017-12-19 05:23:46",
"view_meetings": {
"href": "api/v1/meeting",
"method": "GET"
},
"users": []
}
}
https://github.com/barryvdh/laravel-cors
如何在Laravel5.5框架中使用JWT(Json Web Token) Auth
[myth@contoso ~]$ cd /home/myth/www/meeting && composer require barryvdh/laravel-cors # 安装需要的插件
Using version ^0.10.0 for barryvdh/laravel-cors
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
- Installing barryvdh/laravel-cors (v0.10.0): Downloading (100%)
Writing lock file
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: barryvdh/laravel-cors
Package manifest generated successfully.
[myth@contoso meeting]$
/home/myth/www/meeting/config/app.php
'providers' => [
... ...
... ...
/*
* Package Service Providers...
*/
Barryvdh\Cors\ServiceProvider::class,
... ...
... ...
],
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider"
Copied File [/vendor/barryvdh/laravel-cors/config/cors.php] To [/config/cors.php]
Publishing complete.
[myth@contoso meeting]$
/home/myth/www/meeting/app/Http/Kernel.php
$app->routeMiddleware([
// ...
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'cors' => \Barryvdh\Cors\HandleCors::class,
]);
https://github.com/tymondesigns/jwt-auth
https://github.com/tymondesigns/jwt-auth/wiki
https://github.com/tymondesigns/jwt-auth/wiki/Installation
/home/myth/www/meeting/config/app.php
'providers' => [
... ...
... ...
/*
* Package Service Providers...
*/
Barryvdh\Cors\ServiceProvider::class,
Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class,
... ...
... ...
],
[myth@contoso ~]$ cd /home/myth/www/meeting && composer require tymon/jwt-auth
Using version ^0.5.12 for tymon/jwt-auth
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 4 installs, 0 updates, 0 removals
- Installing symfony/polyfill-util (v1.6.0): Downloading (100%)
- Installing symfony/polyfill-php56 (v1.6.0): Downloading (100%)
- Installing namshi/jose (7.2.3): Downloading (100%)
- Installing tymon/jwt-auth (0.5.12): Downloading (100%)
namshi/jose suggests installing phpseclib/phpseclib (Allows to use Phpseclib as crypto engine, use version ^2.0.)
Writing lock file
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: barryvdh/laravel-cors
Package manifest generated successfully.
[myth@contoso meeting]$
/home/myth/www/meeting/config/app.php
'aliases' => [
... ...
... ...
'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class,
],
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"
Copied File [/vendor/tymon/jwt-auth/src/config/config.php] To [/config/jwt.php]
Publishing complete.
[myth@contoso meeting]$
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan jwt:generate
In BoundMethod.php line 135:
Method Tymon\JWTAuth\Commands\JWTGenerateCommand::handle() does not exist
[myth@contoso meeting]$
解决办法是扩展一个public function handle()方法:
/home/myth/www/meeting/vendor/tymon/jwt-auth/src/Commands/JWTGenerateCommand.php
public function handle(){
$this->fire();
}
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan jwt:generate
jwt-auth secret [Vrw8j8w4tyrmwYKIffIgMy0Vs4evIpWZ] set successfully.
[myth@contoso meeting]$
命令执行成功后,删掉刚刚扩展进来的public function handle()方法
[myth@contoso ~]$ cd /home/myth/www/meeting && php artisan make:middleware VerifyJWTToken
Middleware created successfully.
[myth@contoso meeting]$
# /home/myth/www/meeting/app/Http/Middleware/VerifyJWTToken.php
<?php
namespace App\Http\Middleware;
use Closure;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
class VerifyJWTToken {
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next) {
try {
$user = JWTAuth::toUser($request->input('token'));
} catch (JWTException $e) {
if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException) {
return response()->json(['token_expired'], $e->getStatusCode());
} else if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException) {
return response()->json(['token_invalid'], $e->getStatusCode());
} else {
return response()->json(['error' => 'Token is required']);
}
}
return $next($request);
}
}
/home/myth/www/meeting/app/Http/Kernel.php
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'cors' => \Barryvdh\Cors\HandleCors::class,
'jwt.auth' => \App\Http\Middleware\VerifyJWTToken::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];
/home/myth/www/meeting/app/Http/Controllers/AuthController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use JWTAuth;
use JWTAuthException;
use App\User;
class AuthController extends Controller {
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request) {
$this->validate($request, [
'name' => 'required',
'email' => 'required|email',
'password' => 'required|min:5'
]);
$name = $request->input('name');
$email = $request->input('email');
$password = $request->input('password');
$user = new User([
'name' => $name,
'email' => $email,
'password' => bcrypt($password)
]);
// JWTAuth
$credentials = [
'email' => $email,
'password' => $password
];
if ($user->save()) {
$token = null;
try {
if (!$token = JWTAuth::attempt($credentials)) {
return response()->json([
'message' => 'Email or Password are incorrect',
], 404);
}
} catch (JWTAuthException $e) {
return response()->json([
'message' => 'failed_to_create_token',
], 404);
}
$user->signin = [
'href' => 'api/v1/user/signin',
'method' => 'POST',
'params' => 'email, password'
];
$response = [
'message' => 'User created',
'user' => $user,
'token' => $token
];
return response()->json($response, 201);
}
$response = [
'message' => 'An error occurred'
];
return response()->json($response, 404);
}
/**
*
* @param \Illuminate\Http\Request $request
*/
public function signin(Request $request) {
//
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/user/register
Body
Key Value
name Jim
email jim@136.com
password 123456
Output:
{
"message": "User created",
"user": {
"name": "Jim",
"email": "jim@136.com",
"updated_at": "2017-12-19 08:19:42",
"created_at": "2017-12-19 08:19:42",
"id": 3,
"signin": {
"href": "api/v1/user/signin",
"method": "POST",
"params": "email, password"
}
},
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjMsImlzcyI6Imh0dHA6Ly9jb250b3NvLmVkdS9hcGkvdjEvdXNlci9yZWdpc3RlciIsImlhdCI6MTUxMzY3MTU4MiwiZXhwIjoxNTEzNjc1MTgyLCJuYmYiOjE1MTM2NzE1ODIsImp0aSI6IlFabTVjV1FHcHExQjlFRE4ifQ.d_EviHE2hNnq47CGEwp5wkj_A5DWIlR5bEZs4oi_11Q"
}
/home/myth/www/meeting/app/Http/Controllers/AuthController.php
public function signin(Request $request) {
$this->validate($request, [
'email' => 'required|email',
'password' => 'required|min:5'
]);
$email = $request->input('email');
$password = $request->input('password');
if ($user = User::where('email', $email)->first()) {
$credentials = [
'email' => $email,
'password' => $password
];
$token = null;
try {
if (!$token = JWTAuth::attempt($credentials)) {
return response()->json([
'message' => 'Email or Password are incorrect',
], 404);
}
} catch (JWTAuthException $e) {
return response()->json([
'message' => 'failed_to_create_token',
], 404);
}
$response = [
'message' => 'User signin',
'user' => $user,
'token' => $token
];
return response()->json($response, 201);
}
$response = [
'message' => 'An error occurred'
];
return response()->json($response, 404);
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/user/signin
Body
Key Value
email jim@136.com
password 123456
Output:
{
"message": "User signin",
"user": {
"id": 3,
"name": "Jim",
"email": "jim@136.com",
"created_at": "2017-12-19 08:19:42",
"updated_at": "2017-12-19 08:19:42"
},
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjMsImlzcyI6Imh0dHA6Ly9jb250b3NvLmVkdS9hcGkvdjEvdXNlci9zaWduaW4iLCJpYXQiOjE1MTM2NzQzMTIsImV4cCI6MTUxMzY3NzkxMiwibmJmIjoxNTEzNjc0MzEyLCJqdGkiOiJncWg0OFI3OE54NGpQVGNzIn0.cr3qSgEGXPvvZEzlH2MJnaUILXpcMq9APoWn6rKpB_o"
}
# /home/myth/www/meeting/app/Http/Controllers/MeetingController.php
public function __construct() {
$this->middleware('jwt.auth');
}
# /home/myth/www/meeting/routes/api.php 插入'middleware' => 'cors'
<?php
use Illuminate\Http\Request;
Route::group(['prefix' => 'v1', 'middleware' => 'cors'], function() {
Route::resource('meeting', 'MeetingController', [
'except' => ['create', 'edit']
]);
Route::resource('meeting/registration', 'RegisterController', [
'only' => ['store', 'destroy']
]);
Route::post('/user/register', [
'uses' => 'AuthController@store'
]);
Route::post('/user/signin', [
'uses' => 'AuthController@signin'
]);
});
# /home/myth/www/meeting/app/Http/Controllers/RegisterController.php
use JWTAuth;
public function __construct() {
$this->middleware('jwt.auth');
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/user/signin
Body
Key Value
email jim@136.com
password 123456
Output:
{
"message": "User signin",
"user": {
"id": 3,
"name": "Jim",
"email": "jim@136.com",
"created_at": "2017-12-19 08:19:42",
"updated_at": "2017-12-19 08:19:42"
},
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjMsImlzcyI6Imh0dHA6Ly9jb250b3NvLmVkdS9hcGkvdjEvdXNlci9zaWduaW4iLCJpYXQiOjE1MTM2NzY2NzQsImV4cCI6MTUxMzY4MDI3NCwibmJmIjoxNTEzNjc2Njc0LCJqdGkiOiJzd3ZRdlMxbmJmdEZvWVpVIn0.vxMRIK091bvv8HjimmsThahWg4zwgizdzJGfBNViaag"
}
测试工具:Postman
Headers
Key Value
Accept application/json
GET http://contoso.edu/api/v1/meeting
Body
Key Value
Output:
{
"error": "Token is required"
}
使用登录api接口获得的Token再一次提交请求:
Headers
Key Value
Accept application/json
GET http://contoso.edu/api/v1/meeting
点击Params
Key Value
token eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjMsImlzcyI6Imh0dHA6Ly9jb250b3NvLmVkdS9hcGkvdjEvdXNlci9zaWduaW4iLCJpYXQiOjE1MTM2NzY2NzQsImV4cCI6MTUxMzY4MDI3NCwibmJmIjoxNTEzNjc2Njc0LCJqdGkiOiJzd3ZRdlMxbmJmdEZvWVpVIn0.vxMRIK091bvv8HjimmsThahWg4zwgizdzJGfBNViaag
Output:
{
"msg": "List of all Meetings",
"meetings": [
{
"id": 5,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-19 05:23:46",
"updated_at": "2017-12-19 05:23:46",
"view_meeting": {
"href": "api/v1/meeting/5",
"method": "GET"
}
}
]
}
等价于链接(Token值来自登录成功后返回的Token):
http://contoso.edu/api/v1/meeting?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjMsImlzcyI6Imh0dHA6Ly9jb250b3NvLmVkdS9hcGkvdjEvdXNlci9zaWduaW4iLCJpYXQiOjE1MTM2NzY2NzQsImV4cCI6MTUxMzY4MDI3NCwibmJmIjoxNTEzNjc2Njc0LCJqdGkiOiJzd3ZRdlMxbmJmdEZvWVpVIn0.vxMRIK091bvv8HjimmsThahWg4zwgizdzJGfBNViaag
# /home/myth/www/meeting/app/Http/Controllers/MeetingController.php
public function __construct() {
//$this->middleware('jwt.auth');
$this->middleware(
'jwt.auth', ['except' => ['index', 'show']]
);
}
测试工具:Postman
Headers
Key Value
Accept application/json
GET http://contoso.edu/api/v1/meeting
Output:
{
"message": "Meeting information",
"meeting": {
"id": 5,
"title": "年终总结大会",
"description": "年终总结是人们对一年来的工作学习进行 回顾和分析,从中找出经验和教训,引出规律性认识,以 指导今后工作和实践活动的一种应用文体。年终总结的内容包括一年来的情况概述、成绩和经验教训、今后努力的方向。",
"time": "2017-12-30 09:30:00",
"created_at": "2017-12-19 05:23:46",
"updated_at": "2017-12-19 05:23:46",
"view_meetings": {
"href": "api/v1/meeting",
"method": "GET"
},
"users": []
}
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting
Body
Key Value
title 每周例会
description 汇报上周工作内容和末完成的工作,收集同事们合理化的建议和解决问题的办法,安排本周工作计划。
time 2017-12-18 9:30:00
user_id 2
Output:
{
"error": "Token is required"
}
测试工具:Postman
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/user/signin
Body
Key Value
email jack@136.com
password 123456
Output:
{
"message": "User signin",
"user": {
"id": 2,
"name": "Jack",
"email": "jack@136.com",
"created_at": "2017-12-19 05:34:44",
"updated_at": "2017-12-19 05:34:44"
},
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIsImlzcyI6Imh0dHA6Ly9jb250b3NvLmVkdS9hcGkvdjEvdXNlci9zaWduaW4iLCJpYXQiOjE1MTM2ODkwNjQsImV4cCI6MTUxMzY5MjY2NCwibmJmIjoxNTEzNjg5MDY0LCJqdGkiOiJUNVdJZGJ0dW9oVlV4a05GIn0.mpylls1GOU0iLIyftcLrBjlkU8jatzZTsHql0NXED84"
}
测试工具:Postman 使用登录返回的Token来创建新记录
Headers
Key Value
Accept application/json
POST http://contoso.edu/api/v1/meeting
Body
Key Value
title 每周例会
description 汇报上周工作内容和末完成的工作,收集同事们合理化的建议和解决问题的办法,安排本周工作计划。
time 2017-12-18 9:30:00
user_id 2
token eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIsImlzcyI6Imh0dHA6Ly9jb250b3NvLmVkdS9hcGkvdjEvdXNlci9zaWduaW4iLCJpYXQiOjE1MTM2ODkwNjQsImV4cCI6MTUxMzY5MjY2NCwibmJmIjoxNTEzNjg5MDY0LCJqdGkiOiJUNVdJZGJ0dW9oVlV4a05GIn0.mpylls1GOU0iLIyftcLrBjlkU8jatzZTsHql0NXED84
Output:
{
"message": "Meeting created",
"meeting": {
"title": "每周例会",
"description": "汇报上周工作内容和末完成的工作,收集同事们合理化的建议和解决问题的办法,安排本周工作计划。",
"time": "2017-12-18 9:30:00",
"updated_at": "2017-12-19 13:12:58",
"created_at": "2017-12-19 13:12:58",
"id": 6,
"view_meeting": {
"href": "api/v1/meeting/6",
"method": "GET"
}
}
}
# /home/myth/www/meeting/app/Http/Controllers/RegisterController.php
public function destroy($id) {
$user = JWTAuth::toUser($request['token']);
$meeting = Meeting::findOrFail($id);
$meeting->users()->detach($user->id);
$response = [
'message' => 'User unregistered for meeting',
'meeting' => $meeting,
'user' => 'tbd',
'register' => [
'href' => 'api/v1/meeting/registration',
'method' => 'POST',
'params' => 'user_id, meeting_id'
]
];
return response()->json($response, 200);
}
阅读全文
0 0
- How to implement JWT Auth About Restful API in Laravel 5.5
- lumen5.4整合dingo/api、jwt-auth
- HOW TO IMPLEMENT WEB SERVICES IN INDY
- How To: Implement A Server Plug-in
- How to implement Polymorphism in C
- How to implement linked controls in gridview
- How to implement master-details in OAF?
- How to Implement Ajax in WordPress Themes
- how to implement the WaitForMultipleObjects in linux
- How to implement inheritance in JavaScript
- How to implement switch statement in python
- how to implement WaitForMultipleObjects in linux
- How to implement xpcom module in JavaScript
- Yii2 RESTful API Auth Mechanism
- Laravel (Lumen) 中使用JWT-Auth刷新token的问题
- About Restful arch. & api.
- laravel 5.4 JWT + Dingo 构建API 攻略
- About --auth-user-pass-verify in OpenVPN
- linux chmod命令
- C/C++ 笔试、面试题目大汇总
- ubuntu16.04安装cuda9——简明教程
- FormData 实现文件上传实例
- Ubuntu16.04 pyfasterrcnn make error
- How to implement JWT Auth About Restful API in Laravel 5.5
- Chrome控制台提示“Slow network is detected. Fallback font will be used while loading”
- 仿射密码加解密及暴力破解c++实现
- android 事件分发机制(源码分析)—(详细)(逐步总结)(值得一看)
- 创建一个双向链表或双向循环链表
- 2017/12/19C语言作业
- 猜1到100之间的数字
- Win10 VS2015 OpenGL + freeglut + glew + glm 环境配置
- MATLAB实现基于小波变换的车牌定位