使用UserApp.io在Symfony2中进行用户身份验证

tech2022-09-01  109

UserApp.io is a handy user management tool and API. It provides a web interface to deal with user accounts (and the many features this involves) and an API to hook them into your own web application. The purpose of this service is to make it easier and safer to manage user authentication by not having to worry about that on your own server.

UserApp.io是一个方便的用户管理工具和API。 它提供了一个用于处理用户帐户(以及其中涉及的许多功能)的Web界面,以及一个将其连接到您自己的Web应用程序中的API。 此服务的目的是不必担心您自己的服务器上的身份验证,从而使管理用户身份验证的过程变得更加轻松安全。

It has SDKs and various wrappers for many programming languages and frameworks and the price is affordable. Yes, it comes with a price but you can get started freely with quite a lot of things to play around with. I recommend checking out their features page to get more information. Also, it’s very easy to create an account and experiment with creating users, adding properties to their profiles, etc, so I recommend you check that out as well if you haven’t already.

它具有用于许多编程语言和框架的SDK和各种包装,并且价格适中。 是的,它带有价格,但是您可以免费开始使用很多东西。 我建议查看其功能页面以获取更多信息。 另外,创建帐户并尝试创建用户,向其个人资料添加属性等非常容易,因此,如果您还没有的话,我建议您也进行检查。

In this article, we are going to look at how we can implement a Symfony2 authentication mechanism that leverages UserApp.io. The code we write can also be found in this small library I created (currently in dev) that you can try out. To install it in your Symfony app, just follow the instructions on GitHub.

在本文中,我们将研究如何实现利用UserApp.io的Symfony2身份验证机制。 我们编写的代码也可以在我创建的这个小型库 (当前在dev中)中找到,您可以尝试一下。 要将其安装在您的Symfony应用中,只需按照GitHub上的说明进行操作即可。

依存关系 (Dependecies)

In order to communicate with the UserApp.io service, we will make use of their PHP library. Make sure you require this in your Symfony application’s composer.json file as instructed on their GitHub page.

为了与UserApp.io服务进行通信,我们将使用其PHP库 。 确保按照其GitHub页面上的说明,在Symfony应用程序的composer.json文件中对此有要求。

认证类 (The authentication classes)

To authenticate UserApp.io users with our Symfony app, we’ll create a few classes:

要使用我们的Symfony应用对UserApp.io用户进行身份验证,我们将创建一些类:

A form authenticator class used to perform the authentication with the UserApp.io API

表单身份验证器类,用于通过UserApp.io API执行身份验证 A custom User class used to represent our users with information gathered from the API

自定义User类,用于通过API收集的信息代表我们的用户 A user provider class used to retrieve users and transform them into objects of our User class

用户提供程序类,用于检索用户并将其转换为我们的User类的对象 A Token class used to represent the Symfony authentication token

用于表示Symfony身份验证令牌的Token类 A logout handler class that takes care of logging out from the UserApp.io service.

一个注销处理程序类,负责从UserApp.io服务注销。 A simple exception class that we can throw if the UserApp.io users don’t have any permissions set (that we will convert to Symfony roles)

如果UserApp.io用户没有设置任何权限,我们可以抛出一个简单的异常类(我们将转换为Symfony角色)

Once we create these classes, we will declare some of them as services and use them within the Symfony security system.

创建这些类后,我们将其中一些声明为服务,并在Symfony安全系统中使用它们。

表格验证器 (Form authenticator)

First, we will create the most important class, the form authenticator (inside a Security/ folder of our best practice named AppBundle). Here is the code, I will explain it afterwards:

首先,我们将创建最重要的类,即表单身份验证器(在我们的最佳实践的Security/文件夹中,名为AppBundle )。 这是代码,我将在后面解释:

