2014-08-27 62 views
1

我要提前道歉,我很可能會遺漏一些信息,讓任何人知道我的設置是正確的。請讓我知道我還需要指定什麼。 我在我們通過Google託管學生電子郵件帳戶的大學工作。它經常發生,他們忘記了密碼,並必須重置。如果他們驗證了有關他們自己的足夠信息,我們有一個頁面可以設置他們的密碼。我們使用的代碼已被谷歌棄用,轉而使用他們的Directory API。我一直負責將這個舊代碼轉換成:使用其新API的東西。我已經閱讀了大量的文檔和幾個例子,但他們似乎都沒有幫助。我已經通過他們的管理控制檯爲我們的管理員帳戶啓用了Admin SDK,並註冊了我的應用,並從他們的開發者控制檯獲得了密鑰,但我似乎無法得到任何我想要的內容。現在我只是想獲得用戶列表:如何使用Google的Directory API使用Java更改用戶的密碼?

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錯誤的請求 { 「錯誤」: 「invalid_grant」 }

對我來說這是一個非常無用的錯誤信息,因爲似乎有4或5件可能導致錯誤的響應。

我可以幫助我認爲我讓整個事情太複雜。我喜歡原始代碼的簡單性,對新API的一些反應批評它更復雜。有沒有人必須這樣做,並可以指出我正確的方法來解決這個問題?

回答

1

我要回答我自己的問題,並將其標記爲已解決,而不是刪除問題或進行編輯。

有一些事情在這裏玩,有些事情我錯了。主要是因爲關於建設者的文件很差或根本不存在。這是我必須做的:

建立在管理控制檯https://admin.google.com/

  1. 確保我試圖使用的帳戶有此網域的超級管理員權限(管理員角色 - >超級管理員)
  2. 在安全選項卡中啓用API訪問。 (安全 - > API參考 - > API訪問權限 - >啓用API訪問
  3. 在開發
  4. DO設置控制檯(如下圖)
  5. 添加訪問我的應用程序(安全 - >高級設置 - >身份驗證 - >管理OAuth客戶端訪問
  6. 授予這些範圍從開發者控制檯我的客戶(不含引號):
    • [HTTPS]://www.googleapis.com/auth/admin.directory.group
    • [HTTPS]: //www.googleapis.com/auth/admin.directory.user
    • [https]://www.googleapis.com/auth/admin.directory.u ser.readonly
    • [https]:// www。googleapis.com/auth/admin.directory.user.security

並非所有這些領域可能是必要的,但它是什麼我已經啓用

設置在開發者控制檯https://console.developers.google.com/

  1. 創建項目
  2. 啓用項目(API的&權威性的Admin SDK - > API)的
  3. 建立OAuth客戶作爲服務帳戶(API的& AUTH - >憑證 - >創建新客戶端ID)
  4. 以客戶端ID回管理控制檯(上述步驟5)
  5. 下載P12關鍵在我的Java應用程序可以閱讀它。 (API & auth - >證書 - >生成新的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(); 
    } 
} 

現在,我有我的超級用戶帳號只提供用戶名(其也定義他們的電子郵件查詢)和一個新的密碼,一個很好的方法,它改變了它爲他們。請注意,這不是完整的類,不會從複製粘貼中編譯。

我當然希望我沒有跳過一步。在我的遊戲機中有一些額外的設置,如果它破壞某些東西,我害怕擺脫它。希望這將有助於未來的其他人。

+0

我跟着你的所有步驟和其他所需的邏輯,但我堅持使用updatePassword方法,因爲它調用getUser,它返回用戶而studentUser是用戶類型如何將用戶轉換爲用戶。請多解釋一下。 – simpleProgrammer 2014-10-09 15:36:01

+0

我想知道這一點 - 用戶!=用戶 – acvcu 2015-04-02 18:53:05

+0

這個答案與https://developers.google.com/identity/protocols/OAuth2ServiceAccount – nacross 2015-06-11 07:41:19

相關問題