Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >Google Admin SDK:您无权访问此接口

Google Admin SDK:您无权访问此接口
EN

Stack Overflow用户
提问于 2015-06-01 09:12:13
回答 2查看 1.7K关注 0票数 6

自从上周谷歌登录身份验证被禁用以来,我正在尝试让oAuth 2.0与服务帐户一起工作。我们希望为内部web应用程序上的用户提供在Office之外进行设置的机会。

我下载了最新的Google APIs Client Library for PHP。在Google Developer Console中,我为我的应用程序创建了一个新项目,并创建了一个Service account凭据。我还在开发者控制台中启用了API服务:Admin SDK

我已授予帐户用户ID对正确作用域的访问权限(我认为):

当我使用service-account.php示例并更改细节时,我会收到一个带有访问令牌的JSON,但是当我向用户发出CURL请求(与前面一样)以获取电子邮件设置时,就会出现错误"You are not authorized to access this API."

我的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php

include_once "templates/base.php";
require_once realpath(dirname(__FILE__) . '/../src/Google/autoload.php');
$client_id = '124331845-DELETEDPART-hbh89pbgl20citf6ko.apps.googleusercontent.com'; //Client ID
$service_account_name = '124331845-DELETEDPART-89pbgl20citf6ko@developer.gserviceaccount.com'; //Email Address
$key_file_location = 'globaltext-4ce09b20cb73.p12'; //key.p12

$client = new Google_Client();
if (isset($_SESSION['service_token'])) {
  $client->setAccessToken($_SESSION['service_token']);
}
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
    $service_account_name,
    array('https://apps-apis.google.com/a/feeds/emailsettings/2.0/'),
    $key
);
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
  $client->getAuth()->refreshTokenWithAssertion($cred);
}

$aOutput = json_decode($client->getAccessToken());

$strEmailAdresSplit = explode('@', "FIRSTNAME.LASTNAME@DOMAIN.EXTENSION");
$strDomein = $strEmailAdresSplit[1];
$strAlias = $strEmailAdresSplit[0];

$resConnectionJobs = curl_init();
$aHeader = array();
$aHeader[] = 'Authorization: Bearer '.$aOutput->access_token; 
$aHeader[] = 'Content-Type: application/atom+xml'; 

curl_setopt($resConnectionJobs, CURLOPT_URL, "https://apps-apis.google.com/a/feeds/emailsettings/2.0/DOMAIN.EXTENSION/FIRSTNAME.LASTNAME/vacation"); 
curl_setopt($resConnectionJobs, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($resConnectionJobs, CURLOPT_HTTPHEADER, $aHeader);
curl_setopt($resConnectionJobs, CURLOPT_RETURNTRANSFER, true);
curl_setopt($resConnectionJobs, CURLOPT_HEADER, false);

$oCurlData = curl_exec($resConnectionJobs);

curl_close($resConnectionJobs);
echo $oCurlData;

?>
EN

回答 2

Stack Overflow用户

发布于 2015-06-01 10:27:55

您确定您的凭据是正确的吗?

请尝试以下过程以确保您具有正确的凭据。

创建您的API密钥

转到并执行以下步骤:

  • 选择您的项目
  • 选择菜单项“API&auth”
  • 选择菜单项“注册的应用程序”
  • 注册类型的应用程序web application"
  • Choose根据您创建的应用程序的类型,选择以下选项之一。服务器端语言应使用此选项:用于服务器应用程序的
    • 密钥(具有IP locking)

获取访问令牌和刷新令牌的

创建一个包含以下代码的文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php

if (isset($_GET['code'])) {
    // try to get an access token
    $code = $_GET['code'];
    $url = 'https://accounts.google.com/o/oauth2/token';
    $params = array(
        "code" => $code,
        "client_id" => YOUR_CLIENT_ID,
        "client_secret" => YOUR_CLIENT_SECRET,
        "redirect_uri" => 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"],
        "grant_type" => "authorization_code"
    );

    $ch = curl_init();
    curl_setopt($ch, constant("CURLOPT_" . 'URL'), $url);
    curl_setopt($ch, constant("CURLOPT_" . 'POST'), true);
    curl_setopt($ch, constant("CURLOPT_" . 'POSTFIELDS'), $params);
    $output = curl_exec($ch);
    $info = curl_getinfo($ch);
    curl_close($ch);
    if ($info['http_code'] === 200) {
        header('Content-Type: ' . $info['content_type']);
        return $output;
    } else {
        return 'An error happened';
    }
} else {

    $url = "https://accounts.google.com/o/oauth2/auth";

    $params = array(
        "response_type" => "code",
        "client_id" => YOUR_CLIENT_ID,
        "redirect_uri" => 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"],
        "scope" => "https://www.googleapis.com/auth/plus.me"
    );

    $request_to = $url . '?' . http_build_query($params);

    header("Location: " . $request_to);
}

现在,将YOUR_CLIENT_IDYOUR_CLIENT_SECRET替换为您的客户端ID和客户端密码。

确保您的作用域是正确的。例如,如果您想要访问分析,它应该是https://www.googleapis.com/auth/analytics

如果您运行该文件,您应该会看到一个OAuth2批准屏幕。

如果现在按Accept,应该会得到如下所示的结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "access_token" : YOUR_ACCESS_TOKEN,
  "token_type" : "Bearer",
  "expires_in" : 3600,
  "refresh_token" : YOUR_REFRESH_TOKEN
}

