You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Concrete5搭建的企业内网中,如何通过Google登录请求额外权限?

解决方案:Concrete5 集成 Gmail 一键登录+自动授权+日历展示

嘿,我之前帮团队搭过类似的Concrete5内网系统,正好踩过不少坑,给你一套不用动核心文件的落地方案:

第一步:先搞定 Google OAuth2 应用配置

首先得在Google那边弄好授权凭据,不然Concrete5没法和Gmail对接:

  • 去Google Cloud Console新建个项目,记得启用Google Calendar API(毕竟要访问个人日历)
  • 创建OAuth2客户端ID,授权回调URL填你内网的回调地址,比如 https://your-intranet-domain.com/login/oauth2/callback
  • 把生成的Client ID和Client Secret存好,后面要用到

第二步:用自定义包扩展Concrete5登录流程

Concrete5绝对不建议直接改核心文件,升级会全丢,所以咱们做个自定义包来接管登录:

2.1 写个自定义登录控制器

在你的包目录(比如packages/gmail_login/)下创建controllers/login.php,代码如下:

<?php
namespace Concrete\Package\GmailLogin\Controller;

use Concrete\Core\Controller\Controller;
use League\OAuth2\Client\Provider\Google;
use Concrete\Core\User\User;

class Login extends Controller
{
    public function oauth()
    {
        // 替换成你自己的Google凭据
        $provider = new Google([
            'clientId'     => '你的Google Client ID',
            'clientSecret' => '你的Google Client Secret',
            'redirectUri'  => 'https://your-intranet-domain.com/login/oauth2/callback',
        ]);

        // 还没拿到授权码?直接跳Google授权页(自动触发权限请求)
        if (!isset($_GET['code'])) {
            $authUrl = $provider->getAuthorizationUrl([
                'scope' => [
                    'email',
                    'profile',
                    'https://www.googleapis.com/auth/calendar.readonly' // 要日历只读权限,按需调整
                ]
            ]);
            $_SESSION['oauth2state'] = $provider->getState();
            header('Location: ' . $authUrl);
            exit;
        } 
        // 处理Google回调回来的授权码
        else {
            // 验证state防CSRF,这个不能省
            if (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
                unset($_SESSION['oauth2state']);
                $this->redirect('/login', 'error');
            }

            // 获取访问令牌
            $token = $provider->getAccessToken('authorization_code', [
                'code' => $_GET['code']
            ]);

            // 拿到用户的Gmail信息
            $googleUser = $provider->getResourceOwner($token);
            $userEmail = $googleUser->getEmail();

            // 检查Concrete5里有没有这个用户
            $c5User = User::getByEmail($userEmail);
            if ($c5User && $c5User->isRegistered()) {
                // 自动登录这个用户
                $c5User->login();
                // 把令牌存在用户属性里,后面调用日历API要用
                $c5User->setUserAttribute('google_access_token', $token->getToken());
                $c5User->setUserAttribute('google_refresh_token', $token->getRefreshToken());
                // 直接跳首页
                $this->redirect('/');
            } else {
                // 内网一般只允许公司邮箱,所以加个域名检查
                if (str_ends_with($userEmail, '@你的公司域名.com')) {
                    // 自动创建新用户
                    $newUser = new User();
                    $newUser->create([
                        'uName' => $userEmail,
                        'uEmail' => $userEmail,
                        'uFullName' => $googleUser->getName()
                    ]);
                    $newUser->login();
                    $newUser->setUserAttribute('google_access_token', $token->getToken());
                    $this->redirect('/');
                } else {
                    // 非公司邮箱直接踢回登录页
                    $this->redirect('/login', 'invalid_domain');
                }
            }
        }
    }
}

2.2 替换默认登录入口

把你主题里的登录按钮链接改成自定义的OAuth地址:

<a href="/index.php/login/oauth" class="btn btn-primary">用Gmail一键登录</a>

要是想更彻底,直接把Concrete5默认的登录页面模板改成自动跳转这个OAuth地址,用户点登录就直接触发授权,完全不用填账号密码。

第三步:展示用户的个人日历

登录后用户已经有了Google的访问令牌,咱们可以做个自定义区块或者页面类型来加载日历:

<?php
$currentUser = new User();
$accessToken = $currentUser->getUserAttribute('google_access_token');
if ($accessToken) {
    $client = new Google\Client();
    $client->setAccessToken($accessToken);
    // 令牌过期了?用刷新令牌自动更新
    if ($client->isAccessTokenExpired()) {
        $refreshToken = $currentUser->getUserAttribute('google_refresh_token');
        $client->fetchAccessTokenWithRefreshToken($refreshToken);
        $newTokenData = $client->getAccessToken();
        $currentUser->setUserAttribute('google_access_token', $newTokenData['access_token']);
        // 刷新令牌可能会变,要存回去
        $currentUser->setUserAttribute('google_refresh_token', $newTokenData['refresh_token'] ?? $refreshToken);
    }
    // 调用Calendar API拿事件
    $calendarService = new Google\Service\Calendar($client);
    $events = $calendarService->events->listEvents('primary', [
        'maxResults' => 10,
        'orderBy' => 'startTime',
        'singleEvents' => true,
        'timeMin' => date('c'),
    ]);
    // 渲染日历事件
    foreach ($events->getItems() as $event) {
        $eventStart = $event->start->dateTime ?? $event->start->date;
        echo "<div class='calendar-event mb-3'>";
        echo "<h4 class='mb-1'>" . h($event->getSummary()) . "</h4>";
        echo "<p class='text-muted'>" . h($eventStart) . "</p>";
        echo "</div>";
    }
} else {
    echo "<p class='text-warning'>请先登录以查看个人日历</p>";
}

几个关键提醒

  • 绝对别改核心文件:用自定义包和主题模板扩展,不然Concrete5升级后你的修改全没了
  • 权限锁死:一定要加公司邮箱域名检查,防止外人登录内网
  • 令牌管理:把Google的令牌存在用户自定义属性里,方便后续调用API,还要处理令牌过期自动刷新
  • 安全不能省:OAuth的state参数一定要验证,防CSRF攻击
  • 测试阶段:在Google Cloud Console里加测试用户,不然开发时可能会遇到授权限制

这样一套下来,用户点击登录就直接跳Google授权页,授权完自动登录Concrete5并跳首页,后续还能直接看个人日历,完全符合你的需求。

内容的提问来源于stack exchange,提问作者TheLittleStarWarrior

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:23:20