Jwt-auth official document address
knowledge
- Install the configuration
jwt-auth
- Request validation class decouple controller parameter validation
API
Resource Applications
Install the configuration
Configure Composer Ali cloud mirroring
Global configuration, run the command
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
Copy the code
To modify only the current project configuration, go to the ant-Qa-server project root directory and run the command
composer config repo.packagist composer https://mirrors.aliyun.com/composer/
Copy the code
Install using Composer
Go to the ant-Qa-server project root directory
- Execute the command
composer require tymon/jwt-auth
The installation package - Execute the command
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
To generate thejwt
The configuration fileconfig/jwt.php
- Execute the command
php artisan jwt:secret
Generate encryption keys and add or update them.env
File,JWT_SECRET=c9wWs2aiDSKNUGX6lyrocQctrq3ON8tc7bWQDY2oyLf6G0LH8py8vuHVi9m6jRP4
content
Updating the User model
Modify the app/ user.php model as follows
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name'.'email'.'password',];/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password'.'remember_token',];/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at'= >'datetime',];/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* @return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* @return array
*/
public function getJWTCustomClaims()
{
return[]; }}Copy the code
Modify theconfig/auth.php
The configuration file
'defaults'= > ['guard'= >'api'.'passwords'= >'users',].'guards'= > ['web'= > ['driver'= >'session'.'provider'= >'users',].'api'= > ['driver'= >'jwt'.'provider'= >'users'.'hash'= >false,]],Copy the code
Registered routing
Edit the routes/api.php routing file
Route::post('auth/login'.'AuthController@login');
Route::post('auth/register'.'AuthController@register');
// Authentication is required for access
Route::group(['middleware'= >'auth:api'].function () {
Route::post('user/logout'.'AuthController@logout');
Route::get('user/info'.'UserController@find');
});
Copy the code
Routes in this file have API prefixes by default. This is the app/will/RouteServiceProvider service provider’s control
protected function mapApiRoutes()
{
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
}
Copy the code
Subsequently, the controllers of API route mapping are uniformly deployed under the API directory under the control, so it is ok to modify the namespace here and join the \ API directory
protected function mapApiRoutes()
{
Route::prefix('api')
->middleware('api')
->namespace($this->namespace.'\Api')
->group(base_path('routes/api.php'));
}
Copy the code
createAuthController
The controller
Execute the command in the project root directory PHP artisan make: controller Api/AuthController, this command will create Http/app/Controllers/Api/AuthController controller, if there is no Api catalogue, It is automatically created. Next, the interface functions of registering, logging in and logging out are realized in this controller.
Registered interface
When submitting a registration request, you need to send the user name, email address, password and confirm password parameters. These parameters need to be validated when processing a registration request, and the validation logic for these parameters is written in a separate form request class.
To create a registration request class, run the artisan command
php artisan make:request RegisterRequest
After the execution, will be generated in the project file/app/Http Requests/RegisterRequest PHP file. If the Requests directory did not exist before, it will be created automatically. The initial code is as follows
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class RegisterRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//]; }}Copy the code
The authorize() method is used to check the user’s permissions. If false is returned, the user has no right to submit the form, and the permission exception is thrown to abort the request. Now we adjust it to return true
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class RegisterRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name'= > ['required'.'string'.'max:255'].'email'= > ['required'.'string'.'email'.'max:255'.'unique:users'].'password'= > ['required'.'string'.'min:6'.'confirmed']]; }public function messages()
{
return [
'name.required'= >'Name field cannot be empty'.'name.string'= >'Name field only supports strings'.'name.max'= >'Maximum name field length is 255'.'email.required'= >'Mailbox field cannot be empty'.'email.email'= >'Mailbox field must be a formatted email address'.'email.max'= >'Maximum mailbox field length is 255'.'email.unique'= >'This mailbox already exists'.// Automatically query the users table to determine whether the mailbox already exists
'password.required'= >'Password field cannot be empty'.'password.string'= >'Password field only supports strings'.'password.min'= >'Password field length must not be less than 6'.'password.confirmed'= >'Inconsistent passwords'.// The form parameter must contain the password_confirmation field, which is the same as the password]; }}Copy the code
Next, in the AuthController controller, introduce the RegisterRequest form request class
public function register(RegisterRequest $request)
{
$data = $request->all();
$user = User::create([
'name'= >$data['name'].'email'= >$data['email'].'password' => Hash::make($data['password']),]);$token = auth()->login($user);
return [
'code'= >0.'msg'= >'success'.'data'= > ['token'= >$token,]]; }Copy the code
There is no need to write form parameter validation code in this method, which is already implemented in RegisterRequest. This logic simply executes the registration code and returns the user token.
Test registration interface
The validate method verifies whether the request is an Ajax request, that is, whether the accepted data type is specified in the request header. If it is not specified, it is automatically redirected. If it is specified, for example, accept => application/json accepts JSON data. A piece of JSON data will be returned
{
"message": "The given data was invalid."."errors": {
"name": [
"Name field cannot be empty"]."email": [
"Mailbox field cannot be empty"]."password": [
"Password field cannot be empty"]}}Copy the code
But this period of the json data does not accord with our API interface specification, you can change the app/Exception Handler. PHP files render () method, modified as follows
public function render($request.Exception $exception)
{
if ($exception instanceof ValidationException) {
$errors = $exception->errors();
$msg = 'Parameter error';
foreach ($errors as $errorMsg) {
$msg = $errorMsg[0]????'Parameter error';
}
return response()->json([
'code'= > -1.'msg'= >$msg.'data'= > []]); }return response()->json([
'code'= > -1.'msg'= >'System exception'.'data'= > []]);// return parent::render($request, $exception);
}
Copy the code
If the parameter rule is abnormal, only the first error message is obtained. Otherwise, an error message is returned
Currently, other exceptions are returned to the system exception.
Request type if we want, without judgment, unified returns json data, rather than the redirect page, you can change the Http/Middleware/app/Authenticate. PHP Middleware, modify redirectTo function as follows
use Illuminate\Auth\AuthenticationException;
protected function redirectTo($request)
{
throw new AuthenticationException();
if (!$request->expectsJson()) {
return route('login'); }}Copy the code
Normal result example
{
"code": 0."msg": "success"."data": {
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9sb2NhbGhvc3RcL2FwaVwvYXV0aFwvcmVnaXN0ZXIiLCJpYXQiOjE2MDgwMD A0OTQsImV4cCI6MTYwODAwNDA5NCwibmJmIjoxNjA4MDAwNDk0LCJqdGkiOiI4OHBDeHNNV2x6R0hlRUlwIiwic3ViIjoxLCJwcnYiOiI4N2UwYWYxZWY5Zm QxNTgxMmZkZWM5NzE1M2ExNGUwYjA0NzU0NmFhIn0.PhJ50lStyG6jcVuP0uQHVSXn27uuPveL-AJZ7Lz8tL0"}}Copy the code
Login interface
The request class that defines the login interface
Run the artisan command in the project root directory
php artisan make:request LoginRequest
Copy the code
After the execution, will be generated in the project file/app/Http Requests/LoginRequest PHP file. Modify this file
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class LoginRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'email'= > ['required'.'string'.'email'.'max:255'].'password'= > ['required'.'string'.'min:6']]; }}Copy the code
Edit Http/app/Controller/Api/AuthController PHP Controller, add the login method, as follows
public function login(LoginRequest $request)
{
if (!$token = auth()->attempt($request->all(['email'.'password'))) {return [
'code'= > -1.'msg'= >'Wrong account password'.'data'= > []]; }return [
'code'= >0.'msg'= >'success'.'data'= > ['token'= >$token,]]; }Copy the code
Logging out interface
Exit the login interface. You only need to set the token to invalid. Edit Http/app/Controller/Api/AuthController PHP Controller, add logout method, as follows
public function logout()
{
auth()->logout();
return [
'code'= >0.'msg'= >'success'.'data'= > []]; }Copy the code
If we have direct access to http://localhost/api/user/logout interface, returns the following result
{"code": -1, "data": []}Copy the code
AuthenticationException thrown by auth: API middleware routing protection. A special code value should be specified for such exceptions so that the front end can determine whether to jump to the login page. Modify the file/Exceptions/app/Http Handler. PHP render () method
public function render($request.Exception $exception)
{
if ($exception instanceof ValidationException) {
$errors = $exception->errors();
$msg = 'Parameter error';
foreach ($errors as $errorMsg) {
$msg = $errorMsg[0]????'Parameter error';
}
return response()->json([
'code'= > -1.'msg'= >$msg.'data'= > []]); }if ($exception instanceof AuthenticationException) {
return response()->json([
'code'= > -10001.'msg'= >'Authentication failed'.'data'= > []]); } dd($exception);
return response()->json([
'code'= > -1.'msg'= >'System exception'.'data'= > []]);// return parent::render($request, $exception);
}
Copy the code
Add if judgment
if ($exception instanceof AuthenticationException) {
return response()->json([
'code'= > -10001.'msg'= >'Authentication failed'.'data'= > []]); }Copy the code
If the exception type is AuthenticationException, the code value -10001 is returned, indicating that the authentication fails.
To access routes protected by auth: API middleware, add content to the header of the request
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9sb2NhbGhvc3RcL2FwaVwvYXV0aFwvbG9naW4iLCJpYXQiOjE2MDgwNDM1NDk sImV4cCI6MTYwODA0NzE0OSwibmJmIjoxNjA4MDQzNTQ5LCJqdGkiOiJIMVYyVk15dFY0akowUEIzIiwic3ViIjoxLCJwcnYiOiI4N2UwYWYxZWY5ZmQxNTg xMmZkZWM5NzE1M2ExNGUwYjA0NzU0NmFhIn0.nG7Hk0gMV6F5x4wmR2241PZ2jx6fFMmWghSwHajn07QCopy the code
The token can be obtained through the login interface.
Test exit login interface
The first time the token is invoked to exit the login interface, success is returned
{
"code": 0."msg": "success"."data": []}Copy the code
If an authentication failure result is returned after sending a request to invoke the logout interface
{
"code": - 10001.."msg": "Authentication failed"."data": []}Copy the code
Auth ()->logout(); The token has been invalidated and cannot be used again.
Interface to get user information
Interface to get user information, edited in a new UserController
php artisan make:controller Api/UserController
In the generated Http/Api/app/UserController. PHP controller, add the find method
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Resources\User;
class UserController extends Controller
{
public function find()
{
$user = auth()->user();
return [
'code'= >0.'msg'= >'success'.'data'= > ['user'= >new User($user),]]; }}Copy the code
$user = auth()->user(); Gets the current user model based on the current logon status
The User class instantiated by new User($User) is an API resource class that performs a layer of formatting conversion between retrieved data and returned API interface data. It is also easy to reuse with subsequent places that need the same data structure.
Generate a user information resource class
Execute the command in the project root directory PHP artisan make: the resource User, generates Http/app/Resources/User. The PHP file, the initial content is as follows
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class User extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return parent::toArray($request); }}Copy the code
Modify the returned user information structure. The edited content is as follows
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class User extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
*
* @return array
*/
public function toArray($request)
{
return [
'id'= >$this->id,
'name'= >$this->name, ]; }}Copy the code