我正在做一个小项目,我所知道的就是我应该使用基本认证。由于我没有使用它的经验,我在网上找到了一些东西,我想征求你的意见,这是正确的方法吗…
所以,第一件事来自于Retrofit的文档:
这是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);
}
和我在网上找到的生成auth key的类:
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是否包含用户名/密码,并尝试使用这些参数登录。如果我想注销,我从SharedPreferences中清除这些参数,这样下次用户打开应用程序时,SharedPreferences将不会包含它们,所以用户将不会登录,他/她将不得不再次键入这些参数……
你对此有什么看法,有没有什么我应该做的不一样的?致以问候!
发布于 2018-10-09 14:21:49
到目前为止,这是我尝试过的最简单的“基本身份验证”方法。
使用以下代码生成auth头(API/Repository类)
var basic = Credentials.basic("YOUR_USERNAME", "YOUR_PASSWORD")
将其作为头部传递给the服务调用(API/Repository类)
var retrofitCall = myWebservice.getNewsFeed(basic)
添加基本头部作为参数(Retrofit Webservice接口类)
@GET("newsfeed/daily")
fun getNewsFeed(@Header("Authorization") h1:String):Call<NewsFeedResponse>
对不起,我的代码是Kotlin的,但是可以很容易地翻译成Java。
https://stackoverflow.com/questions/51579299
复制相似问题