我正在做一个辅助项目,我所知道的是我应该使用基本身份验证。由于我没有使用它的经验,因此我在网上找到了一些东西,我想请您征求意见,这是正确的方法吗...
因此,第一件事来自Retrofit的文档:
这是翻新(网络)设置:
public class RetrofitSetup {
public static final String API_BASE_URL = "----";
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
private static Retrofit retrofit = builder.build();
public static <S> S createService(Class<S> serviceClass) {
return createService(serviceClass, null, null);
}
public static <S> S createService(
Class<S> serviceClass, String username, String password) {
if (!TextUtils.isEmpty(username)
&& !TextUtils.isEmpty(password)) {
String authToken = Credentials.basic(username, password);
return createService(serviceClass, authToken);
}
return createService(serviceClass, null);
}
public static <S> S createService(
Class<S> serviceClass, final String authToken) {
if (!TextUtils.isEmpty(authToken)) {
AuthenticationInterceptor interceptor =
new AuthenticationInterceptor(authToken);
if (!httpClient.interceptors().contains(interceptor)) {
httpClient.addInterceptor(interceptor);
builder.client(httpClient.build());
retrofit = builder.build();
}
}
return retrofit.create(serviceClass);
}
}
和身份验证拦截器:
public class AuthenticationInterceptor implements Interceptor {
private String authToken;
public AuthenticationInterceptor(String token) {
this.authToken = token;
}
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request original = chain.request();
Request.Builder builder = original.newBuilder()
.header("Authorization", authToken);
Request request = builder.build();
return chain.proceed(request);
}
}
这是我的RetrofitSerive课:
public interface RetrofitService {
@GET("login")
Call<Void> basicLogin();
@GET("contact")
Call<List<Contacts>> getContacts(@Header("Authorization") String authkey);
@GET("product")
Call<List<Products>> getProducts(@Header("Authorization") String authkey);
}
还有我在网上找到的用于生成身份验证密钥的类:
public class Helper {
public static String getAuthToken(String username, String password) {
byte[] data = new byte[0];
try {
data = (username + ":" + password).getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "Failed to authenticate";
}
return "Basic " + Base64.encodeToString(data, Base64.NO_WRAP);
}
}
我相信这里没有什么可更改的...所以第一件事是登录(检查身份验证),这是我想知道如何正确做的几件事:
private void login(final String username, final String password) {
RetrofitService loginService =
RetrofitSetup.createService(RetrofitService.class, username, password);
Call<Void> call = loginService.basicLogin();
call.enqueue(new Callback<Void>() {
@Override
public void onResponse(@NonNull Call<Void> call, @NonNull Response<Void> response) {
progressBar.setVisibility(View.GONE);
if (response.isSuccessful()) {
// user object available
editor.putString("username", username);
editor.putString("password", password);
editor.apply();
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
} else {
Toast.makeText(LoginActivity.this, response.message(), Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
progressBar.setVisibility(View.GONE);
Toast.makeText(LoginActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
如果响应成功,我会将这些凭据保存在SharedPreferences中。
下一页应该调用另一个请求,所以我想同时发送用户名/密码或身份验证密钥是否有区别?
这是我的方法:
private void getContacts() {
prefs = getActivity().getSharedPreferences(KEY, MODE_PRIVATE);
String username = prefs.getString("username", null);
String password = prefs.getString("password", null);
RetrofitService loginService =
RetrofitSetup.createService(RetrofitService.class, Helper.getAuthToken(username, password));
Call<List<Contacts>> call = loginService.getContacts(Helper.getAuthToken(username, password));
call.enqueue(new Callback<List<Contacts>>() {
@Override
public void onResponse(@NonNull Call<List<Contacts>> call, @NonNull Response<List<Contacts>> response) {
if (response.isSuccessful()) {
kontaktiAdapter.setKontakti(response.body());
} else {
Toast.makeText(getActivity(), response.message(), Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(@NonNull Call<List<Contacts>> call, @NonNull Throwable t) {
Toast.makeText(getActivity(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
因此,在此呼叫中,不是将用户名/密码发送到RetrofitSetup.createService,而是从SharedPreferences发送带有用户名和密码的Helper.getAuthToken(用户名,密码)。
这是正确的方法吗?如果退出该应用程序,则在登录屏幕中,我正在检查SharedPreferences是否包含用户名/密码,并尝试使用这些参数登录。不包含它们,因此用户将无法登录,他/她将不得不再次输入这些信息...
您对此有何看法,有什么我应该做不同的事情吗? 问候!
答案 0 :(得分:0)
这是迄今为止我尝试过的最简单的“基本身份验证”方法。
使用以下代码生成auth标头(API /存储库类)
var basic = Credentials.basic("YOUR_USERNAME", "YOUR_PASSWORD")
将此作为标头传递到Web服务调用(API /存储库类)
var retrofitCall = myWebservice.getNewsFeed(basic)
添加基本标头作为参数(Retrofit Web服务接口类)
@GET("newsfeed/daily")
fun getNewsFeed(@Header("Authorization") h1:String):Call<NewsFeedResponse>
对不起,我的代码在Kotlin中,但是可以轻松地翻译成Java。