3

私の設定が正しいことを誰かに知らせるために、いくつかの情報が欠けている可能性があることを前もってお詫びします。他に何を指定する必要があるか教えてください。私は大学で働いており、Google を通じて学生のメール アカウントをホストしています。パスワードを忘れてリセットしなければならないことはかなり頻繁に発生します。自分自身に関する十分な情報を確認した場合にパスワードを設定できるページがあります。私たちが使用してきたコードは、ディレクトリ API を優先して Google によって廃止されました。私はこの古いコードを変換する任務を負っています:

//changes a password
@Override
public void reset ( final String username, final String password ) throws ResetException
{
    try
    {
        Validate.notEmpty( username );
        Validate.notEmpty( password );

        final AppsForYourDomainClient client = ClientFactory.getClient();  //admin-user account
        final UserEntry entry = client.retrieveUser( username );
        Validate.isTrue( !entry.getLogin().getSuspended(), "Account is suspended." );
        entry.getLogin().setPassword( password );
        client.updateUser( username, entry );
    }
    catch ( final Exception e )
    {
        throw new ResetException( e );
    }
}

新しい API を使用して何かに変換します。多くのドキュメントといくつかの例を読みましたが、どれも役に立たないようです。管理コンソールを介して管理者アカウントで Admin SDK を有効にし、アプリを登録して、開発者コンソールからキーを取得しましたが、必要なものを返すリクエストを受け取ることができないようです。現在、ユーザーのリストを取得しようとしています。

public void testList () throws Exception
{
    InputStream is = null;
    final String accessToken = getAccessToken();
    final NetHttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    final JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
    final File p12 = new File( GoogleResetterTest.class.getClassLoader().getResource("ead05e56893a.p12").toURI() );
    GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
                                        .setJsonFactory(jsonFactory)
                                        .setServiceAccountId( SERVICE_ACCOUNT_EMAIL )
                                        .setServiceAccountScopes( PlusScopes.all() )
                                        .setServiceAccountPrivateKeyFromP12File( p12 )  //password: notasecret
                                        .setClientSecrets(CLIENT_ID, CLIENT_SECRET)
                                        .build();
    final Directory dir = new Directory.Builder( httpTransport, jsonFactory, credential)
                                                .setApplicationName( "API Project" )
                                                .build();
    final Directory.Users diruser = dir.users();
    final Directory.Users.List diruserlist = diruser.list().setDomain( EMAIL_DOMAIN );
    final HttpResponse response = diruserlist.executeUsingHead();
    is = response.getContent();
    StringWriter writer = new StringWriter();
    IOUtils.copy(is, writer, "UTF-8");
    String theString = writer.toString();
    IOUtils.closeQuietly( is );
}

diruserlist.executeUsingHead(); で 行私はこの応答を受け取ります:

com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request { "error" : "invalid_grant" }

私には、これはかなり役に立たないエラー メッセージです。

この全体を複雑にしすぎていると思わずにはいられません。私は元のコードのシンプルさが気に入りましたが、新しい API に対するいくつかの反応は、より複雑であると批判しています。誰かがこれを行う必要があり、これを修正するための正しいパスを教えてもらえますか?

4

1 に答える 1

5

質問を削除したり編集したりするのではなく、自分の質問に答えて解決済みとしてマークします。

ここでいくつかのことが行われ、私が間違っていたことがいくつかありました。ほとんどの場合、ビルダーに関するドキュメントが貧弱であるか存在しないためです。これが私がしなければならなかったことです:

