本文概述
- 要求
- 1.安装并启用HWIOAuthBundle
- 2.在社交网络上创建开发者帐户
- 3.配置HWIO和资源所有者
- 4.配置资源所有者路由
- 5.创建登录和注册管理器
- 6.创建fos_user.oauth_provider服务
- 7.测试!
今天, 很多人都遭受着著名的”密码疲劳”的折磨, 甚至可能是你。网站的访问者一直在寻找一种做事的简单方法, 当我们谈论登录网站时, 社交登录是最好的选择, 因为用户可以使用他们现有的社交帐户, 例如Facebook, Google +, Twitter等。这种优势可以通过改善用户体验来提高你网站上的转化次数。许多网站报告说, 其目标消费者更喜欢使用社交登录, 而不是在其网站上创建新帐户, 这是有充分理由的。对于Symfony项目, HWIOAuthBundle是实现此任务的最著名和最佳解决方案。
在本文中, 你将学习如何允许你的用户使用社交网络登录到你的应用程序。尽管你可以用任何方式配置任何社交网络, 但在这种情况下, 我们将通过Github, Facebook, Google Plus和Stack Exchange进行说明。
注意
如果要添加其他社交网络(如Twitter等), 则可以遵循相同的过程。或者, 如果你不需要示例中的社交网络, 则跳过该步骤。
要求
在继续之前, 你需要为要添加的每个社交网络(资源所有者)在数据库的fos_user表中创建2个字符串类型(Varchar 255)类型的列。我们将这一步骤作为一项要求, 因为你是决定如何将字段添加到数据库的人。一些开发人员使用诸如PHPMyAdmin之类的管理器来处理数据库, 或者通过修改user.orm.yml文件, 然后使用php bin / console doctrine:schema:update –force来构建数据库, 从而遵循symfony的方式。
每个资源所有者的2个字段均遵循下一个命名法:<社交网络名称> _id和<社交网络名称> _access_token。例如, 对于我们提到的4个社交网络, 在fos_user表中将有8个新列, 即:
github_id
github_access_token
facebook
facebook_access_token
googleplus_id
googleplus_access_token
stackexchange_id
stackexchange_access_token
一旦这些列存在, 你显然需要在应用程序的User类中添加该字段的getter和setter:
/** @ORM\Column(name="github_id", type="string", length=255, nullable=true) */
protected $github_id;
/** @ORM\Column(name="github_access_token", type="string", length=255, nullable=true) */
protected $github_access_token;
/** @ORM\Column(name="facebook_id", type="string", length=255, nullable=true) */
protected $facebook_id;
/** @ORM\Column(name="facebook_access_token", type="string", length=255, nullable=true) */
protected $facebook_access_token;
/** @ORM\Column(name="googleplus_id", type="string", length=255, nullable=true) */
protected $googleplus_id;
/** @ORM\Column(name="googleplus_access_token", type="string", length=255, nullable=true) */
protected $googleplus_access_token;
/** @ORM\Column(name="stackexchange_id", type="string", length=255, nullable=true) */
protected $stackexchange_id;
/** @ORM\Column(name="stackexchange_access_token", type="string", length=255, nullable=true) */
protected $stackexchange_access_token;
public function setGithubId($githubId) {
$this->github_id = $githubId;
return $this;
}
public function getGithubId() {
return $this->github_id;
}
public function setGithubAccessToken($githubAccessToken) {
$this->github_access_token = $githubAccessToken;
return $this;
}
public function getGithubAccessToken() {
return $this->github_access_token;
}
public function setFacebookId($facebookID) {
$this->facebook_id = $facebookID;
return $this;
}
public function getFacebookId() {
return $this->facebook_id;
}
public function setFacebookAccessToken($facebookAccessToken) {
$this->facebook_access_token = $facebookAccessToken;
return $this;
}
public function getFacebookAccessToken() {
return $this->facebook_access_token;
}
public function setGoogleplusId($googlePlusId) {
$this->googleplus_id = $googlePlusId;
return $this;
}
public function getGoogleplusId() {
return $this->googleplus_id;
}
public function setGoogleplusAccessToken($googleplusAccessToken) {
$this->googleplus_access_token = $googleplusAccessToken;
return $this;
}
public function getGoogleplusAccessToken() {
return $this->googleplus_access_token;
}
public function setStackexchangeId($stackExchangeId) {
$this->stackexchange_id = $stackExchangeId;
return $this;
}
public function getStackexchangeId() {
return $this->stackexchange_id;
}
public function setStackexchangeAccessToken($stackExchangeAccessToken) {
$this->stackexchange_access_token = $stackExchangeAccessToken;
return $this;
}
public function getStackexchangeAccessToken() {
return $this->stackexchange_access_token;
}
如果按顺序设置了所有内容, 则可以从User对象检索这些属性, 然后可以继续配置HWIOAuthBundle。
注意
请记住, 在修改用户类时, 你需要清除当前用户的缓存并注销, 否则当你添加新字段时, 直到用户再次登录后, 它们才会更新。
1.安装并启用HWIOAuthBundle
首先, 你需要使用以下命令通过composer安装HWIOAuthBundle:
composer require hwi/oauth-bundle
另外, 你可以手动修改composer.json并将捆绑包设置为依赖项:
{
"require": {
"hwi/oauth-bundle": "^0.5.3", }
}
最后使用composer install进行安装。捆绑软件安装完成后, 请不要忘记在symfony应用程序的AppKernel.php文件中启用它:
<?php
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = [
// ..
new HWI\Bundle\OAuthBundle\HWIOAuthBundle(), // ..
];
// ..
}
}
2.在社交网络上创建开发者帐户
允许用户使用社交网络登录应用程序的最重要一点是, 第三方服务(社交网络)也允许你执行此操作。为此, 大多数服务都需要注册你的应用程序才能管理请求权限等。
例如, 对于Github, 你可以在这里注册你的应用程序, 在这里注册Facebook, 在这里注册Stack Exchange, 在这里注册Google Plus。注册你的应用程序后, 他们将为你提供所需的OAuth令牌, 这些令牌将使你可以向其服务器创建请求。 Github管理器看起来像:
注意
除了自定义应用程序的设置外, 你还需要提供我们将在步骤4中定义的授权回调URL。因此, 使用此选项将你的应用程序创建为空, 并且在完成本教程后不要忘记对其进行更新。
在这种情况下, URL将遵循https:// yourwebsite / connect / check- <resource-owner-name>之类的模式。但是, 在遵循本教程的过程中, 你可以自由更改回调URL。
几乎所有的资源所有者都有至少两个参数, 即client_id和secret。在此示例中, 我们将使用前面提到的4个社交网络, 因此我们需要在app / config / config.yml文件中注册以下参数。建议你也将令牌存储在双引号中, 例如”在此处输入你的令牌”:
# app/config/config.yml
parameters:
# For Github you'll need the client_id and secret
github_client_id: <replace-with-your-github-client-id>
github_secret: <replace-with-your-github-secret>
# For Facebook you'll need the client_id and secret
facebook_client_id: <replace-with-your-facebook-client-id>
facebook_secret: <replace-with-your-facebook-secret>
# For Google+ you'll need the client_id and secret
googleplus_client_id: <replace-with-your-googleplus-client-id>
googleplus_secret: <replace-with-your-googleplus-secret>
# For Stack Exchange you'll need the client_id, secret and key
stackexchange_client_id: <replace-with-your-stackexchange-client-id>
stackexchange_secret: <replace-with-your-stackexchange-secret>
stackexchange_key: <replace-with-your-stackexchange-key>
这些令牌将由资源所有者在下一步中使用。
3.配置HWIO和资源所有者
既然你有权创建对所需社交网络服务器的请求, 则需要创建每个社交网络的本地资源所有者。转到Symfony应用程序的config.yml文件, 然后设置HWIOAuthBundle的配置(hwi_oauth)。在这里, 你可以使用各自的访问令牌注册新的社交网络:
# app/config/config.yml
hwi_oauth:
# Define which firewalls will be used for oauth
# Usually, its only the main, but you can add it if you have a custom one
firewall_names: ["main"]
fosub:
username_iterations: 30
# Define in which columns of the fos_user table will be stored
# the access token of every resource_owner
properties:
github: github_id
facebook: facebook_id
googleplus: googleplus_id
stackexchange: stackexchange_id
# Define the resource_owners that your user can use to login into your app
# Note that the client_id and client_secret and key values are symfony parameters
# stored too in the config.yml from the previous step !
resource_owners:
github:
type: github
client_id: "%github_client_id%"
client_secret: "%github_secret%"
scope: 'user:email, public_repo'
facebook:
type: facebook
client_id: "%facebook_client_id%"
client_secret: "%facebook_secret%"
infos_url: "https://graph.facebook.com/me?fields=id, name, email"
googleplus:
type: google
client_id: "%googleplus_client_id%"
client_secret: "%googleplus_secret%"
scope: "email profile"
stackexchange:
type: stack_exchange
client_id: "%stackexchange_client_id%"
client_secret: "%stackexchange_secret%"
options:
key: "%stackexchange_key%"
有关每个资源所有者的配置如何工作的更多信息, 请在此处参考HWIOAuthBundle的官方文档。
4.配置资源所有者路由
你的用户将需要访问标识他要登录的社交网络的路由。转到应用程序的app / config / security.yml文件, 并为防火墙添加oauth配置:
# app/config/security.yml
security:
# Modify firewalls
firewalls:
# Set the config on your firewall
main:
oauth:
# Declare the OAuth Callback URLs for every resource owner
# They will be added in the routing.yml file too later
resource_owners:
github: "/connect/check-github"
facebook: "/connect/check-facebook"
googleplus: "/connect/check-googleplus"
stackexchange: "/connect/check-stackexchange"
## Provide the original login path of your application (fosuserroute)
## and the failure route when the authentication fails.
login_path: /user/login
failure_path: /user/login
# Inject a service that will be created in the step #6
oauth_user_provider:
service: app.fos_user.oauth_provider
接下来, 继续将HWIOBundle和资源所有者的路由添加到你的app / config / routing.yml文件中:
注意
如第2步所述, 在Facebook, Github等应用程序的OAuth帐户管理器中, 你需要提供OAuth回调URL。你可以使用此步骤的路由来提供到第三方服务的路由, 例如http://yoursite.com/connect/check-facebook。
# app/config/routing.yml
hwi_oauth_redirect:
resource: "@HWIOAuthBundle/Resources/config/routing/redirect.xml"
prefix: /connect
hwi_oauth_connect:
resource: "@HWIOAuthBundle/Resources/config/routing/connect.xml"
prefix: /connect
hwi_oauth_login:
resource: "@HWIOAuthBundle/Resources/config/routing/login.xml"
prefix: /login
github_login:
path: /connect/check-github
facebook_login:
path: /connect/check-facebook
googleplus_login:
path: /connect/check-googleplus
stackexchange_login:
path: /connect/check-stackexchange
这样, 如果用户想使用其Facebook帐户登录到你的应用程序, 则只需要将其重定向到http://yoursite.com/connect/check-facebook路由。
5.创建登录和注册管理器
在某种程度上, 你的应用程序需要从社交网络接收信息以进行注册或登录。这就是下面的FOSUBUserProvider类的功能。默认情况下, 它不需要任何修改即可工作。用户访问检查路由后, loadUserByOAuthUserResponse函数将生效。如果用户未在你的应用程序上的社交网络帐户中注册, 则默认情况下, 它将在fos_user表上使用随机用户名(例如12345_ <name-of-social-network>)创建新行并自动对其进行签名。如果用户已经存在, 它将通过<social-network> _id字段搜索用户, 并将发送访问令牌以检索信息。
你可以随意修改类以设置所需的字段, 设置所需的用户名等。在这种情况下, 我们将类存储在AppBundle的Entity文件夹中, 但你可以将其保存在任何位置:
<?php
// Change the namespace according to your project.
namespace AppBundle\Entity;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider as BaseClass;
use Symfony\Component\Security\Core\User\UserInterface;
// Source: https://gist.github.com/danvbe/4476697
class FOSUBUserProvider extends BaseClass {
public function connect(UserInterface $user, UserResponseInterface $response) {
$property = $this->getProperty($response);
$username = $response->getUsername();
// On connect, retrieve the access token and the user id
$service = $response->getResourceOwner()->getName();
$setter = 'set' . ucfirst($service);
$setter_id = $setter . 'Id';
$setter_token = $setter . 'AccessToken';
// Disconnect previously connected users
if (null !== $previousUser = $this->userManager->findUserBy(array($property => $username))) {
$previousUser->$setter_id(null);
$previousUser->$setter_token(null);
$this->userManager->updateUser($previousUser);
}
// Connect using the current user
$user->$setter_id($username);
$user->$setter_token($response->getAccessToken());
$this->userManager->updateUser($user);
}
public function loadUserByOAuthUserResponse(UserResponseInterface $response) {
$data = $response->getResponse();
$username = $response->getUsername();
$email = $response->getEmail() ? $response->getEmail() : $username;
$user = $this->userManager->findUserBy(array($this->getProperty($response) => $username));
// If the user is new
if (null === $user) {
$service = $response->getResourceOwner()->getName();
$setter = 'set' . ucfirst($service);
$setter_id = $setter . 'Id';
$setter_token = $setter . 'AccessToken';
// create new user here
$user = $this->userManager->createUser();
$user->$setter_id($username);
$user->$setter_token($response->getAccessToken());
//I have set all requested data with the user's username
//modify here with relevant data
$user->setUsername($this->generateRandomUsername($username, $response->getResourceOwner()->getName()));
$user->setEmail($email);
$user->setPassword($username);
$user->setEnabled(true);
$this->userManager->updateUser($user);
return $user;
}
// If the user exists, use the HWIOAuth
$user = parent::loadUserByOAuthUserResponse($response);
$serviceName = $response->getResourceOwner()->getName();
$setter = 'set' . ucfirst($serviceName) . 'AccessToken';
// Update the access token
$user->$setter($response->getAccessToken());
return $user;
}
/**
* Generates a random username with the given
* e.g 12345_github, 12345_facebook
*
* @param string $username
* @param type $serviceName
* @return type
*/
private function generateRandomUsername($username, $serviceName){
if(!$username){
$username = "user". uniqid((rand()), true) . $serviceName;
}
return $username. "_" . $serviceName;
}
}
6.创建fos_user.oauth_provider服务
在security.yml中, 我们使用app.fos_user.oauth_provider服务定义了oauth_user_provider选项, 该选项到现在还不存在, 因此你需要创建它。该服务返回FOSUBUserProvider类, 并将FOSUserBundle的用户管理器和在步骤3中创建的资源所有者作为参数:
# app/config/services.yml
services:
app.fos_user.oauth_provider:
# Change the class according to the location of the FOSUBUserProvider class
class: AppBundle\Entity\FOSUBUserProvider
arguments:
# Inject as first argument the user_manager of FOSUserBundle
user_manager: "@fos_user.user_manager"
# An object/array with the registered Social Media from config.yml
user_response:
github: github_id
facebook: facebook_id
googleplus: googleplus_id
stackexchange: stackexchange_id
7.测试!
如果一切均已正确配置(并遵循默认配置), 则可以通过社交网络访问(登录或注册)以下路径:
<!-- Remove app_dev.php from the URL if you aren't in DEV mode -->
<a href="/app_dev.php/connect/github">
Login with Github
</a>
<a href="/app_dev.php/connect/stackexchange">
Login with Stack Exchange
</a>
<a href="/app_dev.php/connect/facebook">
Login with Facebook
</a>
<a href="/app_dev.php/connect/googleplus">
Login with Google+
</a>
在这里, 用户将被重定向到”社交网络”授予页面, 该页面询问用户是否真的要使用其帐户登录另一个应用程序。值得一提的是, 你需要清除缓存并从当前帐户注销, 以防止出现任何错误。
编码愉快!
评论前必须登录!
注册