Android - 改造 2 - 验证器结果
Android - Retrofit 2 - Authenticator Result
我正在尝试使用 Retrofit (2.0.0-beta3),但是当使用 Authenticator 添加令牌时,我似乎无法从同步调用中获取数据。我们在 back-end 上的登录只显示了很多登录尝试,但我无法从 body 获取数据以实际添加到 header.
public static class TokenAuthenticator implements Authenticator {
@Override
public Request authenticate(Route route, Response response) throws IOException {
// Refresh your access_token using a synchronous api request
UserService userService = createService(UserService.class);
Call<Session> call = userService.emailLogin(new Credentials("handle", "pass"));
// This call is made correctly, as it shows up on the back-end.
Session body = call.execute().body();
// This line is never hit.
Logger.d("Session token: " + body.token);
// Add new header to rejected request and retry it
return response.request().newBuilder()
.header("Auth-Token", body.token)
.build();
}
}
我不太确定为什么它甚至没有打印出任何东西。任何有关如何解决此问题的提示都将不胜感激,感谢您花时间提供帮助。
这些是我一直在阅读的有关如何实施 Retrofit 的资源。
使用身份验证器:
使用 Retrofit 2 进行同步调用:
我有类似的验证器,它适用于 2.0.0-beta2。
如果您从 Authenticator 获得大量登录尝试,我建议您确保在进行同步调用时,您没有在该调用中使用 Authenticator。
如果你的 "emailLogin" 也失败了,那可能会陷入循环。
我还建议添加 loggingInterceptor 以查看到服务器的所有流量:
我设法使用 TokenAuthenticator 和拦截器获得了一个不错的解决方案,我想我会分享这个想法,因为它可能对其他人有所帮助。
Adding 'TokenInterceptor' class 处理将令牌添加到 header 是令牌存在,而 'TokenAuthenticator' class 处理以下情况没有令牌,我们需要生成一个。
我确信有一些更好的方法来实现它,但我认为这是一个很好的起点。
public static class TokenAuthenticator implements Authenticator {
@Override
public Request authenticate( Route route, Response response) throws IOException {
...
Session body = call.execute().body();
Logger.d("Session token: " + body.token);
// Storing the token somewhere.
session.token = body.token;
...
}
private static class TokenInterceptor implements Interceptor {
@Override
public Response intercept( Chain chain ) throws IOException {
Request originalRequest = chain.request();
// Nothing to add to intercepted request if:
// a) Authorization value is empty because user is not logged in yet
// b) There is already a header with updated Authorization value
if (authorizationTokenIsEmpty() || alreadyHasAuthorizationHeader(originalRequest)) {
return chain.proceed(originalRequest);
}
// Add authorization header with updated authorization value to intercepted request
Request authorisedRequest = originalRequest.newBuilder()
.header("Auth-Token", session.token )
.build();
return chain.proceed(authorisedRequest);
}
}
来源:
我知道这是一个迟到的答案,但对于仍然想知道如何使用 Retrofit 2 Authenticator 添加/刷新令牌的人来说,这是一个可行的解决方案:
注意:preferenceHelper 是您的首选项管理器class,您可以在其中set/get共享首选项。
public class AuthenticationHelper implements Authenticator {
private static final String HEADER_AUTHORIZATION = "Authorization";
private static final int REFRESH_TOKEN_FAIL = 403;
private Context context;
AuthenticationHelper(@ApplicationContext Context context) {
this.context = context;
}
@Override
public Request authenticate(@NonNull Route route, @NonNull Response response) throws IOException {
// We need to have a token in order to refresh it.
String token = preferencesHelper.getAccessToken();
if (token == null)
return null;
synchronized (this) {
String newToken = preferencesHelper.getAccessToken();
if (newToken == null)
return null;
// Check if the request made was previously made as an authenticated request.
if (response.request().header(HEADER_AUTHORIZATION) != null) {
// If the token has changed since the request was made, use the new token.
if (!newToken.equals(token)) {
return response.request()
.newBuilder()
.removeHeader(HEADER_AUTHORIZATION)
.addHeader(HEADER_AUTHORIZATION, "Bearer " + newToken)
.build();
}
JsonObject refreshObject = new JsonObject();
refreshObject.addProperty("refreshToken", preferencesHelper.getRefreshToken());
retrofit2.Response<UserToken> tokenResponse = apiService.refreshToken(refreshObject).execute();
if (tokenResponse.isSuccessful()) {
UserToken userToken = tokenResponse.body();
if (userToken == null)
return null;
preferencesHelper.saveAccessToken(userToken.getToken());
preferencesHelper.saveRefreshToken(userToken.getRefreshToken());
// Retry the request with the new token.
return response.request()
.newBuilder()
.removeHeader(HEADER_AUTHORIZATION)
.addHeader(HEADER_AUTHORIZATION, "Bearer " + userToken.getToken())
.build();
} else {
if (tokenResponse.code() == REFRESH_TOKEN_FAIL) {
logoutUser();
}
}
}
}
return null;
}
private void logoutUser() {
// logout user
}
}
另请注意:
- preferenceHelper 和 api需要以某种方式提供服务。
- 这不是一个适用于所有系统和 api 的示例,而是一个说明如何使用 Retrofit 2 Authenticator[=22= 添加和刷新令牌的示例]
我正在尝试使用 Retrofit (2.0.0-beta3),但是当使用 Authenticator 添加令牌时,我似乎无法从同步调用中获取数据。我们在 back-end 上的登录只显示了很多登录尝试,但我无法从 body 获取数据以实际添加到 header.
public static class TokenAuthenticator implements Authenticator {
@Override
public Request authenticate(Route route, Response response) throws IOException {
// Refresh your access_token using a synchronous api request
UserService userService = createService(UserService.class);
Call<Session> call = userService.emailLogin(new Credentials("handle", "pass"));
// This call is made correctly, as it shows up on the back-end.
Session body = call.execute().body();
// This line is never hit.
Logger.d("Session token: " + body.token);
// Add new header to rejected request and retry it
return response.request().newBuilder()
.header("Auth-Token", body.token)
.build();
}
}
我不太确定为什么它甚至没有打印出任何东西。任何有关如何解决此问题的提示都将不胜感激,感谢您花时间提供帮助。
这些是我一直在阅读的有关如何实施 Retrofit 的资源。
使用身份验证器:
使用 Retrofit 2 进行同步调用:
我有类似的验证器,它适用于 2.0.0-beta2。
如果您从 Authenticator 获得大量登录尝试,我建议您确保在进行同步调用时,您没有在该调用中使用 Authenticator。 如果你的 "emailLogin" 也失败了,那可能会陷入循环。
我还建议添加 loggingInterceptor 以查看到服务器的所有流量:
我设法使用 TokenAuthenticator 和拦截器获得了一个不错的解决方案,我想我会分享这个想法,因为它可能对其他人有所帮助。
Adding 'TokenInterceptor' class 处理将令牌添加到 header 是令牌存在,而 'TokenAuthenticator' class 处理以下情况没有令牌,我们需要生成一个。
我确信有一些更好的方法来实现它,但我认为这是一个很好的起点。
public static class TokenAuthenticator implements Authenticator {
@Override
public Request authenticate( Route route, Response response) throws IOException {
...
Session body = call.execute().body();
Logger.d("Session token: " + body.token);
// Storing the token somewhere.
session.token = body.token;
...
}
private static class TokenInterceptor implements Interceptor {
@Override
public Response intercept( Chain chain ) throws IOException {
Request originalRequest = chain.request();
// Nothing to add to intercepted request if:
// a) Authorization value is empty because user is not logged in yet
// b) There is already a header with updated Authorization value
if (authorizationTokenIsEmpty() || alreadyHasAuthorizationHeader(originalRequest)) {
return chain.proceed(originalRequest);
}
// Add authorization header with updated authorization value to intercepted request
Request authorisedRequest = originalRequest.newBuilder()
.header("Auth-Token", session.token )
.build();
return chain.proceed(authorisedRequest);
}
}
来源:
我知道这是一个迟到的答案,但对于仍然想知道如何使用 Retrofit 2 Authenticator 添加/刷新令牌的人来说,这是一个可行的解决方案:
注意:preferenceHelper 是您的首选项管理器class,您可以在其中set/get共享首选项。
public class AuthenticationHelper implements Authenticator {
private static final String HEADER_AUTHORIZATION = "Authorization";
private static final int REFRESH_TOKEN_FAIL = 403;
private Context context;
AuthenticationHelper(@ApplicationContext Context context) {
this.context = context;
}
@Override
public Request authenticate(@NonNull Route route, @NonNull Response response) throws IOException {
// We need to have a token in order to refresh it.
String token = preferencesHelper.getAccessToken();
if (token == null)
return null;
synchronized (this) {
String newToken = preferencesHelper.getAccessToken();
if (newToken == null)
return null;
// Check if the request made was previously made as an authenticated request.
if (response.request().header(HEADER_AUTHORIZATION) != null) {
// If the token has changed since the request was made, use the new token.
if (!newToken.equals(token)) {
return response.request()
.newBuilder()
.removeHeader(HEADER_AUTHORIZATION)
.addHeader(HEADER_AUTHORIZATION, "Bearer " + newToken)
.build();
}
JsonObject refreshObject = new JsonObject();
refreshObject.addProperty("refreshToken", preferencesHelper.getRefreshToken());
retrofit2.Response<UserToken> tokenResponse = apiService.refreshToken(refreshObject).execute();
if (tokenResponse.isSuccessful()) {
UserToken userToken = tokenResponse.body();
if (userToken == null)
return null;
preferencesHelper.saveAccessToken(userToken.getToken());
preferencesHelper.saveRefreshToken(userToken.getRefreshToken());
// Retry the request with the new token.
return response.request()
.newBuilder()
.removeHeader(HEADER_AUTHORIZATION)
.addHeader(HEADER_AUTHORIZATION, "Bearer " + userToken.getToken())
.build();
} else {
if (tokenResponse.code() == REFRESH_TOKEN_FAIL) {
logoutUser();
}
}
}
}
return null;
}
private void logoutUser() {
// logout user
}
}
另请注意:
- preferenceHelper 和 api需要以某种方式提供服务。
- 这不是一个适用于所有系统和 api 的示例,而是一个说明如何使用 Retrofit 2 Authenticator[=22= 添加和刷新令牌的示例]