管理コンソール( https://admin.google.com/ )で設定します。

  1. 使用しようとしているアカウントに、このドメインのスーパー管理者アクセス権があることを確認します (管理者の役割 -> スーパー管理者)。
  2. [セキュリティ] タブで API アクセスを有効にします。(セキュリティ -> API リファレンス -> API アクセス -> API アクセスを有効にする)
  3. 開発者コンソール(下記)でセットアップを行います
  4. アプリへのアクセスを追加します (セキュリティ -> 詳細設定 -> 認証 -> OAuth クライアント アクセスの管理
  5. 開発者コンソールからこれらのスコープをクライアントに付与します (角括弧なし):
    • [https]://www.googleapis.com/auth/admin.directory.group
    • [https]://www.googleapis.com/auth/admin.directory.user
    • [https]://www.googleapis.com/auth/admin.directory.user.readonly
    • [https]://www.googleapis.com/auth/admin.directory.user.security

これらのスコープのすべてが必要なわけではありませんが、有効にしたものです

開発者コンソール( https://console.developers.google.com/ )でセットアップします。

  1. プロジェクトを作成
  2. プロジェクトの Admin SDK を有効にする (API & 認証 -> API)
  3. サービス アカウントとして OAuth クライアントを作成します (API & 認証 -> 資格情報 -> 新しいクライアント ID の作成)。
  4. そのクライアント ID を管理コンソールに戻します (上記の手順 5)。
  5. Java アプリが読み取れる p12 キーをダウンロードします。(API & 認証 -> 資格情報 -> 新しい P12 キーを生成)

これでやっと Java を書けるようになりました!

import java.io.*;
import java.net.*;
import java.util.*;

import java.security.GeneralSecurityException;
import java.security.MessageDigest;

import javax.xml.bind.DatatypeConverter;

import com.google.api.services.admin.directory.*;
import com.google.api.services.admin.directory.model.*;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;

public class PasswordResetter
{
    public void changePassword( final String username, final String newPassword ) throws Exception
    {
        final Directory dir = getDirectory();
        final User studentUser = updatePassword( getUser( dir, DOMAIN_NAME, username ), password );
        updateDirectory( dir, studentUser );
    }

    private Directory getDirectory() throws IOException, GeneralSecurityException, URISyntaxException
    {
        final NetHttpTransport httpTransport = new NetHttpTransport();
        final JacksonFactory jsonFactory = new JacksonFactory();
        final File p12 = new File( P12_FILENAME );
        final GoogleCredential credential = new GoogleCredential.Builder()
                                                                    .setTransport(httpTransport)
                                                                    .setJsonFactory(jsonFactory)
                                                                    .setServiceAccountUser( SUPER_USER_EMAIL )
                                                                    .setServiceAccountId( SERVICE_ACCOUNT_EMAIL_FROM_DEV_CONSOLE ) //the one that ends in "@developer.gserviceaccount.com"
                                                                    .setServiceAccountScopes( getCredentials() )
                                                                    .setServiceAccountPrivateKeyFromP12File( p12 )
                                                                    .build();
        return new Directory.Builder( httpTransport, jsonFactory, null)
                                    .setHttpRequestInitializer( credential )
                                    .setApplicationName( "API Project" )    //Not necessary, but silences a runtime warning using any not-blank string here
                                    .build();
    }

    private List<String> getCredentials()
    {
        final List<String> toReturn = new LinkedList<String>();
        toReturn.add( DirectoryScopes.ADMIN_DIRECTORY_GROUP );
        toReturn.add( DirectoryScopes.ADMIN_DIRECTORY_USER );
        toReturn.add( DirectoryScopes.ADMIN_DIRECTORY_USER_READONLY );
        toReturn.add( DirectoryScopes.ADMIN_DIRECTORY_USER_SECURITY );
        return toReturn;
    }

    private Users getUser( final Directory dir, final String domain, final String username ) throws Exception
    {
        Directory.Users.List diruserlist = dir.users().list()
                                                        .setDomain( domain )
                                                        .setQuery( "email:" + username + "*" );
        return diruserlist.execute();
    }

    private User updatePassword( final User user, final String password ) throws Exception
    {
        final MessageDigest md = MessageDigest.getInstance( "MD5" );    //I've been warned that this is not thread-safe
        final byte[] digested = md.digest( password.getBytes( "UTF-8" ) );
        final String newHashword = DatatypeConverter.printHexBinary( digested );
        return user.setHashFunction("MD5")                              //only accepts MD5, SHA-1, or CRYPT
                    .setPassword( newHashword );
    }

    private void updateDirectory( final Directory dir, final User user ) throws IOException
    {
        final Directory.Users.Update updateRequest = dir.users().update( user.getPrimaryEmail(), user );
        updateRequest.execute();
    }
}

これで、スーパーユーザー アカウントがユーザー名 (メールを定義するため、クエリが定義されます) と新しいパスワードを指定するだけで、それを変更するための優れた方法が得られました。これは完全なクラスではなく、コピーして貼り付けるだけではコンパイルできないことに注意してください。

一歩も飛ばさなかったことを願っています。コンソールには、何かが壊れた場合に備えて取り除くのが怖い追加設定がいくつかあります。うまくいけば、これは将来誰かを助けるでしょう。

于 2014-09-09T20:11:00.380 に答える