lumen+dingo api jwt认证不过

1. 运行环境

1). 当前使用的 lumen 版本?

8.0.3

2). 当前使用的 php/php-fpm 版本?

PHP 版本:7.4

3). 当前系统

windows11

4). 业务环境

开发环境

2. 问题描述

app.php注册了两个中间件

$app->routeMiddleware([

    //'permission' => Spatie\Permission\Middlewares\PermissionMiddleware::class,
    //'role'       => Spatie\Permission\Middlewares\RoleMiddleware::class,
    //'cors' => palanik\lumen\Middleware\LumenCors::class,
    'isadmin' => App\Http\Middleware\CheckIsAdminPlan::class,
    'isxiaomiadmin' => App\Http\Middleware\CheckIsAdminXiaomi::class,
    'plan.auth' => \App\Http\Middleware\PlanAuth::class,
    'xiaomi.auth' => \App\Http\Middleware\XiaomiAuth::class,
    'xiaomiadmin.auth' => \App\Http\Middleware\XiaomiAdminAuth::class,
    'auth' => App\Http\Middleware\Authenticate::class,
]);

然后 路由文件如下

$api->version('xiaomi', ['namespace' => 'App\Http\Controllers\xiaomi'], function ($api) {
    $api->group(["prefix" => 'xiaomi'], function ($api) {
        $api->post('/login', 'UserController@login'); //denglu
        $api->post('/admin_login', 'admin\UserController@login'); //denglu
        $api->group(['middleware' => ['auth:xiaomi']], function ($api) {
            $api->post('/xiaomi_index', 'IndexController@index'); // 附件列表
            $api->post('/xiaomi_me', 'UserController@me'); // 附件列表
            $api->post('/xiaomi_getuserroles', 'UserController@getUserRoles'); // 附件列表
        });
        $api->group(['middleware' => ['auth:xiaomiadmin']], function ($api) {
            $api->post('/xiaomi_admin_permissions_list_tree', 'admin\IndexController@getPermissionslist'); // 附件列表
            $api->post('/xiaomi_admin_permissions_set', 'admin\IndexController@setPermissions'); // 给用户组设置权限

            $api->post('/xiaomi_admin_user_list', 'admin\OpUserController@getlist'); // 附件列表
            $api->post('/xiaomi_admin_user_setroles', 'admin\OpUserController@setUserRoles'); // 附件列表
            $api->post('/xiaomi_admin_roles_list', 'admin\RolesController@getlist'); // 角色列表
            $api->post('/xiaomi_admin_roles_add', 'admin\RolesController@add'); // 新增角色
            $api->post('/xiaomi_admin_roles_getone', 'admin\RolesController@getone'); // 获取信息
            $api->post('/xiaomi_admin_roles_edit', 'admin\RolesController@edit'); // 获取信息

            $api->post('/xiaomi_admin_permissions_list', 'admin\PermissionsController@getlist'); // 角色列表
            $api->post('/xiaomi_admin_permissions_add', 'admin\PermissionsController@add'); // 新增角色
            $api->post('/xiaomi_admin_permissions_getone', 'admin\PermissionsController@getone'); // 获取信息
            $api->post('/xiaomi_admin_permissions_edit', 'admin\PermissionsController@edit'); // 获取信息
        });
    });
});

auth.php内容如下

<?php

return [

    'defaults' => [
        'guard' => env('AUTH_GUARD', 'api')
    ],

    'guards' => [
        'api'   =>  [
            'driver' => 'jwt',
            'provider' => 'users'
        ],
        'plan' => [
            'driver' => 'jwt',
            'provider' => 'baseuser',
        ],

        'xiaomi' => [
            'driver' => 'jwt',
            'provider' => 'opuser',
        ],
        'xiaomiadmin' => [
            'driver' => 'jwt',
            'provider' => 'restuser',
        ],
        'alerts' => [
            'driver' => 'jwt',
            'provider' => 'users',
        ],
    ],

    'providers' => [
        'users' => [
            'driver'    => 'eloquent',
            'model'     => \App\Models\User::class
        ],
        'baseuser' => [
            'driver'    => 'eloquent',
            'model'     => \App\Models\Plan\BaseUser::class
        ],
        'restuser' => [
            'driver'    => 'eloquent',
            'model'     => \App\Models\Xiaomi\RestUser::class
        ],
        'opuser' => [
            'driver'    => 'eloquent',
            'model'     => \App\Models\Xiaomi\OpUser::class
        ],
    ],

    'passwords' => [
        //
    ],

];

app\Http\Controllers\xiaomi\UserController.php 登录逻辑如下

 public function login(Request $request)
    {
        $message = [
            'user_id.required' => "用户名不能为空",
            'password.required' => "密码不能为空",
        ];

        $rules = [
            'user_id' => 'required',
            'password' => 'required',
        ];

        $validator = Validator::make($request->all(), $rules, $message);

        if ($validator->fails()) {
            // 获取所有的错误信息
            $errors = $validator->errors()->all();

            // 返回第一个错误信息
            return resp(Code::LoginFailed, $errors[0]);
        }

        $user_id = $request->input('user_id');
        $password = $request->input('password');
        $user = User::where('user_id', $user_id)->where('password', $password)->first();

        if (!$user) {
            return resp(Code::LoginFailed, '用户名或者密码错误');
        }

        //添加应用标识
        $customClaims = ['app_id' => 'xiaomi_app'];
        // 继续执行密码验证和登录逻辑
        if (!$token = auth('xiaomi')->claims($customClaims)->login($user)) {
            return resp(Code::LoginFailed, Msg::LoginFailed);
        }
        return resp(Code::LoginSuccess, Msg::LoginSuccess, $this->responseWithToken($token));
    }

