>PHP 프레임워크 >Laravel >Laravel을 사용하여 JWT 인증을 통합하여 RestfulApi 개발

Laravel을 사용하여 JWT 인증을 통합하여 RestfulApi 개발

Guanhui
Guanhui앞으로
2020-05-09 10:43:452480검색

이 기사에서는 JWT 인증을 사용하여 Laravel에서 Restful API를 구축하는 방법을 알아봅니다. JWT는 JSON 웹 토큰을 나타냅니다. 또한 API를 사용하여 사용자 제품에 대한 완전한 기능의 CRUD 애플리케이션을 생성할 것입니다.

API는 크로스 플랫폼 애플리케이션을 사용할 때 매우 좋은 선택입니다. 귀하의 제품에는 웹사이트 외에도 Android 및 iOS 앱이 있을 수도 있습니다. 이 경우 백엔드 코드를 변경하지 않고도 다양한 프런트엔드를 작성할 수 있으므로 API도 마찬가지로 훌륭합니다. API를 사용할 때 일부 매개변수와 함께 GET, POST 또는 기타 유형의 요청을 누르면 서버는 클라이언트 애플리케이션에서 처리되는 JSON(JavaScript Object Notation) 형식으로 일부 데이터를 반환합니다.

설명

먼저 앱 세부 정보와 기능을 적어 보겠습니다. JWT 인증을 사용하여 laravel에서 Restful API를 사용하여 기본 사용자 제품 목록을 구축합니다.

A 사용자 는 다음 기능을 사용하여 등록하고 새 계정을 만듭니다.

  • 계정에 로그인

  • 로그아웃하고 토큰을 삭제하고 앱을 종료합니다

  • 가져오기 로그인한 사용자의 세부 정보

  • 사용자가 사용할 수 있는 제품 목록 검색

  • ID로 특정 제품 찾기

  • 사용자 제품 목록에 새 제품 추가

  • 기존 제품 세부 정보 편집

  • 기존 제품 제거 사용자 목록

A 사용자 필수

  • 이름

  • email

  • password

A 제품 필수

  • 이름

  • 가격

  • Quantity

Create new project

아래 명령어를 실행하면 새로운 Laravel 프로젝트를 시작하고 생성할 수 있습니다.

composer create-project --prefer-dist laravel/laravel jwt

이렇게 하면 jwt라는 디렉터리에 새 Laravel 프로젝트가 생성됩니다.

JWT 확장 패키지 구성

Laravel에서 JWT를 사용할 수 있도록 tymondesigns/jwt-auth 확장 패키지를 사용하겠습니다.

tymon/jwt-auth 확장 패키지를 설치하세요

이 확장 패키지를 Laravel 애플리케이션에 설치해 보겠습니다. Laravel 5.5 이상을 사용하는 경우 다음 명령을 실행하여 JWT 패키지의 dev-develop 버전을 얻으세요:

composer require tymon/jwt-auth:dev-develop --prefer-source

Laravel 5.4 이하를 사용하는 경우 다음 명령을 실행하세요:

composer require tymon/jwt-auth

For Laravel For 5.5 이전 버전을 사용하는 애플리케이션의 경우 config/app.php 파일에서 서비스 공급자와 별칭도 설정해야 합니다.

'providers' => [
    ....
    Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class,
    ....
],
'aliases' => [
    ....
    'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
    'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory',
    ....
],

Laravel 버전이 5.5 이상인 경우 Laravel은 "패키지 자동 검색"을 수행합니다.

구성 파일 게시

Laravel 5.5 이상의 버전에서는 다음 명령을 사용하여 구성 파일을 게시하세요.

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

이전 버전의 Laravel에서는 다음 명령을 실행해야 합니다:

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

위 명령은 config/jwt.php 구성 파일을 생성합니다. 주석이 제거되면 구성 파일은 다음과 같습니다.

