Laravel 为什么与jwt auth的会话时间是从登录时算起的1小时?
在Laravel7后端RESTAPI应用程序中,我使用jwt auth,我在登录时遇到了一个问题 我可以在前端部分工作,但在1小时内我得到了令牌_过期错误 1) 我试图将会议时间设置得更大,但失败了。在开发阶段,我需要一个多小时的会话时间。 继续现场直播,我将设置会议时间30分钟 2) 我预计,从登录用户的最后一个请求到后端的会话时间是1小时,但不是从登录开始 我在下面实现了刷新方法,但看起来刷新不起作用 app/Http/Controllers/API/AuthController.php:Laravel 为什么与jwt auth的会话时间是从登录时算起的1小时?,laravel,jwt-auth,Laravel,Jwt Auth,在Laravel7后端RESTAPI应用程序中,我使用jwt auth,我在登录时遇到了一个问题 我可以在前端部分工作,但在1小时内我得到了令牌_过期错误 1) 我试图将会议时间设置得更大,但失败了。在开发阶段,我需要一个多小时的会话时间。 继续现场直播,我将设置会议时间30分钟 2) 我预计,从登录用户的最后一个请求到后端的会话时间是1小时,但不是从登录开始 我在下面实现了刷新方法,但看起来刷新不起作用 app/Http/Controllers/API/AuthController.php:
<?php
namespace App\Http\Controllers\API;
use App\library\CheckValueType;
use App\Settings;
use Auth;
use Config;
use DB;
use Validator;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Support\Str;
use App\UserGroup;
use App\Http\Resources\UserCollection;
use Avatar;
use Storage;
class AuthController extends Controller
{
/**
* Create a new AuthController instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('jwt.auth', ['except' => ['login', 'register', 'activate']]);
}
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if ($token = $this->guard('api')->attempt($credentials)) {
$loggedUser = $this->guard('api')->user();
if ($loggedUser->status != 'A') {
return response()->json(['error' => 'Unauthorized'], HTTP_RESPONSE_NOT_UNAUTHORIZED);
}
$loggedUser->last_logged = Carbon::now(config('app.timezone'));
$loggedUser->save();
$userGroupsCount = UserGroup
::getByUserId($loggedUser->id)
->count();
if ($userGroupsCount == 0) {
return response()->json(['error' => 'Unauthorized'], HTTP_RESPONSE_NOT_UNAUTHORIZED);
}
return $this->respondWithToken($token);
}
return response()->json(['error' => 'Unauthorized'], HTTP_RESPONSE_NOT_UNAUTHORIZED);
}
public function me()
{
return response()->json($this->guard('api')->user());
}
public function logout()
{
$this->guard('api')->logout();
return response()->json(['message' => 'Successfully logged out']);
}
public function refresh()
{
return $this->respondWithToken($this->guard()->refresh());
}
protected function respondWithToken($token)
{
$loggedUser = $this->guard()->user();
$user_avatar_path = 'public/' . User::getUserAvatarPath($loggedUser->id, $loggedUser->avatar);
$filenameData = User::setUserAvatarProps($loggedUser->id, $loggedUser->avatar, true);
$usersGroups = User::getUserGroupByUserId($loggedUser->id, false);
return response()->json([
'access_token' => $token,
'user' => $loggedUser,
'token_type' => 'bearer',
'user_avatar_path' => $user_avatar_path,
'filenameData' => $filenameData,
'usersGroups' => $usersGroups,
'expires_in' => $this->guard('api')->factory()->getTTL() * 999360 // I SET VERY BIG VALUE
]);
}
public function guard()
{
return \Auth::Guard('api');
}
我有:
"laravel/framework": "^7.0",
"tymon/jwt-auth": "^1.0.0",
我的配置有什么问题
已修改:
我添加了一个文件
app/Http/Middleware/JwtMiddleware.php,包含内容和一行错误日志:
<?php
namespace App\Http\Middleware;
use Closure;
use Tymon\JWTAuth\Exceptions\JWTException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
class JwtMiddleware extends BaseMiddleware
{
public function handle($request, Closure $next)
{
try {
if (! $user = $this->auth->parseToken()->authenticate()) {
return response()->json(['success' => false, 'error' => __('Invalid User.')]);
}
} catch (TokenExpiredException $e) {
try {
$refreshed = $this->auth->refresh($this->auth->getToken());
$user = $this->auth->setToken($refreshed)->toUser();
header('Authorization: Bearer ' . $refreshed);
} catch (JWTException $e) {
return response()->json(['success' => false, 'error' => __('Could not generate refresh token')]);
}
} catch (JWTException $e) {
\Log::info( '-1 JwtMiddleware$e->getMessage() ::' . print_r( $e->getMessage(), true ) );
return response()->json(['success' => false, 'error' => __('Invalid request')]);
}
return $next($request);
}
}
它可能与app/Http/Controllers/API/AuthController.php的代码有冲突吗?
怎么能修好呢
已修改#2:
谢谢我修复了错误,并在.env中添加了行:
JWT_TTL=20 # 20 minutes
JWT_REFRESH_TTL=20160 # 2 weeks
清除缓存,我再次登录,结果在应用程序中工作时,我这样做了
没有注销任何20分钟,但当我离开应用程序打开,没有使用它
如我所料,在大约30分钟的时间里,我可以在没有日志的情况下继续工作。
还有其他选择吗
已修改#3:
在我的vuejs文件的客户端部分,我喜欢在src/App.vue中设置一个请求拦截器:
created() {
let self = this
this.$http.interceptors.response.use(undefined, function (error) {
return new Promise(function (/*resolve, reject*/) {
if (typeof error.response.status !== 'undefined' && error.response.status === 401) {
self.$store.dispatch('logout') // DEBUGGING
self.showPopupMessage('Access', 'Not authorized !', 'warn')
let splitted0 = self.getSplitted(error.response.config.url, '/login', 0)
if (splitted0 == '') { // not move from login page
self.$router.push('/login') // DEBUGGING
}
}
if (typeof error.response.status !== 'undefined') {
if (error.response.status === 401) {
self.$store.dispatch('logout') // DEBUGGING
self.showPopupMessage('Access', 'Not authorized !', 'warn')
self.$router.push('/login') // DEBUGGING
}
}
throw error
})
})
}, // created() {
我发现了其中的401错误,并想知道是否有可能捕获来自服务器的请求
header('Authorization: Bearer ' . $refreshed);
以及从$refreshed写入新的访问令牌值?
但是我怎么能抓住它呢?但是一些特殊的退货要求代码
谢谢 - 您需要添加中间件并检查令牌是否过期
- 如果过期,请检查生成时间,以检查是否应生成新令牌。将此视为刷新令牌过期时间。如果要在不进行任何时间验证的情况下生成刷新令牌,可以跳过此步骤
- 现在,如果一切正常,则生成一个新的令牌,并根据需要将其发送到标头/正文中,并将其存储在前端应用程序中
- 您需要添加中间件并检查令牌是否过期
- 如果过期,请检查生成时间,以检查是否应生成新令牌。将此视为刷新令牌过期时间。如果要在不进行任何时间验证的情况下生成刷新令牌,可以跳过此步骤
- 现在,如果一切正常,则生成一个新的令牌,并根据需要将其发送到标头/正文中,并将其存储在前端应用程序中
在登录时尝试此操作
if ($token = $this->guard('api')->attempt($credentials,['exp' => Carbon\Carbon::now()->addHours(2)->timestamp])) {
}
或者您可以在config/jwt
如果有帮助,请告诉我 在登录时尝试此操作
if ($token = $this->guard('api')->attempt($credentials,['exp' => Carbon\Carbon::now()->addHours(2)->timestamp])) {
}
或者您可以在config/jwt
如果有帮助,请告诉我 转到-->config/jwt.php
你可以这样做
'ttl' => env('JWT_TTL', 1440)
或在控制器中
$token = JWTAuth::attempt($credentials, ['exp' => Carbon\Carbon::now()->addDays(7)->timestamp]);
或
或
转到-->config/jwt.php
你可以这样做
'ttl' => env('JWT_TTL', 1440)
或在控制器中
$token = JWTAuth::attempt($credentials, ['exp' => Carbon\Carbon::now()->addDays(7)->timestamp]);
或
或
您应该有一个config/jwt.php
文件。如果还没有,请运行:
php artisan供应商:publish--provider=“Tymon\JWTAuth\Providers\LaravelServiceProvider”
在该文件中,您可以看到引用.env
变量的几个属性,它们是:
- ‘ttl’(环境=‘JWT_ttl’)
- '刷新\u ttl'(env='JWT\u刷新\u ttl')
另外,您可能希望将'refresh'
添加到jwt.auth
中间件异常列表中,因为在控制器中调用refresh()
函数时,它将不起作用
但是,在这个软件包中有一些重要的东西需要注意:
身份验证TTL链接在一起
我相信您几乎可以忽略ttl
属性,因为它是refresh\u ttl
,根据这个类比,它实际上定义了JWT的有效期:
锁匠(认证提供者)给你一把红色钥匙(JWT)。该键允许您打开红门(使用后端)。5分钟(TTL=5分钟)后,钥匙自动对折。但是,您可以带着损坏的钥匙回到锁匠那里,锁匠将在2周内更换钥匙(刷新TTL=2w)
您基本上可以使用过期的JWT调用auth/refresh
端点,它将刷新端点,直到刷新TTL过期
另请参见[github上的这个问题][1],这也解释了为什么需要添加refresh
函数,使其前面没有jwt.auth
中间件
使用此包提供的JWT时,您不会保存任何DB调用
我最初的想法是,它可以节省到数据库的往返时间,因为用户对象将在JWT中签名并准备就绪
我现在已经在几个项目中使用了这个包,我得出的结论是,它有点像一个美化的会话cookie。在tymon/jwt
中,sub
声明仅等于1
(或此处引用的任何用户ID)
这意味着你需要
- 。。。(默认)让
tymon/jwt
做一些简单的工作,从数据库中检索用户并将其应用到您的身份验证提供者,这样auth::user()
等就可以工作了
或
- 。。。使用完整用户对象添加声明,并在不同位置修改此包。这可以节省DB调用,因为此对象将是JWT的一部分,并在JWT中签名。它会导致在每次请求时发送更多的JWT字节,但您基本上可以将给定对象视为理所当然(即,在接收时接受它)并使用它。然后还可以通过这种方式添加权限/角色,这样就不需要从数据库中检索这些权限/角色。这个设置确实意味着在更改数据库中的任何权限时,您必须等待刷新新的JWT才能看到这些更改
$token = JWTAuth::attempt($credentials, ['exp' => Carbon\Carbon::now()->addDays(7)->timestamp]);
config()->set('jwt.ttl', 60*60*7);
Config::set('jwt.ttl', 60*60*7);
// ...
'ttl' => env('JWT_TTL', 3600)
php artisan config:clear