Java “线程中的异常”;“主要”;com.google.api.client.auth.oauth2.TokenResponseException:401尝试访问google课堂api时未经授权
我已经阅读了所有与此问题相关的堆栈溢出问题。我有一些想法,但它不能帮助我解决这个问题 我已使用服务帐户进行授权。因为我不想为我的用户显示授权屏幕。所以我在GoogleAPI控制台中创建了服务帐户并启用了域范围的委托权限 我需要以编程的方式在用户的google教室中创建课程。我已经按照java语言使用了OAuth客户机ID和OAuth客户机机密。完成后,授权令牌已存储在项目目录中。使用此令牌,我可以在授权用户的google教室中创建课程。因为我需要在谷歌教室中为我所在领域的许多用户创建课程。所以我使用了服务帐户。当我尝试实现它时,我得到了上面的错误 我已经在web应用程序中实现了它。为了更好地理解和代码可读性,我创建了一个quickstart maven项目并粘贴了代码。代码在System.out.println(“进入列表课程方法:”)中运行良好;线路 1) 如何解决这个问题 2) 它会要求管理员授权吗?因为为了访问用户数据,我们需要访问令牌。如何使用服务帐户获取访问令牌Java “线程中的异常”;“主要”;com.google.api.client.auth.oauth2.TokenResponseException:401尝试访问google课堂api时未经授权,java,google-api,google-oauth,google-admin-sdk,google-classroom,Java,Google Api,Google Oauth,Google Admin Sdk,Google Classroom,我已经阅读了所有与此问题相关的堆栈溢出问题。我有一些想法,但它不能帮助我解决这个问题 我已使用服务帐户进行授权。因为我不想为我的用户显示授权屏幕。所以我在GoogleAPI控制台中创建了服务帐户并启用了域范围的委托权限 我需要以编程的方式在用户的google教室中创建课程。我已经按照java语言使用了OAuth客户机ID和OAuth客户机机密。完成后,授权令牌已存储在项目目录中。使用此令牌,我可以在授权用户的google教室中创建课程。因为我需要在谷歌教室中为我所在领域的许多用户创建课程。所以我
public class ClassroomServiceAccount {
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static final String SERVICE_ACCOUNT_EMAIL = "xxxxxxx@projectName.iam.gserviceaccount.com";
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH = "/MyProject.p12";
private static final List<String> SCOPES = Arrays.asList(ClassroomScopes.CLASSROOM_COURSES, ClassroomScopes.CLASSROOM_TOPICS, ClassroomScopes.CLASSROOM_ANNOUNCEMENTS);
public static void main(String... args) throws IOException, GeneralSecurityException {
HttpTransport httpTransport = new NetHttpTransport();
InputStream in = ClassroomServiceAccount.class.getResourceAsStream(SERVICE_ACCOUNT_PKCS12_FILE_PATH);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(in, "notasecret".toCharArray());
String alias = "key1";
Key key = keystore.getKey(alias, "notasecret".toCharArray());
// Get certificate of public key
Certificate cert = keystore.getCertificate(alias);
// Get public key
PublicKey publicKey = cert.getPublicKey();
System.out.println("This is public key : "+ publicKey);
// Return a key pair
KeyPair k = new KeyPair(publicKey, (PrivateKey) key);
System.out.println("This is k : "+ k.getPrivate());
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountPrivateKey(k.getPrivate())
.setServiceAccountScopes(SCOPES)
.setServiceAccountUser("email@yourdomain.com")
.build();
System.out.println("credentials : " + credential.getServiceAccountPrivateKey());
Classroom service = new Classroom.Builder(httpTransport, JSON_FACTORY, null)
.setApplicationName(APPLICATION_NAME)
.setHttpRequestInitializer(credential)
.build();
// Create courses in users google classroom
Course course = new Course();
course.setOwnerId("user@yourdomain.com");
course.setName("Science");
service.courses().create(course).execute();
}
}
公共类ClassroomServiceAccount{
私有静态最终JsonFactory JSON_FACTORY=JacksonFactory.getDefaultInstance();
私有静态最终字符串服务\u帐户\u电子邮件=”xxxxxxx@projectName.iam.gserviceaccount.com";
私有静态最终字符串服务\u帐户\u PKCS12\u文件\u路径=“/MyProject.p12”;
私有静态最终列表范围=Arrays.asList(ClassroomScopes.clustry\u课程、ClassroomScopes.clustry\u主题、ClassroomScopes.clustry\u公告);
publicstaticvoidmain(字符串…参数)抛出IOException、GeneralSecurityException{
HttpTransport HttpTransport=新的NetHttpTransport();
InputStream in=ClassroomServiceAccount.class.getResourceAsStream(服务\帐户\ PKCS12\文件\路径);
KeyStore KeyStore=KeyStore.getInstance(KeyStore.getDefaultType());
加载(在“notasecret.toCharArray()中);
字符串alias=“key1”;
Key=keystore.getKey(别名“notasecret.toCharArray());
//获取公钥证书
证书cert=keystore.getCertificate(别名);
//获取公钥
PublicKey PublicKey=cert.getPublicKey();
System.out.println(“这是公钥:“+publicKey”);
//返回密钥对
密钥对k=新密钥对(公钥,(私钥)密钥);
System.out.println(“这是k:+k.getPrivate());
GoogleCredential credential=新建GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(JSON_工厂)
.setServiceAccountId(服务\帐户\电子邮件)
.setServiceAccountPrivateKey(k.getPrivate())
.setServiceAccountScopes(范围)
.setServiceAccountUser(“email@yourdomain.com")
.build();
System.out.println(“凭证:+credential.getServiceAccountPrivateKey());
教室服务=新教室.Builder(httpTransport,JSON_工厂,空)
.setApplicationName(应用程序名称)
.setHttpRequestInitializer(凭证)
.build();
//在谷歌教室中创建课程
课程=新课程();
course.setOwnerId(“user@yourdomain.com");
课程名称(“科学”);
service.courses().create(course.execute();
}
}
如评论中所述,您必须将用户凭据替换为用户的凭据。在本例中,我使用服务帐户中的示例修改了凭证的示例。如您所见,我完全删除了getCredentials
函数。但是,您仍然可以将凭据生成器放在那里:
public class ClassroomQuickstart {
private static final String APPLICATION_NAME = "Google Classroom API Java Quickstart";
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static final String TOKENS_DIRECTORY_PATH = "tokens";
private static final String KEY_FILE_LOCATION = "full path of your service account creds json";
/**
* Global instance of the scopes required by this quickstart.
* If modifying these scopes, delete your previously saved tokens/ folder.
*/
private static final List<String> SCOPES = Collections.singletonList(ClassroomScopes.CLASSROOM_COURSES_READONLY);
/**
* Creates an authorized Credential object.
* @param HTTP_TRANSPORT The network HTTP Transport.
* @return An authorized Credential object.
* @throws IOException If the credentials.json file cannot be found.
*/
public static void main(String... args) throws IOException, GeneralSecurityException {
GoogleCredential credential = GoogleCredential
.fromStream(new FileInputStream(KEY_FILE_LOCATION))
.createScoped(ClassroomScopes.all());
// Build a new authorized API client service.
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
Classroom service = new Classroom.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME)
.build();
// List the first 10 courses that the user has access to.
ListCoursesResponse response = service.courses().list()
.setPageSize(10)
.execute();
List<Course> courses = response.getCourses();
if (courses == null || courses.size() == 0) {
System.out.println("No courses found.");
} else {
System.out.println("Courses:");
for (Course course : courses) {
System.out.printf("%s\n", course.getName());
}
}
}
}
域范围快速启动的其余部分
您的教室服务生成器和新课程代码是正确的,应该与新的凭证一起使用。我已通过更改范围解决了此异常。i、 例如,在我的代码中,我使用了三个作用域。这三个范围应与Gsuite的范围相匹配。同时,我们增加了范围。这两个范围都应该匹配,以避免未经授权 您是否从服务帐户创建了
键
?代币在里面。是的。我已经下载了.p12密钥。你可以在我的代码中看到它。i、 例如,私有静态最终字符串服务\u帐户\u PKCS12\u文件\u路径=“/MyProject.p12”@Jescanellas我从.p12文件中获得了私钥,并将其传递到凭证中(setServiceAccountPrivateKey)。我已经提到了这个答案。不要使用那个帖子,因为它是从2013年开始的,而且已经过时了。尝试从同一个站点复制步骤3授权。@Jescanella我可以使用该快速启动创建课程。他们使用了OAuth客户端ID。但我的问题不同。我想使用服务帐户,因为它使用机器人帐户启用服务器到服务器、应用程序级身份验证。谢谢您的回答。你能消除我的两个疑虑吗?1) 我需要在我的用户的google教室中创建课程/班级。我可以在哪里指定他们的电子邮件ID/所有者ID?2) 当我执行这段代码时,我得到了“系统无法调整指定的路径”。我为路径指定了限定名称(projectname/src/main/resources)。如何解决这个问题?1)您是从API还是从Web界面创建课程?2) 关于路径位置,您必须使用完整路径,因为它使用的是FileInputStream。例如:/usr/local/bin/home/userName/myProjects/java/IntellijProjects/src/main/resources/service
GoogleCredential credential2 = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("example@project.iam.gserviceaccount.com")
.setServiceAccountScopes(SCOPES)
.setServiceAccountUser("my_email@example.com")
.setServiceAccountPrivateKeyFromP12File(new File(KEY_FILE_LOCATION)).build();