<?php /** * @file AppBundle\Security\UserAppAuthenticator.php */ namespace AppBundle\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Authentication\SimpleFormAuthenticatorInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\User\UserProviderInterface; use UserApp\API as UserApp; use UserApp\Exceptions\ServiceException; class UserAppAuthenticator implements SimpleFormAuthenticatorInterface { /** * @var UserApp */ private $userAppClient; public function __construct(UserApp $userAppClient) { $this->userAppClient = $userAppClient; } /** * {@inheritdoc} */ public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey) { try { $login = $this->userAppClient->user->login(array( "login" => $token->getUsername(), "password" => $token->getCredentials(), ) ); // Load user from provider based on id $user = $userProvider->loadUserByLoginInfo($login); } catch(ServiceException $exception) { if ($exception->getErrorCode() == 'INVALID_ARGUMENT_LOGIN' || $exception->getErrorCode() == 'INVALID_ARGUMENT_PASSWORD') { throw new AuthenticationException('Invalid username or password'); } if ($exception->getErrorCode() == 'INVALID_ARGUMENT_APP_ID') { throw new AuthenticationException('Invalid app ID'); } } return new UserAppToken( $user, $user->getToken(), $providerKey, $user->getRoles() ); } /** * {@inheritdoc} */ public function supportsToken(TokenInterface $token, $providerKey) { return $token instanceof UserAppToken && $token->getProviderKey() === $providerKey; } /** * {@inheritdoc} */ public function createToken(Request $request, $username, $password, $providerKey) { return new UserAppToken($username, $password, $providerKey); } }

As you can see, we are implementing the SimpleFormAuthenticatorInterface and consequently have 3 methods and a constructor. The latter takes a dependency as the instantiated UserApp.io client (passed using the service container, but more on this in a minute).

如您所见,我们正在实现SimpleFormAuthenticatorInterface ,因此有3个方法和一个构造函数。 后者将依赖项作为实例化的UserApp.io客户端(使用服务容器进行了传递,但稍后会介绍更多内容)。

This class is used by Symfony when a user tries to login and authenticate with the application. The first thing that happens is that createToken() is called. This method needs to return an authentication token which combines the submitted username and password. In our case, it will be an instance of the UserAppToken class we will define in a moment.

当用户尝试登录应用程序并对其进行身份验证时,Symfony将使用此类。 发生的第一件事是调用createToken() 。 此方法需要返回一个身份验证令牌,其中包含提交的用户名和密码。 在我们的例子中,它将是我们稍后定义的UserAppToken类的实例。

Then the supportToken() method is called to check if this class does support the token returned by createToken(). Here we just make sure we return true for our token type.

然后调用supportToken()方法以检查此类是否支持createToken()返回的令牌。 在这里,我们只是确保我们为令牌类型返回true。

Finally, authenticateToken() gets called and attempts to check whether the credentials in the token are valid. In here, and using the UserApp.io PHP library, we try to log in or throw a Symfony authentication exception if this fails. If the authentication is successful though, the responsible user provider is used to build up our user object, before creating and returning another token object based on the latter.

最后,被调用authenticateToken()并尝试检查令牌中的凭证是否有效。 在这里,使用UserApp.io PHP库,我们尝试登录或抛出Symfony身份验证异常(如果失败)。 但是,如果身份验证成功,则在创建并返回基于后者的另一个令牌对象之前,将使用负责任的用户提供程序来构建我们的用户对象。

We will write our user provider right after we quickly create the simple UserAppToken class.

快速创建简单的UserAppToken类之后,我们将立即编写用户提供程序。

代币类 (Token class)

<?php /** * @file AppBundle\Security\UserAppToken.php */ namespace AppBundle\Security; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; class UserAppToken extends UsernamePasswordToken { }

As you can see, this is just an extension of the UsernamePasswordToken class for the sake of naming being more accurate (since we are storing a token instead of a password).

如您所见,这只是UsernamePasswordToken类的扩展,以便命名更准确(因为我们存储的是令牌而不是密码)。

用户提供者 (User provider)

Next, let’s see how the authenticator works with the user provider, so it’s time to create the latter as well:

接下来,让我们看看身份验证器如何与用户提供程序一起使用,因此也该创建后者了:

<?php /** * @file AppBundle\Security\UserAppProvider.php */ namespace AppBundle\Security; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use UserApp\API as UserApp; use UserApp\Exceptions\ServiceException; use AppBundle\Security\Exception\NoUserRoleException; use AppBundle\Security\UserAppUser; class UserAppProvider implements UserProviderInterface { /** * @var UserApp */ private $userAppClient; public function __construct(UserApp $userAppClient) { $this->userAppClient = $userAppClient; } /** * {@inheritdoc} */ public function loadUserByUsername($username) { // Empty for now } /** * {@inheritdoc} */ public function refreshUser(UserInterface $user) { if (!$user instanceof UserAppUser) { throw new UnsupportedUserException( sprintf('Instances of "%s" are not supported.', get_class($user)) ); } try { $api = $this->userAppClient; $api->setOption('token', $user->getToken()); $api->token->heartbeat(); $user->unlock(); } catch (ServiceException $exception) { if ($exception->getErrorCode() == 'INVALID_CREDENTIALS') { throw new AuthenticationException('Invalid credentials'); } if ($exception->getErrorCode() == 'AUTHORIZATION_USER_LOCKED') { $user->lock(); } } return $user; } /** * {@inheritdoc} */ public function supportsClass($class) { return $class === 'AppBundle\Security\UserAppUser'; } /** * * Loads a user from UserApp.io based on a successful login response. * * @param $login * @return UserAppUser * @throws NoUserRoleException */ public function loadUserByLoginInfo($login) { try { $api = $this->userAppClient; $api->setOption('token', $login->token); $users = $api->user->get(); } catch(ServiceException $exception) { if ($exception->getErrorCode() == 'INVALID_ARGUMENT_USER_ID') { throw new UsernameNotFoundException(sprintf('User with the id "%s" not found.', $login->user_id)); } } if (!empty($users)) { return $this->userFromUserApp($users[0], $login->token); } } /** * Creates a UserAppUser from a user response from UserApp.io * * @param $user * @param $token * @return UserAppUser * @throws NoUserRoleException */ private function userFromUserApp($user, $token) { $roles = $this->extractRolesFromPermissions($user); $options = array( 'id' => $user->user_id, 'username' => $user->login, 'token' => $token, 'firstName' => $user->first_name, 'lastName' => $user->last_name, 'email' => $user->email, 'roles' => $roles, 'properties' => $user->properties, 'features' => $user->features, 'permissions' => $user->permissions, 'created' => $user->created_at, 'locked' => !empty($user->locks), 'last_logged_in' => $user->last_login_at, 'last_heartbeat' => time(), ); return new UserAppUser($options); } /** * Extracts the roles from the permissions list of a user * * @param $user * @return array * @throws NoUserRoleException */ private function extractRolesFromPermissions($user) { $permissions = get_object_vars($user->permissions); if (empty($permissions)) { throw new NoUserRoleException('There are no roles set up for your users.'); } $roles = array(); foreach ($permissions as $role => $permission) { if ($permission->value === TRUE) { $roles[] = $role; } } if (empty($roles)) { throw new NoUserRoleException('This user has no roles enabled.'); } return $roles; } }

Similar to the form authenticator class, we inject the UserApp.io client into this class using dependency injection and we implement the UserProviderInterface. The latter requires we have 3 methods:

与表单身份验证器类相似,我们使用依赖项注入将UserApp.io客户端注入此类,并实现UserProviderInterface 。 后者要求我们有3种方法:

loadUserByUsername() – which we leave empty for now as we don’t need it

loadUserByUsername() –我们暂时将其保留为空,因为我们不需要它

refreshUser() – which gets called on each authenticated request

refreshUser() –在每个经过身份验证的请求上调用

supportsClass() – which determines whether this user provider works with our (yet to be created) User class.

supportsClass() –确定此用户提供程序是否与我们(尚未创建)用户类一起使用。

Let’s turn back a second to our authenticator class and see what exactly happens when authentication with UserApp.io is successful: we call the custom loadUserByLoginInfo() method on the user provider class which takes a successful login result object from the API and uses its authentication token to request back from the API the logged-in user object. The result gets wrapped into our own local UserAppUser class via the userFromUserApp() and extractRolesFromPermissions() helper methods. The latter is my own implementation of a way to translate the concept of permissions in UserApp.io into roles in Symfony. And we throw our own NoUserRoleException if the UserApp.io is not set up with permissions for the users. So make sure that your users in UserApp.io have permissions that you want to map to roles in Symfony.

让我们再回到身份验证器类,看看使用UserApp.io成功进行身份验证时会发生什么:我们在用户提供程序类上调用自定义loadUserByLoginInfo()方法,该方法从API获取成功的登录结果对象并使用其身份验证令牌以从API请求返回已登录的用户对象。 结果通过userFromUserApp()和userFromUserApp() extractRolesFromPermissions()帮助器方法包装到我们自己的本地UserAppUser类中。 后者是我自己的实现,该方法将UserApp.io中的permissions概念转换为Symfony中的roles 。 如果没有为用户设置UserApp.io的权限,我们将抛出自己的NoUserRoleException 。 因此,请确保UserApp.io中的用户具有要映射到Symfony中的角色的权限。

The exception class is a simple extension from the default PHP \Exception:

异常类是默认PHP \Exception的简单扩展:

<?php /** * @file AppBundle\Security\Exception\NoUserRoleException.php */ namespace AppBundle\Security\Exception; class NoUserRoleException extends \Exception { }

Back to our authenticator again, we see that if the authentication with UserApp.io is successful, a UserAppUser classed object is built by the user provider containing all the necessary info on the user. Having this object, we need to add it to a new instance of the UserAppToken class and return it.

再次回到我们的身份验证器,我们可以看到,如果通过UserApp.io的身份验证成功,则用户提供程序将构建一个UserAppUser对象,其中包含有关用户的所有必要信息。 有了这个对象,我们需要将其添加到UserAppToken类的新实例并返回它。

So basically this happens from the moment a user tries to log in:

因此,基本上这是从用户尝试登录的那一刻起发生的:

we create a token with the submitted credentials (createToken())

我们使用提交的凭据创建令牌( createToken() )

we try to authenticate the credentials in this token and throw an authentication exception if we fail

我们尝试验证此令牌中的凭据,如果失败则抛出身份验证异常 we create a new token containing the user object and some other information if authentication is successful

如果身份验证成功,我们将创建一个包含用户对象和其他信息的新令牌 we return this token which Symfony will then use to store the user in the session.

我们返回此令牌,Symfony随后将使用该令牌将用户存储在会话中。

The refreshUser() method on the user provider is also very important. This method is responsible for retrieving a new instance of the currently logged in user on each authenticated page refresh. So whenever the authenticated user goes to any of the pages inside the firewall, this method gets triggered. The point is to hydrate the user object with any changes in the storage that might have happened in the meantime.

用户提供者上的refreshUser()方法也非常重要。 此方法负责在每次经过身份验证的页面刷新时检索当前登录用户的新实例。 因此,每当通过身份验证的用户访问防火墙内的任何页面时,都会触发此方法。 这样做的目的是使用户对象与存储中同时发生的任何变化保持一致。

Obviously we need to keep API calls to a minimum but this is a good opportunity to increase the authentication time of UserApp.io by sending a heartbeat request. By default (but configurable), each authenticated user token is valid for 60 minutes but by sending a heartbeat request, this gets extended by 20 minutes.

显然,我们需要将API调用保持在最低限度,但这是通过发送心跳请求来延长UserApp.io身份验证时间的好机会。 默认情况下(但可配置),每个经过身份验证的用户令牌在60分钟内有效,但是通过发送心跳请求,该令牌将延长20分钟。

This is a great place to perform also two other functions:

这也是执行其他两项功能的好地方:

If the token has expired in the meantime in UserApp.io, we get an INVALID_CREDENTIALS valued exception so by throwing a Symfony AuthenticationException we log the user out in Symfony as well.

如果令牌同时在UserApp.io中过期,则将得到一个INVALID_CREDENTIALS值异常,因此通过抛出Symfony AuthenticationException我们也将用户注销在Symfony中。

Although heartbeat requests are made to be as cheap as possible (which means no real user data is retrieved), the user locked status does get transmitted back in the form of an exception. So we can take this opportunity and mark our User object locked as well. The locked status can then be used in the application, for example, by checking against it and denying access to various parts if the user is locked.

尽管心跳请求尽可能便宜(这意味着未检索到真实的用户数据),但用户locked状态的确会以异常的形式发送回去。 因此,我们可以借此机会,将我们的User对象也标记为锁定。 然后可以在应用程序中使用locked状态,例如,通过对其进行检查并在用户被锁定的情况下拒绝访问各个部分。

If you want, you can make an API request and update the user object with data from UserApp.io here as well but I find it doesn’t make much sense for most use cases. Data can be updated when the user logs out and back in the next time. But depending on the needs, this can be easily done here. Although keep in mind the performance implications and the cost of many API calls to UserApp.io.

如果愿意,您也可以在此处发出API请求并使用UserApp.io中的数据更新用户对象,但我发现对于大多数用例来说,它没有多大意义。 可以在用户注销并下次再次登录时更新数据。 但是根据需要,这可以在此处轻松完成。 尽管请记住性能影响和对UserApp.io的许多API调用的成本。

And basically that is the crux of our authentication logic.

基本上,这就是我们认证逻辑的关键。

用户类 (The User class)

Let’s also create the UserAppUser class we’ve been talking about earlier:

我们还创建我们之前讨论过的UserAppUser类:

<?php /** * @file AppBundle\Security\UserAppUser.php */ namespace AppBundle\Security; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Security\Core\User\UserInterface; class UserAppUser implements UserInterface { private $id; private $username; private $token; private $firstName; private $lastName; private $email; private $roles; private $properties; private $features; private $permissions; private $created; private $locked; public function __construct($options) { $resolver = new OptionsResolver(); $this->configureOptions($resolver); $params = $resolver->resolve($options); foreach ($params as $property => $value) { $this->{$property} = $value; } } /** * Configures the class options * * @param $resolver OptionsResolver */ private function configureOptions($resolver) { $resolver->setDefaults(array( 'id' => NULL, 'username' => NULL, 'token' => NULL, 'firstName' => NULL, 'lastName' => NULL, 'email' => NULL, 'roles' => array(), 'properties' => array(), 'features' => array(), 'permissions' => array(), 'created' => NULL, 'locked' => NULL, 'last_logged_in' => NULL, 'last_heartbeat' => NULL, )); $resolver->setRequired(array('id', 'username')); } /** * {@inheritdoc} */ public function getRoles() { return $this->roles; } /** * {@inheritdoc} */ public function getToken() { return $this->token; } /** * {@inheritdoc} */ public function getSalt() { } /** * {@inheritdoc} */ public function getUsername() { return $this->username; } /** * {@inheritdoc} */ public function eraseCredentials() { } /** * {@inheritdoc} */ public function getPassword() { } /** * @return mixed */ public function getId() { return $this->id; } /** * @return array */ public function getProperties() { return $this->properties; } /** * @return mixed */ public function isLocked() { return $this->locked; } /** * Locks the user */ public function lock() { $this->locked = true; } /** * Unlocks the user */ public function unlock() { $this->locked = false; } /** * @return mixed */ public function getFirstName() { return $this->firstName; } /** * @return mixed */ public function getLastName() { return $this->lastName; } /** * @return mixed */ public function getEmail() { return $this->email; } /** * @return mixed */ public function getFeatures() { return $this->features; } /** * @return mixed */ public function getCreated() { return $this->created; } /** * @return mixed */ public function getPermissions() { return $this->permissions; } }

Nothing particular here, we are just mapping some data from UserApp.io and implementing some of the methods required by the interface. Additionally we added the locked/unlocked flagger.

这里没有什么特别的,我们只是映射UserApp.io中的一些数据并实现接口所需的一些方法。 另外,我们添加了locked/unlocked标志。

登出 (Logout)

The last class we need to create is the one that deals with logging the user out from UserApp.io when they log out of Symfony.

我们需要创建的最后一个类是处理用户从Symfony注销时从UserApp.io中注销的类。

<?php /** * @file AppBundle\Security\UserAppLogout.php */ namespace AppBundle\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface; use UserApp\API as UserApp; use UserApp\Exceptions\ServiceException; class UserAppLogout implements LogoutHandlerInterface { /** * @var UserApp */ private $userAppClient; public function __construct(UserApp $userAppClient) { $this->userAppClient = $userAppClient; } /** * {@inheritdoc} */ public function logout(Request $request, Response $response, TokenInterface $token) { $api = $this->userAppClient; $user = $token->getUser(); $api->setOption('token', $user->getToken()); try { $api->user->logout(); } catch (ServiceException $exception) { // Empty for now, error probably caused by user not being authenticated which means // user is logged out already. } } }

Here again we inject the UserApp.io PHP client and since we implement the LogoutHandlerInterface we need to have a logout() method. All we do in it is log the user out from UserApp.io if they’re still logged in.

在这里,我们再次注入UserApp.io PHP客户端,由于我们实现了LogoutHandlerInterface我们需要有一个logout()方法。 我们要做的就是如果用户仍在登录,则从UserApp.io注销。

接线全部 (Wiring everything up)

Now that we have our classes, it’s time to declare them as services and use them in our authentication system. Here are our YML based service declarations:

现在我们有了类,是时候将它们声明为服务并在我们的身份验证系统中使用它们了。 这是我们基于YML的服务声明:

user_app_client: class: UserApp\API arguments: ["%userapp_id%"] user_app_authenticator: class: AppBundle\Security\UserAppAuthenticator arguments: ["@user_app_client"] user_app_provider: class: AppBundle\Security\UserAppProvider arguments: ["@user_app_client"] user_app_logout: class: AppBundle\Security\UserAppLogout arguments: ["@user_app_client"]

The first one is the UserApp.io PHP library to which we pass in our application ID in the form of a reference to a parameter. You will need to have a parameter called userapp_id with your UserApp.io App ID.

第一个是UserApp.io PHP库,我们以对参数的引用的形式将应用程序ID传递给该库。 您将需要一个带有UserApp.io App ID的参数userapp_id 。

The other three are the form authenticator, user provider and logout classes we wrote earlier. And as you remember, each accepts one parameter in their constructor in the form of the UserApp.io client defined as the first service.

其他三个是我们之前编写的表单验证器,用户提供程序和注销类。 而且您还记得,每个用户都在其构造函数中以定义为第一个服务的UserApp.io客户端的形式接受一个参数。

Next, it’s time to use these services in our security system, so edit the security.yml file and do the following:

接下来,是时候在我们的安全系统中使用这些服务了,所以请编辑security.yml文件并执行以下操作:

Under the providers key, add the following:

在providers键下,添加以下内容:

user_app: id: user_app_provider

Here we specify that our application has also this user provider so it can use it.

在这里,我们指定我们的应用程序也具有该用户提供程序,以便它可以使用它。

Under the firewall key, add the following:

在firewall密钥下,添加以下内容:

secured_area: pattern: ^/secured/ simple_form: authenticator: user_app_authenticator check_path: security_check login_path: login logout: path: logout handlers: [user_app_logout] target: _home anonymous: ~

What happens here is that we define a simple secure area which uses the simple_form type of authentication with our authenticator. Under the logout key we are adding a handler to be called (our UserAppLogout class defined as a service). The rest is regular Symfony security setup so make sure you do have a login form being shown on the login route, etc. Check out the documentation on this for more information.

这里发生的是,我们定义了一个简单的安全区域,该区域使用我们的身份验证器使用的simple_form身份验证类型。 在logout键下,我们添加了一个要调用的处理程序(我们的UserAppLogout类定义为服务)。 其余的是常规的Symfony安全设置,因此请确保您确实在login路径等上显示了登录表单。有关更多信息,请查看此文档。

And that’s all. By using the simple_form authentication with our custom form authenticator and user provider (along with an optional logout handler), we’ve implemented our own UserApp.io based Symfony authentication mechanism.

就这样。 通过将simple_form身份验证与我们的自定义表单身份验证器和用户提供程序(以及可选的注销处理程序)一起使用,我们实现了自己的基于UserApp.io的Symfony身份验证机制。

结论 (Conclusion)

In this article, we’ve seen how to implement a custom Symfony form authentication using the UserApp.io service and API as a user provider. We’ve gone through quite a lot of code which meant a very brief explanation of the code itself. Rather, I tried to explain the process of authentication with Symfony by building a custom solution that takes into account the way we can interact with UserApp.io.

在本文中,我们已经看到了如何使用UserApp.io服务和API作为用户提供程序来实现自定义Symfony表单身份验证。 我们已经阅读了很多代码,这意味着对代码本身进行了非常简短的解释。 相反,我试图通过构建自定义解决方案来解释使用Symfony进行身份验证的过程,该解决方案考虑了我们与UserApp.io交互的方式。

If you followed along and implemented this method inside your bundle and want to use it like this, go ahead. You also have the option of using the library I created which has a very quick and easy setup described on the GitHub page. I recommend the latter because I plan on developing and maintaining it so you can always get an updated version if any bugs are removed or features introduced (hope not the other way around).

如果您遵循并在包中实现了此方法,并想像这样使用它,请继续。 您还可以选择使用我创建的库 ,该库具有非常快速和容易的设置,如GitHub页面所述。 我建议使用后者,因为我计划开发和维护它,因此,如果删除了任何错误或引入了功能,则始终可以获得更新的版本(不希望出现其他情况)。

If you would like to contribute to it, you’re very welcome. I also appreciate letting me know if you find any problems or think there are better ways to accomplish similar goals.

如果您想为此做出贡献,我们非常欢迎。 如果您发现任何问题或认为有更好的方法来实现类似的目标,也欢迎与我联系。

翻译自: https://www.sitepoint.com/user-authentication-symfony2-userapp-io/

最新回复(0)