<?php
return [
    &#39;secret&#39; => env(&#39;JWT_SECRET&#39;),
    &#39;keys&#39; => [
        &#39;public&#39; => env(&#39;JWT_PUBLIC_KEY&#39;),
        &#39;private&#39; => env(&#39;JWT_PRIVATE_KEY&#39;),
        &#39;passphrase&#39; => env(&#39;JWT_PASSPHRASE&#39;),
    ],
    &#39;ttl&#39; => env(&#39;JWT_TTL&#39;, 60),
    &#39;refresh_ttl&#39; => env(&#39;JWT_REFRESH_TTL&#39;, 20160),
    &#39;algo&#39; => env(&#39;JWT_ALGO&#39;, &#39;HS256&#39;),
    &#39;required_claims&#39; => [
        &#39;iss&#39;,
        &#39;iat&#39;,
        &#39;exp&#39;,
        &#39;nbf&#39;,
        &#39;sub&#39;,
        &#39;jti&#39;,
    ],
    &#39;persistent_claims&#39; => [
        // &#39;foo&#39;,
        // &#39;bar&#39;,
    ],
    &#39;lock_subject&#39; => true,
    &#39;leeway&#39; => env(&#39;JWT_LEEWAY&#39;, 0),
    &#39;blacklist_enabled&#39; => env(&#39;JWT_BLACKLIST_ENABLED&#39;, true),
    &#39;blacklist_grace_period&#39; => env(&#39;JWT_BLACKLIST_GRACE_PERIOD&#39;, 0),
    &#39;decrypt_cookies&#39; => false,
    &#39;providers&#39; => [
        &#39;jwt&#39; => Tymon\JWTAuth\Providers\JWT\Lcobucci::class,
        &#39;auth&#39; => Tymon\JWTAuth\Providers\Auth\Illuminate::class,
        &#39;storage&#39; => Tymon\JWTAuth\Providers\Storage\Illuminate::class,
    ],
];

Generate JWT Key

JWT 토큰은 암호화된 키를 통해 발급됩니다. Laravel 5.5 이상에서는 다음 명령을 실행하여 토큰 발급을 위한 키를 생성합니다.

php artisan jwt:secret

Laravel 5.5 미만 버전 실행:

php artisan jwt:generate

이 튜토리얼에서는 Laravel 5.6을 사용합니다. 튜토리얼의 다음 단계는 5.5 및 5.6에서만 테스트되었습니다. Laravel 5.4 이하에서는 작동하지 않을 수 있습니다. 이전 버전의 Laravel에 대한 문서를 읽을 수 있습니다.

등록 미들웨어

JWT 인증 확장 프로그램에는 이를 사용할 수 있는 미들웨어가 함께 제공됩니다. app/Http/Kernel.php에 auth.jwt 미들웨어를 등록하세요.

protected $routeMiddleware = [
    ....
    &#39;auth.jwt&#39; => \Tymon\JWTAuth\Http\Middleware\Authenticate::class,
];

이 미들웨어는 요청에 첨부된 토큰을 확인하여 사용자 인증을 확인합니다. 사용자가 인증되지 않으면 이 미들웨어는 UnauthorizedHttpException 예외를 발생시킵니다.

라우팅 설정

시작하기 전에 이 튜토리얼에서 논의한 모든 지점에 대한 라우팅을 설정하겠습니다. Routes/api.php를 열고 다음 경로를 파일에 복사하십시오.