结果可能包含其他字段,具体取决于您申请的作用域。

在后台与谷歌系统连接

一旦你得到上面的工作,你的应用程序需要实现以下工作流程:

1)检查您的输入是否包含名为code的GET参数。如果"code“存在,则获取新的访问令牌并重复此步骤(刷新页面)。如果"code”不存在,请转到步骤2。

2)检查您的服务是否存储了凭据。如果存在凭据,请检查您的访问令牌是否已过期或即将过期。然后转到步骤3。如果凭据不存在,请转到您的服务的身份验证路径以获取身份验证码,然后返回步骤1(确保Google重定向到您当前的URL)。

3)如果需要刷新,请刷新页面并返回步骤1。如果不需要刷新,则已准备好在第一个位置实际执行您想要做的操作。

不过,谷歌的PHP库会关注oAuth2是否会为您流动。如果你正在使用他们的库,3步过程中的每一步都是由库来处理的,你应该能够直接使用Google的服务做任何你想做的事情。我自己在中使用了这个策略。

但是,您可以只编写自定义库并直接与服务连接。下面是我几个月前写的一个项目的一些开发代码。虽然它不是开箱即用的(因为它是一个大型应用程序的控制器),但它应该可以帮助您理解Google的库在幕后处理的流程。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
namespace Application;

class Controller_API_Google_Youtube extends Controller_API {
    public function read() {
        $scope = "https://www.googleapis.com/auth/youtube";
        $this->doOauth($scope);
    }

    function doOauth($scope) {

        $oauth2Credentials = JSON_File::load(__DIR__ . DIRECTORY_SEPARATOR . 'Config.json');

        $paths = array(
            'token' => 'https://accounts.google.com/o/oauth2/token',
            'auth' => "https://accounts.google.com/o/oauth2/auth"
        );

       $refreshtime = 300;

        if (isset($_GET['code'])) {
            // Get access code
            $query = $_GET;
            unset($query['code']);
            if (count($query) > 0) {
                $query = '?' . http_build_query($query);
            } else {
                $query = '';
            }

            $client = \PowerTools\HTTP_Client::factory(
                        array(
                            'maps' => array(
                                'url' => $paths['token'],
                                'returntransfer' => 1,
                                'post' => true,
                                'postfields' => array(
                                    'code' => $_GET['code'],
                                    "client_id" => $oauth2Credentials['client_id'],
                                    "client_secret" => $oauth2Credentials['client_secret'],
                                    "redirect_uri" => HTTP_PROTOCOL . URL_PATH . $query,
                                    "grant_type" => "authorization_code"
                                )
                            )
                        )
            )->execute();
            $responses = $client->getResponses();
            $response = array_pop($responses);
            $info = $response['maps']->getInfo();
            $content = $response['maps']->getContent();
            if ($info['http_code'] === 200) {
                $output = JSON::decode($content);
                $oauth2Credentials[$scope] = array();
                $oauth2Credentials[$scope]['expires'] = time() + $output['expires_in'];
                $oauth2Credentials[$scope]['access_token'] = $output['access_token'];
                $oauth2Credentials[$scope]['refresh_token'] = $output['refresh_token'];
                file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . 'Config.json', JSON::encode($oauth2Credentials));
                header("Location: " . HTTP_PROTOCOL . URL_PATH . $query);
            } else {
                echo "Something went wrong";
            }
        } elseif (!isset($oauth2Credentials[$scope])) {
            // Get auth code

            header("Location: " . $paths['auth'] . '?' . http_build_query(
                        array(
                            "response_type" => "code",
                            "client_id" => $oauth2Credentials['client_id'],
                            "redirect_uri" => HTTP_PROTOCOL . DOMAIN_PATH,
                            "scope" => $scope
                        )
            ));
        } elseif ($oauth2Credentials[$scope]['expires'] - $refreshtime < time()) {
            // Refresh access code

            $client = \PowerTools\HTTP_Client::factory(
                        array(
                            'maps' => array(
                                'url' => $paths['token'],
                                'returntransfer' => 1,
                                'post' => true,
                                'postfields' => array(
                                    "client_id" => $oauth2Credentials['client_id'],
                                    "client_secret" => $oauth2Credentials['client_secret'],
                                    "refresh_token" => $oauth2Credentials[$scope]['refresh_token'],
                                    "grant_type" => "refresh_token"
                                )
                            )
                        )
            )->execute();
            $responses = $client->getResponses();
            $response = array_pop($responses);
            $info = $response['maps']->getInfo();
            $content = $response['maps']->getContent();
            if ($info['http_code'] === 200) {
                $output = JSON::decode($response['maps']->getContent());
                $oauth2Credentials[$scope]['expires'] = time() + $output['expires_in'];
                $oauth2Credentials[$scope]['access_token'] = $output['access_token'];
                file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . 'Config.json', JSON::encode($oauth2Credentials));
                $this->read();
            } else {
                $this->output = array("error" => "Something went wrong");
            }
        } else {
            $this->doSomethinguseful($oauth2Credentials, $scope);
        }
        return $this;
    }


    function doSomethinguseful($oauth2Credentials, $scope) {
        // https://developers.google.com/youtube/v3/sample_requests?hl=nl
        $client = \PowerTools\HTTP_Client::factory(
                    array(
                        'maps' => array(
                            'useragent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13',
                            'url' => 'https://www.googleapis.com/youtube/v3/channels?part=contentDetails&mine=true',
                            'returntransfer' => true,
                            'httpheader' => array(
                                'Authorization: Bearer ' . $oauth2Credentials[$scope]['access_token'],
                                'Accept-Encoding: gzip, deflate'
                            )
                        )
                    )
        )->execute();
        $responses = $client->getResponses();
        $response = array_pop($responses);
        $content = $response['maps']->getContent();
        $this->output = JSON::decode(gzdecode($content));
    }
}
票数 1
EN

