我只是设法解决这个问题。具体方法如下:
在同一控制器作为getAuthenticatedUser()
和authenticate()
方法驻留,我把令牌刷新方法:
public function refresh(Request $request)
{
try {
$current_token = $request->get('token');
//$current_token = JWTAuth::getToken();
if(!$current_token) return response()->json(null);
$token = JWTAuth::refresh($current_token);
return response()->json(compact('token'));
} catch (JWTException $e) {
if ($e instanceof TokenExpiredException) {
return response()->json(['token_expired'], $e->getStatusCode());
} else if ($e instanceof TokenBlacklistedException) {
return response()->json(['token_blacklisted'], $e->getStatusCode());
} else if ($e instanceof TokenInvalidException) {
return response()->json(['token_invalid'], $e->getStatusCode());
} else if ($e instanceof PayloadException) {
return response()->json(['token_expired'], $e->getStatusCode());
} else if ($e instanceof JWTException) {
return response()->json(['token_invalid'], $e->getStatusCode());
}
}
}
以及相应的路线:
Route::post('authenticate', '[email protected]');
Route::post('refresh', '[email protected]'); // The new route.
现在,因为我们”重新使用AngularJS作为我们的前端和所有的HTTP请求,我们正在确定令牌是否已经过期。不知道这是否适用于您的项目,但也许您可以使用逻辑原理。
如果您的前端没有使用AngularJS,并且对我们在AngularJS中构建的前端逻辑不感兴趣,则可以立即停止阅读。
在我们的主AngularJS文件,app.js
,在这里我们使用UI-Router
基于状态的路由(和jwtHelper-library
):
app.run(function($rootScope, $state jwtHelper, AuthFactory) {
// Checks if the token has expired on every view change.
$rootScope.$on('$stateChangeStart', function(e, to) {
if (to.data.requiresLogin && jwtHelper.isTokenExpired(store.get('token')) {
AuthFactory.attemptRefreshToken();
}
});
});
// We use a http interceptor to listen for the Token Expired-exception
// coming from the backend (Laravel 5.1 and JWTAuth) on any http calls performed.
app.config(function ($httpProvider) {
$httpProvider.interceptors.push('httpInterceptor');
});
// The actual interceptor.
app.factory('httpInterceptor', function ($q, store, $injector) {
return {
// On every request that returns an error, check if the status code is
// 401 ('unauthorized'), which means the token has expired.
responseError: function(response) {
if (response.status == 401){
var AuthFactory = $injector.get('AuthFactory');
// Pass the attempted response config in order to retry the request after the refresh.
return AuthFactory.attemptRefreshToken(response.config);
}
}
};
});
最后但并非最不重要的,我们的实际刷新调用存储在我们的AuthFactory文件:
attemptRefreshToken: function(requestTodoWhenDone){
var token = store.get('token');
return $http({
method: 'POST',
skipAuthorization: true,
url: ApiEndpoint.url + 'refresh',
data: {token: token}
})
.success(function(response)
{
// Set the refreshed token.
store.set('token', response.token);
})
.then(function(){
// Attempt to retry the request if request config is passed.
if(!angular.isUndefined(requestTodoWhenDone) && requestTodoWhenDone.length > 0)
{
// Set the new token for the authorization header.
requestTodoWhenDone.headers = {
'Authorization': 'Bearer ' + store.get('token')
};
// Run the request again.
return $http(requestTodoWhenDone);
}
});
});
它的实际工作,但我在我的新令牌被列入黑名单的问题,我有几乎相同的设置,你有我只是用satellizer来发送令牌,我把它们存储在localStorage的。 –
对,我们很快就注意到了这一点。我在回答后做了以下事情: - 为了让Angular能够检测到令牌是否列入黑名单,我们不得不将黑名单标记作为后端的例外。 - 由于我不熟悉的一些错误,我们也将HTTP请求从工厂移到了主app.js。 - 我们发送令牌作为请求参数,而不是使用JWT的内置身份验证。 查看我的更新回答。 – Mattias