bigfork / silverstripe-oauth-login
使用PHP League的OAuth2客户端进行OAuth2登录,实现SilverStripe登录
Requires
- bigfork/silverstripe-oauth: ^2
- silverstripe/framework: ^4.4 | ^5
Requires (Dev)
- phpunit/phpunit: ^5.7
- sminnee/phpunit-mock-objects: ^3.4.5
README
基于PHP League的OAuth2客户端和SilverStripe OAuth模块的SilverStripe OAuth2登录功能。
本模块的功能
此模块向SilverStripe默认登录表单中添加了“通过 <提供者> 登录”按钮,该按钮将使用所选提供者对用户进行身份验证。它还提供了可配置的访问令牌作用域(或权限级别)和字段映射,以便在注册时存储用户数据。
安装
必须使用composer安装此模块。在命令行中运行 composer require bigfork/silverstripe-oauth-login:*,然后运行 dev/build。
配置
注意:您必须首先使用SilverStripe OAuth2模块文档中详细说明的配置选项配置OAuth提供者。
要为配置的提供者显示登录按钮,您必须将它们添加到新的Authenticator类的YAML配置中。配置有两个选项:name(显示在“登录为X”按钮上,此配置方式可能在未来的版本中发生变化)和scopes(访问令牌所需的范围/权限级别)。
有关SilverStripe OAuth2模块文档中Facebook示例的后续内容
SilverStripe\Core\Injector\Injector: Bigfork\SilverStripeOAuth\Client\Factory\ProviderFactory: properties: providers: 'Facebook': '%$FacebookProvider' FacebookProvider: class: 'League\OAuth2\Client\Provider\Facebook' constructor: Options: clientId: '12345678987654321' clientSecret: 'geisjgoesingoi3h1521onnro12rin' graphApiVersion: 'v6.0' Bigfork\SilverStripeOAuth\Client\Authenticator\Authenticator: providers: 'Facebook': # Matches the key for '$%FacebookProvider' above name: 'The Facebooks' scopes: ['email', 'public_profile']
自定义
您可以通过创建相应的模板来自定义每个提供者的登录动作外观,遵循命名约定 FormAction_OAuth_<ProviderName>。例如
<!-- themes/mysite/templates/FormAction_OAuth_Facebook.ss --> <button type="submit" name="{$Name}" id="{$ID}" class="facebook-login"> Connect with Facebook </button>
Bigfork\SilverStripeOAuth\Client\Form\LoginForm类还提供了两个扩展点,updateFields和updateActions,用于进一步自定义。
错误处理
当提供者成功返回,但返回错误状态(例如,当用户选择拒绝您请求的权限时),此模块将尝试将用户返回到登录屏幕并显示一个可读的错误消息。由于每个提供者以不同的格式返回错误消息,您可能需要添加自己的错误处理器,以防默认处理器无法显示合适的消息。例如
Bigfork\SilverStripeOAuth\Client\Control\Controller: error_handlers: loginerrorhandler: priority: 10 context: login class: 'MyLoginErrorHandler'
use Exception; use League\OAuth2\Client\Provider\AbstractProvider; use SilverStripe\Control\HTTPRequest; use SilverStripe\Security\Security; class MyLoginErrorHandler implements ErrorHandler { public function handleError(AbstractProvider $provider, HTTPRequest $request, Exception $exception) { $message = $request->getVar('some_error_message_get_var'); if ($message) { return Security::permissionFailure(null, $message); } } }
概念
护照
通过OAuth提供者进行身份验证的每个成员都被分配一个“护照”——一个对每个OAuth账户所有者唯一的记录。这允许一个SilverStripe账户链接到多个OAuth提供者,或者甚至链接到同一提供者的多个个人账户。虽然这两者都是可能的,但都不是此模块的默认行为:默认情况下,每个新的OAuth账户将创建一个新的SilverStripe成员记录。有关更多信息,请参阅多个提供者/账户和电子邮件冲突部分。
映射器
当用户首次通过提供者注册时,他们尚在SilverStripe数据库中没有关联的Member记录。为此创建该记录,此模块尝试从提供者返回的资源所有者复制信息。
默认行为是尝试复制电子邮件、名和姓,但可以通过两种方式之一更改此行为。
使用 GenericMemberMapper
默认映射器(Bigfork\SilverStripeOAuth\Client\Mapper\GenericMemberMapper)将尝试从可以配置的YAML映射数组中复制字段,例如。
Bigfork\SilverStripeOAuth\Client\Mapper\GenericMemberMapper: mapping: 'Facebook': 'Town': 'Hometown' # Town is the SilverStripe db column, 'Hometown' is in the data returned by Facebook 'Gender': 'Gender'
使用自定义映射器
如果需要更详细或复杂的映射,可以创建自己的映射器类来处理。只需实现Bigfork\SilverStripeOAuth\Client\Mapper\MemberMapperInterface,设置映射逻辑,然后在YAML中注册您的新的映射器。
Bigfork\SilverStripeOAuth\Client\Factory\MemberMapperFactory: mappers: 'Facebook': 'Mysite\MyFacebookMapperClass'
多个提供者/账户
此模块的默认行为是将每个OAuth账户视为一个独立的SilverStripe账户。这是因为每个网站都会有关于如何处理多个账户的特定要求,例如。
- 如果我使用Facebook注册,然后又想链接我的Twitter账户——哪个账户的信息(即姓名、电子邮件地址)应该优先?
- 如果我想要将我的Twitter账户链接到SilverStripe账户A,但因为它已经属于我已用其注册的SilverStripe账户B,会发生什么?应该禁止这样做,还是应该删除账户B?
- 如果我是一个非常尴尬的人,并且有两个想要链接到同一SilverStripe账户的Facebook账户呢?
您可以选择是否以及如何处理此类场景。典型的解决方案是在用户初次认证后,向用户显示“链接X账户”按钮。
电子邮件冲突
由于用户可能有多个OAuth提供者的账户,每个提供者都有自己的电子邮件地址,您可能会遇到类似于“无法用相同的标识符(电子邮件=foo@bar.com)覆盖现有的成员#123”的错误。这是因为SilverStripe的默认行为是确保每个成员记录都有一个唯一的电子邮件地址。有几种不同的方法可以解决这个问题。
- 将
Member.unique_identifier_field配置设置更改为除Email之外的其他内容(例如,ID)。 - 更新您的提供者的
GenericMemberMapper配置,但省略Email字段。 - 创建一个不导入电子邮件地址的自定义映射器。
替换默认认证器
如果您想替换默认认证器或更改oauth认证器的内部名称,您首先需要重置认证器列表。您可以使用以下方法实现这一点。
--- Name: app-auth-reset After: - '#oauthauthenticator' --- SilverStripe\Core\Injector\Injector: SilverStripe\Security\Security: properties: Authenticators: null --- Name: app-auth After: - '#app-auth-reset' --- SilverStripe\Core\Injector\Injector: SilverStripe\Security\Security: properties: Authenticators: myoauthname: '%$Bigfork\SilverStripeOAuth\Client\Authenticator\Authenticator'