Stack Overflow用户

发布于 2015-07-27 19:56:31

看起来你可能也遇到了我遇到的问题。

Google_Auth_AssertionCredentials的调用实际上需要更多的参数,而不是发送给服务帐户。(至少在我的案例中是这样的。)

您需要传递足够的参数来包含sub (针对哪个用户采取操作)。

如果不这样做,我的访问总是会被拒绝。这显然并不明显,因为php库中甚至添加了一个函数loadServiceAccountJson,该函数用于设置服务帐户客户端连接,但由于也没有设置sub而中断。

请参阅此处的工作代码:Google php client library loadServiceAccountJson broken - fix enclosed

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30569681

复制
相关文章
Python抛出异常_python抛出异常的作用
在python中不同的异常可以用不同的类型(python中统一了类与类型,类型即类)去标识,不同的类对象标识不同的异常,一个异常标识一种错误
全栈程序员站长
2022/11/02
2.5K0
Java陷阱之:finally块抛出异常或return导致异常丢失
java中finally语句包含有抛出异常或者return语句,会把try块中出现的异常丢弃。
崔认知
2023/06/19
8830
Java陷阱之:finally块抛出异常或return导致异常丢失
【C++ 语言】异常 ( 抛出字符串异常 | 抛出异常对象 | 抛出任意对象 | 抛出自定义异常 )
1. 异常处理 : 使用 " try{}catch(){} " 将抛出异常的代码包起来 , 注意将可能抛出异常的代码包裹在 try 后的大括号中 , 将异常处理逻辑放在 catch 后的大括号中 ;
韩曙亮
2023/03/27
1.3K0
django 获取字段选项 choice 的值
由二项元组构成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,而且这个选择框的选项就是choices 中的选项。
卓越笔记
2023/02/18
2.7K0
android 抛出FileNotFoundException异常
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
全栈程序员站长
2022/11/17
1.6K0
.net remoting 抛出异常
所有在远程软件运行的类,如果需要传输到本地,都需要继承 MarshalByRefObject 或其他可以序列化的类。
林德熙
2018/09/19
1.5K0
.net remoting 抛出异常
dotnet remoting 抛出异常
所有在远程软件运行的类,如果需要传输到本地,都需要继承 MarshalByRefObject 或其他可以序列化的类。
林德熙
2019/09/27
1.4K0
dotnet remoting 抛出异常
python抛出异常和捕获异常_在try块中可以抛出异常吗
2.解析 关键字try 以及except是 使用Python 解释器主动抛出异常的关键, Python解释器从上向下执行 当运行try中的某行代码出错,会直接进入except中执行下方代码 try中错行下方的代码不会被运行 except…as… 是固定的语法格式 打印traceback信息 finally 后的代码不管是否抛出异常都会执行 except 的原理 调用sys中 exc.info 方法返回基本信息 所以抛出异常的第一步拓展可以在这里开始 注意 每个关键字下方的代码都是独立的(所有的变量都是局部变量)
全栈程序员站长
2022/11/02
4.5K0
python抛出异常会终止程序吗_catch里面抛出异常
如果没有 try 和 except 语句覆盖抛出异常的 raise 语句,该程序就会崩溃,并显示异常的出错信息。通常是调用该函数的代码知道如何处理异常,而不是该函数本身。所以你常常会看到 raise 语句在一个函数中,try 和 except 语句在调用该函数的代码中。
全栈程序员站长
2022/11/19
2.2K0
dotnet remoting 抛出异常
所有在远程软件运行的类,如果需要传输到本地,都需要继承 MarshalByRefObject 或其他可以序列化的类。
林德熙
2022/08/04
1K0
python抛出异常和捕获异常_Python异常
class Widget: def __init__(self,size=(40,40)): self._size=size def getSize(self): return self._size def resize(self,width,height): if width<0 or height<0:
全栈程序员站长
2022/11/02
2.9K0
应该抛出什么异常?不应该抛出什么异常?(.NET/C#)
2018-02-04 13:25
walterlv
2018/09/18
1.7K0
python抛出异常会终止程序吗_python抛出异常的作用
当python执行无效的代码时,就会抛出异常。用 try 和 catch 语句可以处理异常,以避免程序的崩溃。我们也可以在代码中抛出自己的异常,抛出异常意味着 停止运行这个函数中的代码,将程序执行转到except语句
全栈程序员站长
2022/11/02
1.8K0
c++构造函数是否可以抛出异常_什么叫抛出异常
从语法上来说,构造函数可以抛出异常。但从逻辑上和风险控制上,构造函数中尽量不要抛出异常。万不得已,一定要注意防止内存泄露。
全栈程序员站长
2022/09/22
1.7K1
Java 捕获和抛出异常
Java中把非正常情况分为两种:异常(Exception)和错误(Error),其中Error错误一般是指与虚拟机相关的问题,这种错误无法恢复或不可能捕获,而对于Exception异常我们可以使用try…catch进行捕获。try…catch不允许存在单独的try块或catch块,可存在多个catch块。try块中存放业务功能代码,catch块中存放异常处理代码。Java7后支持用catch捕获多个异常,也可捕获自定义异常。对于捕获的异常一般可以使用printStackTrace()方法追踪输出至标准错误流。try…catch后可以添加finally,使用finally可以保证除系统退出外finally块中代码绝对执行。捕获异常时需要注意一定要先捕获小异常,再捕获大异常,否则小异常将无法被捕获。代码示例如下
用户7886150
2021/04/06
1.9K0
django 主动抛出 403 异常
* 网站名称:obaby@mars * 网址:https://h4ck.org.cn/ * 本文标题: 《django 主动抛出 403 异常》 * 本文链接:https://h4ck.org.cn/2018/12/django-%e4%b8%bb%e5%8a%a8%e6%8a%9b%e5%87%ba-403-%e5%bc%82%e5%b8%b8/ * 转载文章请标明文章来源,原文标题以及原文链接。请遵从 《署名-非商业性使用-相同方式共享 2.5 中国大陆 (CC BY-NC-SA 2.5 CN) 》许可协议。
obaby
2023/02/24
7540
python中用来抛出异常的关键字是( )_python异常抛出
动抛出异常raise typeerror(类型错误) # 7. 触发异常try: raise typeerror(类型错误)except exception as e: print(e) # 8. 自定义异常class my…syntaxerror 语法错误 python代码非法,代码不能编译(个人认为这是语法错误,写错了) typeerror 类型错误传入对象类型与要求的不符合 unboundlocalerror …
全栈程序员站长
2022/11/02
1K0
interrupt+抛出异常测试
建议使用“抛异常”的方法来实现线程的停止,因为在catch块中可以对异常的信息进行相关的处理,而且使用异常流能更好、更方便的控制程序的运行流程,不至于代码中出现很多个return;污染代码。
用户7365393
2021/10/07
4980
在python中,如果异常并未被处理或捕捉_抛出异常是什么意思
Python使用异常类来管理异常信息。当发生异常的时候,程序会抛出一个异常信息,自动根据代码的层次查找异常处理信息。当代码发生异常而没有指定处理异常的方法是,Traceback会打印发生异常时代码执行栈的情况。
全栈程序员站长
2022/11/02
1.6K0
Java 如何抛出异常、自定义异常
1、定义 : 一个方法不处理这个异常,而是调用层次向上传递,谁调用这个方法,这个异常就由谁来处理。
Java编程指南
2019/08/02
4.8K0
Java 如何抛出异常、自定义异常

相似问题

按值或引用抛出异常

23

抛出异常或返回值

45

抛出异常或返回值

11

抛出异常,然后传播或返回布尔值,然后抛出异常?

11

为"Find“方法抛出异常或返回选项更好吗?

20
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文