gpt4 book ai didi

php - 使用 League OAuth2 客户端的 Laravel Oauth2 Controller

转载 作者:行者123 更新时间:2023-12-04 04:11:47 25 4
gpt4 key购买 nike

我正在尝试使用 League OAuth2 Client允许用户验证我的 Laravel 网络应用程序以在他们的日历上设置约会。注意:我不是试图让用户登录我的网站或使用 OAuth 验证我的网站!我只是希望能够让用户将约会添加到他们自己的日历中。

我基本上遵循此处概述的流程:https://github.com/thephpleague/oauth2-google并创建了一个 Controller (称为 OauthController,使用一个方法 redirectGoogle。我的重定向路由(已在 Google 注册)是 https://example。 com/oauth2/google。当我在我的 Laravel 应用程序中点击此端点时,我被重定向到 Google 以批准我的应用程序按预期访问我的帐户数据,然后重定向回 Controller 端点。

但是每次都在 exit('Invalid state'); 行失败。

Controller 方法代码如下:

public function redirectGoogle(Request $request)
{
$provider = new Google([
'clientId' => config('oauth.google_oauth_id'),
'clientSecret' => config('oauth.google_oauth_secret'),
'redirectUri' => 'https://example.com/oauth2/google',
]);

if (!empty($request->input('error'))) {
// Got an error, probably user denied access
dd($request->input('error'));
} elseif (empty($request->input('code'))) {
// If we don't have an authorization code then get one
$authUrl = $provider->getAuthorizationUrl();
session(['oauth2state', $provider->getState()]);
Log::info('Storing provider state ' . session('oauth2state')); <-- Log entry exists so we know session value was written
header('Location: ' . $authUrl);
exit;
} elseif (empty($request->input('state')) || ($request->input('state') !== session('oauth2state', false))) {
Log::error($request->input('state') . ' did not equal stored value ' . session('oauth2state', false)); <-- Log entry exists
// State is invalid, possible CSRF attack in progress
exit('Invalid state'); <-- Breaks here
} else {
// Try to get an access token (using the authorization code grant)
$token = $provider->getAccessToken('authorization_code', [
'code' => $request->input('code')
]);

// Optional: Now you have a token you can look up a users profile data
try {
// We got an access token, let's now get the owner details
$ownerDetails = $provider->getResourceOwner($token);

// Use these details to create a new profile
dd('Hello %s!', $ownerDetails->getFirstName());

} catch (Exception $e) {
// Failed to get user details
dd('Something went wrong: ' . $e->getMessage());
}

// Use this to interact with an API on the users behalf
echo $token->getToken() . PHP_EOL;

// Use this to get a new access token if the old one expires
echo $token->getRefreshToken() . PHP_EOL;

// Unix timestamp at which the access token expires
echo $token->getExpires() . PHP_EOL;
dd();
}
}

奇怪的是,上面代码中记录的日志消息都存在,并且值匹配(至少,它试图用与第二个日志文件的值匹配的值写入第一个 session 变量):

[2020-05-04 21:02:48] local.INFO: Storing provider state 4963a33bbd5bcf52d3e21c787f24bd7b  
[2020-05-04 21:02:51] local.ERROR: 4963a33bbd5bcf52d3e21c787f24bd7b did not equal stored value <null>

为什么第二次通过代码oauth2state session value 是空的,当它在第一次循环中成功写入时?

注意:问题似乎是 session 不同,这是有道理的,但是这个 session 如何保持一致,或者以其他方式保持数据直接?

[2020-05-05 15:25:06] local.INFO: Session id: bV7F5mNM69rJAVJNWK9ZD0rcoN284FxXvjNAmUiw  
[2020-05-05 15:25:06] local.INFO: Storing provider state 7351b313b741df41a6be9a049f71db6b
[2020-05-05 15:25:10] local.INFO: Session id: VNiBxr1gYYIA9Nr11x9c4JJArHOiKQScEGh2jkuc
[2020-05-05 15:25:10] local.ERROR: 7351b313b741df41a6be9a049f71db6b did not equal stored value <null>

EDIT2:我试过教程 here它使用 Laravel 和 League Oauth 库使用略有不同的方法——它有完全相同的问题,两个请求之间的 session ID 不同,这意味着你永远无法在 state< 之间获得匹配 键。

最佳答案

我认为问题在于您如何重定向到 google。

问题:

Laravel 需要运行整个请求,以便将值持久化到 session 中。

通过使用 exit; 您将中断请求,因此 Laravel 将没有机会将值持久保存到 session 中。

解决方案:

按照 docs 中的建议使用 redirect() 助手, Laravel 将能够完成请求。

elseif(empty($request->input('code'))) {
// If we don't have an authorization code then get one
$authUrl = $provider->getAuthorizationUrl();
session(['oauth2state', $provider->getState()]);
Log::info('Storing provider state ' . session('oauth2state'));
return redirect($authUrl);
}

解释:

在 Laravel 中,您可以决定何时运行中间件,从 docs :

中间件前后

Whether a middleware runs before or after a request depends on the middleware itself. For example, the following middleware would perform some task before the request is handled by the application:

public function handle($request, Closure $next)
{
// Perform action

return $next($request);
}

However, this middleware would perform its task after the request is handled by the application:

public function handle($request, Closure $next)
{
$response = $next($request);

// Perform action

return $response;
}

现在,如果我们看一下 Laravel 如何在 StartSession middleware 中持久化 session 数据。 , 你可以看到 here Laravel 尝试在应用程序处理请求后将数据持久化到 session 中,因此通过使用 exit;die();dd( ); 你正在停止脚本,Laravel 永远不会有机会在 session 中保留值。

protected function handleStatefulRequest(Request $request, $session, Closure $next)
{
// Before middleware
$request->setLaravelSession(
$this->startSession($request, $session)
);

$this->collectGarbage($session);

$response = $next($request);

// After middleware
$this->storeCurrentUrl($request, $session);

$this->addCookieToResponse($response, $session);

$this->saveSession($request);

return $response;
}

关于php - 使用 League OAuth2 客户端的 Laravel Oauth2 Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61601733/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com