Route::post(&#39;login&#39;, &#39;ApiController@login&#39;);
Route::post(&#39;register&#39;, &#39;ApiController@register&#39;);
Route::group([&#39;middleware&#39; => &#39;auth.jwt&#39;], function () {
    Route::get(&#39;logout&#39;, &#39;ApiController@logout&#39;);
    Route::get(&#39;user&#39;, &#39;ApiController@getAuthUser&#39;);
    Route::get(&#39;products&#39;, &#39;ProductController@index&#39;);
    Route::get(&#39;products/{id}&#39;, &#39;ProductController@show&#39;);
    Route::post(&#39;products&#39;, &#39;ProductController@store&#39;);
    Route::put(&#39;products/{id}&#39;, &#39;ProductController@update&#39;);
    Route::delete(&#39;products/{id}&#39;, &#39;ProductController@destroy&#39;);
});

사용자 모델 업데이트

JWT는 사용자 모델에서 TymonJWTAuthContractsJWTSubject 인터페이스를 구현해야 합니다. 이 인터페이스는 getJWTIdentifier 및 getJWTCustomClaims 두 가지 메소드를 구현해야 합니다. 다음 내용으로 app/User.php를 업데이트하세요.

<?php
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 = [
        &#39;name&#39;, &#39;email&#39;, &#39;password&#39;,
    ];
    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        &#39;password&#39;, &#39;remember_token&#39;,
    ];
    /**
     * 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 [];
    }
}

JWT 인증 로직

JWT 인증을 이용하여 laravel에서 Restful API의 로직을 작성해 보겠습니다.

用户注册时需要姓名,邮箱和密码。那么,让我们创建一个表单请求来验证数据。通过运行以下命令创建名为 RegisterAuthRequest 的表单请求:

php artisan make:request RegisterAuthRequest

它将在 app/Http/Requests 目录下创建 RegisterAuthRequest.php 文件。将下面的代码黏贴至该文件中。

<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class RegisterAuthRequest extends FormRequest
{
    /**
     * 确定是否授权用户发出此请求
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }
    /**
     * 获取应用于请求的验证规则
     *
     * @return array
     */
    public function rules()
    {
        return [
            &#39;name&#39; => &#39;required|string&#39;,
            &#39;email&#39; => &#39;required|email|unique:users&#39;,
            &#39;password&#39; => &#39;required|string|min:6|max:10&#39;
        ];
    }
}

运行以下命令创建一个新的 ApiController :

php artisan make:controller ApiController

这将会在 app/Http/Controllers 目录下创建 ApiController.php 文件。将下面的代码黏贴至该文件中。

<?php
namespace App\Http\Controllers;
use App\Http\Requests\RegisterAuthRequest;
use App\User;
use Illuminate\Http\Request;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
class ApiController extends Controller
{
    public $loginAfterSignUp = true;
    public function register(RegisterAuthRequest $request)
    {
        $user = new User();
        $user->name = $request->name;
        $user->email = $request->email;
        $user->password = bcrypt($request->password);
        $user->save();
        if ($this->loginAfterSignUp) {
            return $this->login($request);
        }
        return response()->json([
            &#39;success&#39; => true,
            &#39;data&#39; => $user
        ], 200);
    }
    public function login(Request $request)
    {
        $input = $request->only(&#39;email&#39;, &#39;password&#39;);
        $jwt_token = null;
        if (!$jwt_token = JWTAuth::attempt($input)) {
            return response()->json([
                &#39;success&#39; => false,
                &#39;message&#39; => &#39;Invalid Email or Password&#39;,
            ], 401);
        }
        return response()->json([
            &#39;success&#39; => true,
            &#39;token&#39; => $jwt_token,
        ]);
    }
    public function logout(Request $request)
    {
        $this->validate($request, [
            &#39;token&#39; => &#39;required&#39;
        ]);
        try {
            JWTAuth::invalidate($request->token);
            return response()->json([
                &#39;success&#39; => true,
                &#39;message&#39; => &#39;User logged out successfully&#39;
            ]);
        } catch (JWTException $exception) {
            return response()->json([
                &#39;success&#39; => false,
                &#39;message&#39; => &#39;Sorry, the user cannot be logged out&#39;
            ], 500);
        }
    }
    public function getAuthUser(Request $request)
    {
        $this->validate($request, [
            &#39;token&#39; => &#39;required&#39;
        ]);
        $user = JWTAuth::authenticate($request->token);
        return response()->json([&#39;user&#39; => $user]);
    }
}

让我解释下上面的代码发生了什么。

在 register 方法中,我们接收了 RegisterAuthRequest 。使用请求中的数据创建用户。如果 loginAfterSignUp 属性为 true ,则注册后通过调用 login 方法为用户登录。否则,成功的响应则将伴随用户数据一起返回。

在 login 方法中,我们得到了请求的子集,其中只包含电子邮件和密码。以输入的值作为参数调用  JWTAuth::attempt() ,响应保存在一个变量中。如果从 attempt 方法中返回 false ,则返回一个失败响应。否则,将返回一个成功的响应。

在 logout 方法中,验证请求是否包含令牌验证。通过调用 invalidate 方法使令牌无效,并返回一个成功的响应。如果捕获到 JWTException 异常,则返回一个失败的响应。

在 getAuthUser 方法中,验证请求是否包含令牌字段。然后调用 authenticate 方法,该方法返回经过身份验证的用户。最后,返回带有用户的响应。

身份验证部分现在已经完成。

构建产品部分

要创建产品部分,我们需要 Product 模型,控制器和迁移文件。运行以下命令来创建 Product 模型,控制器和迁移文件。

php artisan make:model Product -mc

它会在 database/migrations 目录下创建一个新的数据库迁移文件 create_products_table.php,更改 up 方法。

public function up()
{
    Schema::create(&#39;products&#39;, function (Blueprint $table) {
        $table->increments(&#39;id&#39;);
        $table->integer(&#39;user_id&#39;);
        $table->string(&#39;name&#39;);
        $table->integer(&#39;price&#39;);
        $table->integer(&#39;quantity&#39;);
        $table->timestamps();
        $table->foreign(&#39;user_id&#39;)
            ->references(&#39;id&#39;)
            ->on(&#39;users&#39;)
            ->onDelete(&#39;cascade&#39;);
    });
}

向 Product 模型中添加 fillable 属性。在 app 目录下打开 Product.php 文件并添加属性。

protected $fillable = [
    &#39;name&#39;, &#39;price&#39;, &#39;quantity&#39;
];

现在在 .env 文件中设置数据库凭证,并通过运行以下命令迁移数据库。

php artisan migrate

现在,我们必须在 User 模型中添加一个关系来检索相关产品。在 app/User.php 中添加以下方法。

public function products()
{
    return $this->hasMany(Product::class);
}

在 app/Http/Controllers 目录下打开 ProductController.php 文件。在文件开头添加 use 指令覆盖上一个。

use App\Product;
use Illuminate\Http\Request;
use JWTAuth;

现在我们将实现五个方法。

index, 为经过身份认证的用户获取所有产品列表

show, 根据 ID 获取特定的产品

store, 将新产品存储到产品列表中

update, 根据 ID 更新产品详情

destroy, 根据 ID 从列表中删除产品

添加一个构造函数来获取经过身份认证的用户,并将其保存在 user 属性中。

protected $user;
public function __construct()
{
    $this->user = JWTAuth::parseToken()->authenticate();
}

parseToken 将解析来自请求的令牌, authenticate 通过令牌对用户进行身份验证。

让我们添加 index 方法。

public function index()
{
    return $this->user
        ->products()
        ->get([&#39;name&#39;, &#39;price&#39;, &#39;quantity&#39;])
        ->toArray();
}

上面的代码非常简单,我们只是使用 Eloquent 的方法获取所有的产品,然后将结果组成一个数组。最后,我们返回这个数组。Laravel 将自动将其转换为 JSON ,并创建一个为 200 成功的响应码。

继续实现 show 方法。

public function show($id)
{
    $product = $this->user->products()->find($id);
    if (!$product) {
        return response()->json([
            &#39;success&#39; => false,
            &#39;message&#39; => &#39;Sorry, product with id &#39; . $id . &#39; cannot be found&#39;
        ], 400);
    }
    return $product;
}

这个也非常容易理解。我们只需要根据 ID 找到该产品。如果产品不存在,则返回 400 故障响应。否则,将返回产品数组。

接下来是 store 方法

public function store(Request $request)
{
    $this->validate($request, [
        &#39;name&#39; => &#39;required&#39;,
        &#39;price&#39; => &#39;required|integer&#39;,
        &#39;quantity&#39; => &#39;required|integer&#39;
    ]);
    $product = new Product();
    $product->name = $request->name;
    $product->price = $request->price;
    $product->quantity = $request->quantity;
    if ($this->user->products()->save($product))
        return response()->json([
            &#39;success&#39; => true,
            &#39;product&#39; => $product
        ]);
    else
        return response()->json([
            &#39;success&#39; => false,
            &#39;message&#39; => &#39;Sorry, product could not be added&#39;
        ], 500);
}

在 store 方法中,验证请求中是否包含名称,价格和数量。然后,使用请求中的数据去创建一个新的产品模型。如果,产品成功的写入数据库,会返回成功响应,否则返回自定义的 500 失败响应。

实现 update 方法

public function update(Request $request, $id)
{
    $product = $this->user->products()->find($id);
    if (!$product) {
        return response()->json([
            &#39;success&#39; => false,
            &#39;message&#39; => &#39;Sorry, product with id &#39; . $id . &#39; cannot be found&#39;
        ], 400);
    }
    $updated = $product->fill($request->all())
        ->save();
    if ($updated) {
        return response()->json([
            &#39;success&#39; => true
        ]);
    } else {
        return response()->json([
            &#39;success&#39; => false,
            &#39;message&#39; => &#39;Sorry, product could not be updated&#39;
        ], 500);
    }
}

在 update 方法中,我们通过 id 取得产品。如果产品不存在,返回一个 400 响应。然后,我们把请求中的数据使用 fill 方法填充到产品详情。更新产品模型并保存到数据库,如果记录成功更新,返回一个 200 成功响应,否则返回 500 内部服务器错误响应给客户端。

现在,让我们实现 destroy 方法。

public function destroy($id)
{
    $product = $this->user->products()->find($id);
    if (!$product) {
        return response()->json([
            &#39;success&#39; => false,
            &#39;message&#39; => &#39;Sorry, product with id &#39; . $id . &#39; cannot be found&#39;
        ], 400);
    }
    if ($product->delete()) {
        return response()->json([
            &#39;success&#39; => true
        ]);
    } else {
        return response()->json([
            &#39;success&#39; => false,
            &#39;message&#39; => &#39;Product could not be deleted&#39;
        ], 500);
    }
}

在 destroy 方法中,我们根据 ID 获取产品,如果产品不存在,则返回 400 响应。然后我们删除产品后并根据删除操作的成功状态返回适当的响应。

控制器代码现在已经完成,完整的控制器代码在这。

测试

我们首先来测试身份认证。我们将使用 serve 命令在开发机上启动 Web 服务,你也可以使用虚拟主机代替。运行以下命令启动 Web 服务。

php artisan serve

它将监听 localhost:8000

为了测试 restful API's,我们使用 Postman。填写好请求体之后,我们请求一下 register 路由。

Laravel을 사용하여 JWT 인증을 통합하여 RestfulApi 개발

요청을 보내면 토큰을 받게 됩니다.

Laravel을 사용하여 JWT 인증을 통합하여 RestfulApi 개발

이제 사용자가 등록 및 인증되었습니다. 로그인 경로를 감지하기 위해 또 다른 요청을 보내면 200과 토큰이 반환됩니다.

Laravel을 사용하여 JWT 인증을 통합하여 RestfulApi 개발

사용자 세부정보 가져오기

Laravel을 사용하여 JWT 인증을 통합하여 RestfulApi 개발

테스트 신원 인증이 완료되었습니다. 다음으로 제품 부분을 테스트하고 먼저 제품을 만듭니다.

Laravel을 사용하여 JWT 인증을 통합하여 RestfulApi 개발

이제 인덱스 방식을 요청하여 제품을 받아보세요.

Laravel을 사용하여 JWT 인증을 통합하여 RestfulApi 개발

다른 경로를 테스트해 보면 모두 잘 작동할 것입니다.

추천 튜토리얼: "Laravel Tutorial"

위 내용은 Laravel을 사용하여 JWT 인증을 통합하여 RestfulApi 개발의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 learnku.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제