laravel 使用dingo 和 jwt 管理员和用户使用不同的表进行验证
简单说,就是两张不同功能的用户表,使用不同的guard守卫。[PS:获取到的token是通用的,也就是说,任何一个角色拿着这个token都可以验证通过,所以如果需要不同权限的话,需要将token和用户关联起来,比如在生成token的时候,token信息存入user表,比如叫做last_token]
核心配置 ./config/auth.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
'defaults' => [ 'guard' => 'web', //经测试不用改 'passwords' => 'users', ], 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'jwt', 'provider' => 'users', 'hash' => false, ], //管理员或者其他的用户,尽量不要用admin做键。 'super' => [ 'driver' => 'jwt', 'provider' => 'admins', 'hash' => false, ], ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\FrontCustomer::class, //对应的api用户模型 ], 'admins' => [ 'driver' => 'eloquent', 'model' => App\Models\AdminUser::class, //对应的管理员模型,laravel-admin需要自己生成一个 ], ], |
核心配置:./routes/api.php,里面旧的配置删除,用下面的内容根据自己的实际情况替换。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
/* Laravel 路由缓存执行 php artisan route:cache 后,Dingo 报错该版本未注册路由 Dingo/api 的路由信息实际应该是单独的命令去进行缓存,也就是清理api路由缓存用php artisan api:cache */ $api = app('Dingo\Api\Routing\Router'); $api->version('v1',['namespace' => 'App\Http\Controllers\Api','middleware'=>['xss']], function ($api) { //namespace声明路由组的命名空间,因为设置了"prefix"=>"api",所以以下路由都要加一个api前缀, //比如请求/api/users_list才能访问到用户列表接口 //guest不需要验证的 #测试 $api->get("guest", 'RestFulController@guestTest')->name("getsite"); //登录 $api->post('user/login', 'AuthController@login'); //登录授权 //登录 $api->post('admin/login', 'AuthController@adminLogin'); //登录授权 //注销 $api->post('user/logout', 'AuthController@logout'); //注销授权 //注销 $api->post('admin/logout', 'AuthController@adminLogout'); //注销授权 //需要api验证的 refresh.token是自动刷新token的中间件 $api->group(['middleware'=>['refresh.token','jwt.auth']], function ($api) { #测试 $api->get("user", 'RestFulController@userTest')->name("usertest"); $api->get("admin", 'RestFulController@adminTest')->name("admintest"); }); }); |
生成验证基本控制器:php artisan make:controller Api\BaseController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?php namespace App\Http\Controllers\Api; use Dingo\Api\Routing\Helpers; use App\Http\Controllers\Controller; class BaseController extends Controller { use Helpers; /** * 快速响应一个json格式的字符串 * @param string $message 详细信息 * @param array $data 响应的数据 * @param int $responseCode 响应状态码 * @return mixed */ public function jsonResponse(string $message = '', array $data = [], int $responseCode = 200) { return $this->response->array([ 'message' => $message, 'data' => $data, 'status_code' => $responseCode ]); } } |
生成验证控制器【不同表验证在这里,代码随便写的,只看关键即可】:php artisan make:controller Api\AuthController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
<?php namespace App\Http\Controllers\Api; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class AuthController extends BaseController { public function __construct() { //路由中的公用中间件也可以放这里,也可以放config\api.php中 //$this->middleware(['中间件1', '中间件2'], ['except' => ['login']]); } public function login(Request $request) { $this->validate($request, [ 'user_name' => 'required|max:255', 'password' => 'required', ]); try { //验证用户是否存在,存在则颁发token,不存在,则不颁发token。 if (! $token = auth('api')->attempt($request->only('user_name', 'password'))) { return response()->json(['用户不存在或者密码错误'], 404); } } catch (\TokenExpiredException $e) { //登录的时候,不可能存在token过期的。 return response()->json(['token_expired'], 500); } catch (\TokenInvalidException $e) { return response()->json(['token_invalid'], 500); } catch (\JWTException $e) { return response()->json(['token_absent' => $e->getMessage()], 500); } $data = [ 'user'=>auth('api')->user(), 'token'=>$token ]; return $this->jsonResponse('验证成功',$data); } public function AdminLogin(Request $request) { $this->validate($request, [ 'username' => 'required|max:255', 'password' => 'required', ]); try { //验证用户是否存在,存在则颁发token,不存在,则不颁发token。 if (! $token = auth('super')->attempt($request->only('username', 'password'))) { return response()->json(['用户不存在或者密码错误'], 404); } } catch (\TokenExpiredException $e) { return response()->json(['token_expired'], 500); } catch (\TokenInvalidException $e) { return response()->json(['token_invalid'], 500); } catch (\JWTException $e) { return response()->json(['token_absent' => $e->getMessage()], 500); } $data = [ 'user'=>auth('super')->user(), 'token'=>$token ]; return $this->jsonResponse('验证成功',$data); } public function logout() { auth('api')->logout(); return response()->json(['status' => 200, 'message' => 'Exit successfully']); } public function adminLogout() { auth('super')->logout(); return response()->json(['status' => 200, 'message' => 'Exit successfully']); } } |
生成测试控制器(如果讲究一点,可以生成在Api\V1目录下):php artisan make:controller Api\RestFulController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<?php namespace App\Http\Controllers\Api; use Illuminate\Http\Request; use App\Models\FrontSite; class RestFulController extends BaseController { //需要登录验证的 public function userTest(Request $request){ $site = FrontSite::all()->toArray(); return $this->jsonResponse('站点信息',$site); //return $this->response->array(['data'=>$site,'status_code'=>"200"]); } public function guestTest(Request $request){ $site = FrontSite::all()->toArray(); return $this->jsonResponse('site_info',$site); //return $this->response->array(['data'=>$site,'status_code'=>"200"]); } public function adminTest(Request $request){ $site = FrontSite::all()->toArray(); return $this->jsonResponse('SiteInfo',$site); //return $this->response->array(['data'=>$site,'status_code'=>"200"]); } } |
生成中间件(用于防止xss攻击):php artisan make:middleware XSSProtection
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?php /* * 防止xss攻击 */ namespace App\Http\Middleware; use Closure; class XSSProtection { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { //如果不是puut 和 post,直接跳过xss。 if (!in_array(strtolower($request->method()), ['put', 'post'])) { return $next($request); } $input = $request->all(); array_walk_recursive($input, function (&$input) { $input = strip_tags($input); }); $request->merge($input); return $next($request); } } |
xss中间件取别名:./config/app.php 中aliases 项添加
1 |
'xss' => App\Http\Middleware\XSSProtection::class, //config\api.php中使用 |
xss生效:./config/api.php 中middleware 项添加
1 2 3 |
'middleware' => [ 'xss', ], |
数据库表【用于用户验证的表】修改,我只post一张管理用户表的,另外一张表自行修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
<?php namespace App\Models; use Encore\Admin\Traits\DefaultDatetimeFormat; use Tymon\JWTAuth\Contracts\JWTSubject; //*这里是新增 use Illuminate\Notifications\Notifiable; //*这里是新增 use Illuminate\Foundation\Auth\User as Authenticatable; //*这里是修改 class AdminUser extends Authenticatable implements JWTSubject //*这里是修改 { //JWT use Notifiable; //*这里是新增 //格式化日期显示 use DefaultDatetimeFormat; //指定表名 因为表名带s protected $table = 'admin_users'; protected $fillable = []; protected $guarded = [ 'remember_token' ]; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; //实现 JWTSubject接口 新增 两个函数 /** * 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 []; } } |
噢!评论已关闭。