我要事先道歉,我可能会遗漏一些信息,让任何人都知道我的设置是正确的。请告诉我还需要指明的内容。 我在一所大学工作,我们通过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 );
}
}
使用他们的新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错误请求 { “错误”:“invalid_grant” }
对我而言,这是一个非常无用的错误消息,因为似乎有4或5个部分可能出错导致该响应。
我可以帮助以为我让整件事变得太复杂了。我喜欢原始代码的简单性,对新API的一些回应批评它更复杂。有没有人必须这样做,并指出我正确的道路来解决这个问题?
答案 0 :(得分:1)
我将回答我自己的问题并将其标记为已解决,而不是删除问题或进行编辑。
这里有一些事情在发生,有些事情我错了。主要是因为关于构建器的文档很差或根本不存在。这就是我必须做的事情:
在管理控制台上设置(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();
}
}
现在我有一个很好的方法让我的超级用户帐户只提供一个用户名(定义他们的电子邮件因此查询)和一个新密码,并为它们更改它。请注意,这不是完整的类,不能仅通过复制粘贴进行编译。
我当然希望我没有跳过一步。我在我的游戏机中有一些额外的设置,我害怕在它破坏的情况下摆脱它。希望这将有助于将来的其他人。