Ste*_*ole 3 java google-directory-api google-oauth-java-client
我要提前道歉,因为我可能会丢失一些信息,以便让任何人知道我的设置是正确的。请让我知道我还需要指定什么。我在一所大学工作,我们通过 Google 托管学生电子邮件帐户。他们经常忘记密码并不得不重置密码。如果他们验证了足够的有关自己的信息,我们有一个页面可以设置他们的密码。Google 已弃用我们一直使用的代码,转而使用他们的 Directory API。我的任务是转换这个旧代码:
//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 );
}
}
Run Code Online (Sandbox Code Playgroud)
使用他们的新 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 );
}
Run Code Online (Sandbox Code Playgroud)
在 diruserlist.executeUsingHead() 上;我得到这样的回复:
com.google.api.client.auth.oauth2.TokenResponseException:400错误请求{“错误”:“invalid_grant”}
对我来说,这是一个非常无用的错误消息,因为似乎有 4 或 5 个部分可能出错而导致该响应。
我不禁觉得我把这整件事搞得太复杂了。我喜欢原始代码的简单性,但对新 API 的一些回应批评它更复杂。有没有人必须这样做并且可以指出我正确的路径来解决这个问题?
我将回答我自己的问题并将其标记为已解决,而不是删除问题或编辑它。
这里有一些事情在起作用,有些事情我也搞错了。主要是因为有关构建器的文档很差或不存在。这是我必须做的:
在管理控制台( https://admin.google.com/ )上设置
并非所有这些范围都是必要的,但这是我启用的
在开发者控制台( https://console.developers.google.com/ )上设置
现在我终于可以写一些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();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我的超级用户帐户有一个很好的方法,只需提供一个用户名(定义他们的电子邮件,从而进行查询)和一个新密码,它就会为他们更改它。请注意,这不是完整的类,并且不能仅通过复制粘贴进行编译。
我当然希望我没有跳过任何一步。我的控制台中有一些额外的设置,我担心它们会损坏某些东西,因此我担心它们会被删除。希望这能帮助其他人在未来。
| 归档时间: |
|
| 查看次数: |
7926 次 |
| 最近记录: |