laravel 11 使用jw-auth进行API 登录
首先安装
composer require tymon/jwt-auth
默认安装后我的版本是2.1
"require": {"php": "^8.2",...."tymon/jwt-auth": "^2.1"},
发布包配置文件
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
生成密钥
php artisan jwt:secret
env 中会生成这段代码
JWT_SECRET=fW87rUsPjEy0UoE0J9CYbk44mBskdyPQrLehLDVRL3pUA4nq4umf8aoaoC6ugy55
AUTH_GUARD = api
AUTH_PASSWORD_BROKER = users
开始
首先更新user 模型
<?phpnamespace App\Models;// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;class User extends Authenticatable implements JWTSubject
{use HasFactory, Notifiable;/*** The attributes that are mass assignable.** @var array<int, string>*/protected $fillable = ['name','email','password',];/*** The attributes that should be hidden for serialization.** @var array<int, string>*/protected $hidden = ['password','remember_token',];/*** Get the attributes that should be cast.** @return array<string, string>*/protected function casts(): array{return ['email_verified_at' => 'datetime','password' => 'hashed',];}// Rest omitted for brevity/*** 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 [];}}
在 config/auth.php
文件中修改配置
..... 'guards' => ['web' => ['driver' => 'session','provider' => 'users',],'api' => ['driver' => 'jwt','provider' => 'users',],],
...
在API路由中添加认证
Route::post('/auth/login', [App\Http\Controllers\Apis\AuthController::class,'login'])->name('login');Route::group(['middleware' => 'auth:api'], function()
{Route::post('/auth/logout', [App\Http\Controllers\Apis\AuthController::class,'logout']);Route::post('/auth/refresh', [App\Http\Controllers\Apis\AuthController::class,'refresh']);Route::any('/auth/me', [App\Http\Controllers\Apis\AuthController::class,'me']);
});
创建AuthController.php
<?php
namespace App\Http\Controllers\Apis;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use DB;
use Auth;class AuthController extends Controller
{public function __construct(){// $this->middleware('auth:api', ['except' => ['login']]);}public function login(Request $request){$credentials = $request->only('email', 'password');if ($token = $this->guard()->attempt($credentials)) {return $this->respondWithToken($token);}return response()->json(['error' => 'Unauthorized'], 401);}/*** Get the authenticated User** @return \Illuminate\Http\JsonResponse*/public function me(){return response()->json($this->guard()->user());}/*** Log the user out (Invalidate the token)** @return \Illuminate\Http\JsonResponse*/public function logout(){$this->guard()->logout();return response()->json(['message' => 'Successfully logged out']);}/*** Refresh a token.** @return \Illuminate\Http\JsonResponse*/public function refresh(){return $this->respondWithToken($this->guard()->refresh());}/*** Get the token array structure.** @param string $token** @return \Illuminate\Http\JsonResponse*/protected function respondWithToken($token){return response()->json(['code'=>100,'data'=>['access_token' => $token,'token_type' => 'bearer','expires_in' => $this->guard()->factory()->getTTL() * 60]]);}/*** Get the guard to be used during authentication.** @return \Illuminate\Contracts\Auth\Guard*/public function guard(){return Auth::guard();}}
Login 页面
<style scoped>.login-box{width: 100%;padding-top: 100px;}.Loginform{width: 50%;margin: auto;}
</style><template><div class="login-box"><h1 style="text-align: center;">喵~登录</h1><el-form class="Loginform" :model="form" label-width="auto" style="max-width: 600px"><el-form-item label="邮箱"><el-input v-model="form.email" /></el-form-item><el-form-item label="密码"><el-input type="password" v-model="form.password" ></el-input></el-form-item><el-form-item style="text-align: -webkit-center"><div style="width: 100%; text-align: center;"><el-button class="submit-btn" type="primary" @click="submitForm" style="justify-content: center;">登录</el-button></div></el-form-item></el-form></div>
</template><script lang="ts" setup>
import { ref,computed,onMounted } from 'vue';
import { Login } from '../apis/api';
import { useAuthStore } from '@/stores/auth';
import router from '../router'// import { AuthToken } from '../interfaces/Auth'const form = ref({email: '',password: ''})const submitForm = () => {let Loginform = {"email":form.value.email,"password":form.value.password};Login(Loginform).then(function(res:any){if(res.access_token && res.expires_in && res.token_type=='bearer'){const authStore = useAuthStore();authStore.login(true,res.access_token)router.push('/admin/home');}})};onMounted(() => {// GetCsrfToken().then(function(res:any){// form.value.csrfToken = res.csrf_token// })})</script>
api.ts
import {post,get} from './https'export const Login = (params:any) => post('/auth/login',params)
原理是,当用户登录客户端之后,后台会返回一段字符串给客户端,客户端之后的每一步操作都会通过字符串访问后台,判断其字符串是否已经登录,所以需要在客户端的路由中编写监听器,不过这是后话!