应该是走到 xiaomiauth.php 内容如下

<?php

namespace App\Http\Middleware;

use Closure;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use App\Models\Xiaomi\OpUser as User;
use Illuminate\Support\Facades\Auth;

class XiaomiAuth extends BaseMiddleware
{
    public function handle($request, Closure $next)
    {
        // 检查请求中是否有 token
        if (!$token = $this->auth->setRequest($request)->getToken()) {
            return response()->json(['code' => 404, 'msg' => '缺少令牌'], 200);
        }
        //dd($this->auth->getPayload($token)->get('app_id'));
        if ($this->auth->getPayload($token)->get('app_id') !== 'xiaomi_app') {
            return response()->json(['code' => 404, 'msg' => '没有权限访问该应用'], 200);
        }

        try {
            $payload = $this->auth->getPayload($token);
            $user_id = $payload['sub']; // 'sub' 通常包含用户ID

            $user = User::find($user_id);

            if (!$user) {
                return response()->json(['code' => 404, 'msg' => '找不到用户'], 404);
            }
            Auth::guard('xiaomi')->setUser($user);
        } catch (TokenExpiredException $e) {
            return response()->json(['code' => 404, 'msg' => 'token过期'], 200);
        } catch (JWTException $e) {
            return response()->json(['code' => 404, 'msg' => 'token验证失败'], 200);
        }

        // 用户已认证,可以继续下一个请求
        return $next($request);
    }
}

这里认证中间件没有问题 但是就会走到

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Contracts\Auth\Factory as Auth;
use Illuminate\Support\Facades\Log;

class Authenticate
{
    /**
     * The authentication guard factory instance.
     *
     * @var \Illuminate\Contracts\Auth\Factory
     */
    protected $auth;

    /**
     * Create a new middleware instance.
     *
     * @param  \Illuminate\Contracts\Auth\Factory  $auth
     * @return void
     */
    public function __construct(Auth $auth)
    {
        $this->auth = $auth;
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  $guard
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        Log::info("Guard being used: " . ($guard ?: 'default'));
        Log::info("1");
        if ($this->auth->guard($guard)->guest()) {
            Log::info("2");
            Log::info("User is guest on guard: " . ($guard ?: 'default'));
            return response([
                'code' => 401,
                'msg' => '需要认证',
                'data' => null,
            ], 401);
        }

        return $next($request);
    }
}

提示未认证 头大了
//: <> (代码问题的话,请提供一份最短的,可复现问题的代码。或者相关代码)

3. 您期望得到的结果?

就是能正常多应用 分前后台能正常登录,,,可有偿
//: <> (能截图就截图。)

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 7

问题应该是这里:

// 继续执行密码验证和登录逻辑
if (!$token = auth('xiaomi')->claims($customClaims)->login($user)) {
    return resp(Code::LoginFailed, Msg::LoginFailed);
}
return resp(Code::LoginSuccess, Msg::LoginSuccess, $this->responseWithToken($token));

感觉是$user的问题,一般登录只会用到账号和密码,你这个$user肯定不止这两个信息,你看看
->claims($customClaims)->login()这个login()方法的参数是什么类型,里面有什么内容。

3周前 评论
sdphper (楼主) 3周前
她来听我的演唱会 (作者) 3周前

看了你的代码后,我觉得你可能对jwt和lumen框架用法不熟,建议多看看文档。

  1. jwt问题,先根据文档排查。
    Tymon Jwt Github
    Tymon Jwt Doc
  2. 路由鉴权中间件指定了auth中间件,没有指定小米鉴权中间件,理论上不会走小米鉴权中间件的,使用小米鉴权中间件应该这么写xiaomi.auth:xiaomi,如果按文档安装jwt,auth中间件验证会自动使用jwt鉴权中间件。
// 1.auth:xiaomiadmin 释义 冒号前是中间件别名,后面是参数。
// 对auth中间件来说,后面的参数为guard,中间件后面的用户业务代码,可以不需要指定guard,默认为auth后的guard.
 $api->group(['middleware' => ['auth:xiaomiadmin']], function ($api) {
    // ...
};
  1. jwt鉴权获取用户信息,如果用户model没有指定sub,默认存储的就是主键id,获取用户信息直接可以使用Auth::user()$request->user(),不需要手动读取sub,获取用户信息。
3周前 评论
sdphper (楼主) 3周前

auth.php 里默认的是guard 是api

 'defaults' => [
        'guard' => env('AUTH_GUARD', 'api')
    ],

Authenticate 里$grard 默认是 null 你打印的日志里应该也是用了Guard being used:default? $guard没传吧

public function handle($request, Closure $next, $guard = null)
    {
        Log::info("Guard being used: " . ($guard ?: 'default'));
        Log::info("1");
        if ($this->auth->guard($guard)->guest()) {
            Log::info("2");
            Log::info("User is guest on guard: " . ($guard ?: 'default'));
            return response([
                'code' => 401,
                'msg' => '需要认证',
                'data' => null,
            ], 401);
        }

        return $next($request);
    }
4天前 评论

如果弄不好久看看dingo的文档,文档里推荐了tymon/jwt-auth 进行jwt验证,按照那个来,就可以

4天前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!