我一直在使用 Google OAuth 让用户授权访问我的Web应用程序的日历服务。成功3-legged auth flow后,我将所有用户的凭据存储在应用服务器上的公共文件中。下次应用程序需要使用该服务时,它将检查凭据是否存在,如果是,则认为它们是有效的
代码就像那样
@Override
public void _authorize(String userId) throws IOException {
// Check if user has already authorised the service.
Credential credents = flow.loadCredential(userId);
// Checking if the given user is not authorized
if (credents == null) {
//Create credentials now. user will be redirected to authorise
try {
//Creating a LocalServer Receiver
// Getting the redirect URI
// Creating a new authorization URL
// Setting the redirect URI
// Building the authorization URL
// Receiving authorization code
// Exchanging it for an access token
// Storing the credentials for later access
credents = flow.createAndStoreCredential(response, id);
} finally {
// Releasing resources
}
} else {
// Assume the credentials are valid. so there's nothing left to do here, let's get that client
//Update: Nooooooot! the user might have revoked the authorization, so credents != null BUT they are invalid
//TODO: handle an Exception here, and manage the revoked credentials
}
// Setting up the calendar service client
client = new com.google.api.services.calendar.Calendar.Builder(httpTransport, jsonFactory, credents).setApplicationName(APPLICATION_NAME)
.build();
}
只要用户永远不会改变主意,这种方法就可以了。但是,如果用户使用Google帐户安全选项决定 manually revoke 授权,则com.google.api.services.calendar.Calendar检索将失败。
我的问题是:
flow.createAndStoreCredential
,他们会被覆盖吗?或者我必须先删除旧的? (怎么样?)答案 0 :(得分:2)
您可以使用refreshToken()方法。见例:
// Fetch credential using the GoogleAuthorizationCodeFlow
GoogleAuthorizationCodeFlow authorizationCodeFlow;
Credential credential = authorizationCodeFlow.loadCredential(userId);
if (credential != null) {
try {
// refresh the credential to see if the refresh token is still valid
credential.refreshToken();
System.out.println("Refreshed: expires in: " + credential.getExpiresInSeconds());
} catch (TokenResponseException e) {
// process exception here.
// This will catch the Exception.
// This Exception contains the HTTP status and reason etc.
// In case of a revoke, this will throw something like a 401 - "invalid_grant"
return;
}
} else {
// No credential yet known.
// Flow for creating a new credential here
}
修改强> 如果您确实有一个无效的刷新令牌并且想要续订它,那么您需要重复您在第一时间所做的步骤以获取凭据。所以:
无需删除旧凭据。但如果你想明确这样做,那就有可能。 类似的东西:
// This userId is obviously the same as you used to create the credential
String userId = "john.doe";
authorizationCodeFlow.getDataStore().delete(userId);
答案 1 :(得分:1)
您可以使用端点https://www.googleapis.com/oauth2/v1/tokeninfo来确定OAuth2令牌是否仍然有效。有关详细信息,请参阅OAuth2 guide。
答案 2 :(得分:0)
回答第一个问题:
使用服务对象从Google日历中检索日历项时,会自动验证令牌。当它们无效时,它们将自动刷新,并存储在您提供给流程的数据存储区中。
这也可以手动完成。令牌有效期为3600秒(一小时)。检索令牌时,您将获得此值以及发布时的时间戳。您可以手动确定令牌是否有效。如果无效,请调用以下异步方法。
await credents.RefreshtokenAsync(CancellationToken.None);
此功能可获取新鲜令牌,并将其存储在您提供的数据存储中。
答案 3 :(得分:0)
使用tokeninfo检查令牌以及令牌是否无效: - 从数据存储中删除凭据 - 调用新的身份验证
protected void doGet(HttpServletRequest request,HttpServletResponse response)抛出IOException,ServletException { UserService userService = UserServiceFactory.getUserService();
if (userService.isUserLoggedIn()) {
User user = userService.getCurrentUser();
log.info(String.format("LoggedUser: %s %s", user.getEmail(), user.getUserId()));
Credential credential = this.getCredential();
Tokeninfo tokenInfo = OAuth2Utils.getTokenInfo(credential, null);
if (tokenInfo != null)
log.info(String.format("Token expires in: %d", tokenInfo.getExpiresIn()));
else {
OAuth2Utils.deleteCredential(user.getUserId());
response.sendRedirect(request.getRequestURI()); // recall this servlet to require new user authorization
return;
}
}
public static Tokeninfo getTokenInfo(Credential credential,String accessToken){ Oauth2 service = new Oauth2.Builder(new NetHttpTransport(),Constant.JSON_FACTORY,credential).setApplicationName(Constant.APP_NAME).build(); Tokeninfo tokenInfo = null; 尝试{ tokenInfo = service.tokeninfo()。setAccessToken(accessToken == null?credential.getAccessToken():accessToken).execute(); } catch(IOException e){ log.warning(“发生错误:”+ e); } return tokenInfo; }