如题
一、安装Social login插件
查看官网资料,不再赘述。
二、配置Social login插件
系统管理员账号登录后,先点击Setting,进入系统设置,后点击Social login,进入配置界面。
博主配置后的样例如下:
配置总结如下:
- 允许自动创建新用户;
- 允许已注册的用户采用Social login,在个性化设置界面,手动链接下方的Provider;
- 若email地址已存在,则不允许创建新用户;
- 用户每次登陆时,均更新用户信息;
- 若新用户采用Social login登陆,则自动创建用户,且分配到Default Group;
配置完成后,经过测试可以实现登录、登出功能。
三、常见问题
3.1 Social login登录后,未使用已存在账户,而是新建了一个账户,如何解决?
2023年12月更新:nextcloud27版本中Social login修改位置发生变化为:/var/www/html/custom_apps/sociallogin/lib/Service
Social login插件默认会使用Internal Name-identifier创建新用户。例如博主的已有用户名是Claves,若配置的Internal Name为QQ,则系统会默认创建一个登录名为QQ-Claves的新用户。且无法通过配置纠正此问题。
若实在想解决此问题,那方法就是修改代码。
修改lib\Controller\LoginController.php的private function auth($class, array $config, $provider, $providerType)函数。
修改:
$uid = $provider.'-'.$profileId;
为
$uid = $profileId;
即可解决该问题。
3.2 配置Oauth2配置后,登录始终报错如何解决?
由于Social login未提供属性映射功能,因为Oauth2 Provider的/getUserInfo 接口返回的属性名可能和Social login默认不一致。
想解决此方法,要么更改Social login插件代码,要么更改Oauth2 Provider配置。
Social login获取UserInfo 代码如下:
public function getUserProfile()
{
$profileFields = $this->strToArray($this->config->get('profile_fields'));
$profileUrl = $this->config->get('endpoints')['profile_url'];
if (count($profileFields) > 0) {
$profileUrl .= (strpos($profileUrl, '?') !== false ? '&' : '?') . 'fields=' . implode(',', $profileFields);
}
$response = $this->apiRequest($profileUrl);
if (!isset($response->identifier) && isset($response->id)) {
$response->identifier = $response->id;
}
if (!isset($response->identifier) && isset($response->data->id)) {
$response->identifier = $response->data->id;
}
if (!isset($response->identifier) && isset($response->user_id)) {
$response->identifier = $response->user_id;
}
$data = new Data\Collection($response);
if (!$data->exists('identifier')) {
throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
}
$userProfile = new User\Profile();
foreach ($data->toArray() as $key => $value) {
if ($key !== 'data' && property_exists($userProfile, $key)) {
$userProfile->$key = $value;
}
}
if (null !== $groups = $this->getGroups($data)) {
$userProfile->data['groups'] = $groups;
}
if ($groupMapping = $this->config->get('group_mapping')) {
$userProfile->data['group_mapping'] = $groupMapping;
}
return $userProfile;
}
可以看到用户的唯一性标识字段仅支持identifier,id,user_id,不支持username等字段,因此需要统一。
private function login($uid, Profile $profile, $newGroupPrefix = '')
{
$user = $this->userManager->get($uid);
if (null === $user) {
$connectedUid = $this->socialConnect->findUID($uid);
$user = $this->userManager->get($connectedUid);
}
if ($this->userSession->isLoggedIn()) {
if (!$this->config->getAppValue($this->appName, 'allow_login_connect')) {
throw new LoginException($this->l->t('Social login connect is disabled'));
}
if (null !== $user) {
throw new LoginException($this->l->t('This account already connected'));
}
$currentUid = $this->userSession->getUser()->getUID();
$this->socialConnect->connectLogin($currentUid, $uid);
return new RedirectResponse($this->urlGenerator->linkToRoute('settings.PersonalSettings.index', ['section'=>'sociallogin']));
}
if ($this->config->getAppValue($this->appName, 'restrict_users_wo_mapped_groups') && isset($profile->data['group_mapping'])) {
$groups = isset($profile->data['groups']) ? $profile->data['groups'] : [];
$mappedGroups = array_intersect($groups, array_keys($profile->data['group_mapping']));
if (!$mappedGroups) {
throw new LoginException($this->l->t('Your user group is not allowed to login, please contact support'));
}
}
$updateUserProfile = $this->config->getAppValue($this->appName, 'update_profile_on_login');
if (null === $user) {
if ($this->config->getAppValue($this->appName, 'disable_registration')) {
throw new LoginException($this->l->t('Auto creating new users is disabled'));
}
if (
$profile->email && $this->config->getAppValue($this->appName, 'prevent_create_email_exists')
&& count($this->userManager->getByEmail($profile->email)) !== 0
) {
throw new LoginException($this->l->t('Email already registered'));
}
$password = substr(base64_encode(random_bytes(64)), 0, 30);
$user = $this->userManager->createUser($uid, $password);
if ($this->config->getAppValue($this->appName, 'create_disabled_users')) {
$user->setEnabled(false);
}
$this->config->setUserValue($uid, $this->appName, 'disable_password_confirmation', 1);
$updateUserProfile = true;
if (!$this->config->getAppValue($this->appName, 'disable_notify_admins')) {
$this->notifyAdmins($uid, $profile->displayName ?: $profile->identifier, $profile->data['default_group']);
}
}
if ($updateUserProfile) {
$user->setDisplayName($profile->displayName ?: $profile->identifier);
$user->setEMailAddress((string)$profile->email);
if ($profile->photoURL) {
$curl = new Curl();
try {
$photo = $curl->request($profile->photoURL);
$avatar = $this->avatarManager->getAvatar($uid);
$avatar->set($photo);
} catch (\Exception $e) {}
}
if (isset($profile->data['groups']) && is_array($profile->data['groups'])) {
$groupNames = $profile->data['groups'];
$groupMapping = isset($profile->data['group_mapping']) ? $profile->data['group_mapping'] : null;
$userGroups = $this->groupManager->getUserGroups($user);
$autoCreateGroups = $this->config->getAppValue($this->appName, 'auto_create_groups');
$syncGroupNames = [];
foreach ($groupNames as $k => $v) {
if ($groupMapping && isset($groupMapping[$v])) {
$syncGroupNames[] = $groupMapping[$v];
}
if ($autoCreateGroups) {
$syncGroupNames[] = $newGroupPrefix.$v;
}
}
if (!$this->config->getAppValue($this->appName, 'no_prune_user_groups')) {
foreach ($userGroups as $group) {
if (!in_array($group->getGID(), $syncGroupNames)) {
$group->removeUser($user);
}
}
}
foreach ($syncGroupNames as $groupName) {
if ($group = $this->groupManager->createGroup($groupName)) {
$group->addUser($user);
}
}
}
$defaultGroup = $profile->data['default_group'];
if ($defaultGroup && $group = $this->groupManager->get($defaultGroup)) {
$group->addUser($user);
}
}
$this->userSession->completeLogin($user, ['loginName' => $user->getUID(), 'password' => '']);
$this->userSession->createSessionToken($this->request, $user->getUID(), $user->getUID());
if ($redirectUrl = $this->session->get('login_redirect_url')) {
return new RedirectResponse($redirectUrl);
}
$this->session->set('last-password-confirm', time());
return new RedirectResponse($this->urlGenerator->getAbsoluteURL('/'));
}
通过以上代码可知,用户名只支持displayName字段,不支持常规的nickName,因此也需要适配统一。