Laravel 5 Socialite - 动态更改身份验证重定向路径
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29127330/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel 5 Socialite - change auth redirect path dynamically
提问by NightMICU
I am trying to incorporate Socialite into a site and have come across a problem with what should be a rather trivial thing to do - change where the user is redirected after authenticated by a social provider.
我正在尝试将 Socialite 合并到一个网站中,但遇到了一个问题,应该做的是一件相当微不足道的事情 - 在通过社交提供商进行身份验证后更改用户重定向的位置。
I have three actions that I will be using Socialite for:
我将使用 Socialite 执行三个操作:
- Register- Authenticate with the provider and then redirect to the Registration Form. Their name and email address are filled in for them, more fields are required.
- Login- Typical login scenario, the provider information is checked against the Users table and they are logged in if there is a match
- Link- User already has an active account but would like to link an external (Faceebook or Google) account. This authenticates the user and adds the proper social media ID to their row in the Users table. The problem is that you specify the authentication redirect in the services.php file, I cannot figure out how to change where the user is redirected after successfully authenticating with the third party provider.
- 注册- 向提供商进行身份验证,然后重定向到注册表。为他们填写了他们的姓名和电子邮件地址,需要更多字段。
- 登录- 典型的登录场景,根据用户表检查提供者信息,如果匹配则登录
- 链接- 用户已经有一个活动帐户,但想要链接一个外部(Faceebook 或 Google)帐户。这将验证用户并将正确的社交媒体 ID 添加到用户表中的行中。问题是您在 services.php 文件中指定了身份验证重定向,我无法弄清楚在与第三方提供商成功进行身份验证后如何更改用户重定向的位置。
Here is what I have so far -
这是我到目前为止所拥有的 -
Route: This seems to work up to when the social provider redirects, because driver=facebook&action=login
(for example) is missing. Ideally, I'd like to specify where the user is redirected when the initial auth request is made - this was just my first attempt at figuring this out.
路线:这似乎在社交提供者重定向时起作用,因为driver=facebook&action=login
(例如)丢失了。理想情况下,我想指定在发出初始身份验证请求时将用户重定向到何处 - 这只是我第一次尝试解决这个问题。
get('social-auth', function(AuthenticateUser $authenticateUser, Request $request) {
$driver = $request->input('driver');
$action = $request->input('action');
return $authenticateUser->execute($request->has('code'), $driver, $action);
});
AuthenticateUser class - Hopefully the comments here are sufficient:
AuthenticateUser 类 - 希望这里的评论足够了:
<?php namespace App;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Laravel\Socialite\Contracts\Factory as Socialite;
use Auth;
use Flash;
class AuthenticateUser
{
/**
* @var Socialite
*/
private $socialite;
/**
* @var Auth
*/
private $auth;
public function __construct(Socialite $socialite, Auth $auth)
{
$this->socialite = $socialite;
$this->auth = $auth;
}
/**
* @param boolean $hasCode Whether or not we have been authenticated already
* @param string $driver Driver to use, Facebook or Google
* @param string $type Type of call - Login, Register, or Link
* @return array|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function execute($hasCode, $driver, $type)
{
if (!$hasCode) {
return $this->getAuthorizationFirst($driver);
}
// Get the User details from the Social Provider
$socialUser = $this->socialite->driver($driver)->user();
$socialUserArray = $socialUser->user;
if ($driver == 'facebook') {
// Get Facebook specific fields
$first_name = $socialUserArray['first_name'];
$last_name = $socialUserArray['last_name'];
} else if ($driver == 'google') {
// Get Google specific fields
$first_name = $socialUserArray['name']['givenName'];
$last_name = $socialUserArray['name']['familyName'];
}
$email = $socialUser->email;
$id = $socialUser->id;
// Perform an action - login, register, or link
switch ($type) {
case 'login':
// Log the user in with the Facebook ID
try {
if ($driver == 'facebook') {
$user = User::whereFacebookAuth($id)->firstOrFail();
} else {
$user = User::whereGoogleAuth($id);
}
} catch (ModelNotFoundException $e) {
flash::error('Could not find a user associated with this ' . ucfirst($driver) . ' account.');
return redirect('auth/login');
}
Auth::login($user);
return redirect('members');
break;
case 'register':
// Register using social media account
return redirect('register')
->with('social_type', $driver)
->with('social_id', $id)
->with('email', $email)
->with('first_name', $first_name)
->with('last_name', $last_name);
break;
case 'link':
// Associate this Social Media account with the current User
$driver == 'facebook' ? Auth::user()->facebook_auth = $id : Auth::user()->google_auth = $id;
Auth::user()->save();
return ['status' => 'success'];
break;
}
}
/**
* Authorize the user before proceeding
* @param $driver
* @return mixed
*/
private function getAuthorizationFirst($driver)
{
return $this->socialite->with($driver)->redirect('hopefully-somewhere-else');
// Anything inside redirect doesn't seem to do anything
}
}
回答by Martin Bean
I tend to include the provider in my URLs. For example:
我倾向于在我的 URL 中包含提供者。例如:
Route::get('auth/{provider}', 'AuthController@redirectToProvider');
Route::get('auth/{provider}/callback', 'AuthController@handleProviderCallback');
That way I can access the provider name from the request in my controller actions:
这样我就可以在我的控制器操作中从请求中访问提供者名称:
public function callback($provider)
{
$user = $this->socialite->driver($provider)->getUser();
try {
// Try and find user by their social profile UID
$appUser = SocialAccount::whereUid($user->getId())
->whereProvider($provider)
->firstOrFail();
Auth::loginUsingId($appUser->user_id);
} catch (ModelNotFoundException $e) {
if (Auth::user()) {
// Attach social profile to logged in user
} else {
// User is not logged in, and account does not exist
// Prompt to register
}
}
}