I am trying a login to a server from Android using Retrofit 2. The API for login is working fine in postman (REST client tool) and getting the response like this
[
{
"success": true,
"message": "Enjoy your token!",
"token": "ABCDEFGHIJKLMNOPQESTUVWXYZ",
"log_id": 1234
}
]
But when I tried with the same flow in Android using Retrofit 2 I m getting different output. This is the log snippet for Android when I call Login API in android.
08-12 11:27:29.299 13457-13593/com.example.user.retrofit D/OkHttp: --> POST http://www.test.com/api/authenticate http/1.1
08-12 11:27:29.300 13457-13593/com.example.user.retrofit D/OkHttp: Content-Type: application/json; charset=UTF-8
Content-Length: 181
Accept: application/json
08-12 11:27:29.301 13457-13593/com.example.user.retrofit D/OkHttp: {"data":"VTJGc2RHVmtYMWdNYj1E"}
--> END POST (181-byte body)
08-12 11:27:35.087 13457-13593/com.example.user.retrofit D/OkHttp: <-- 200 https://www.test.com/api/authenticate (5785ms)
content-type: text/html
cache-control: no-cache
content-length: 210
x-iinfo: 7-48850495-0 0NNN RT(1534053455965 0) q(0 -1 -1 5) r(0 -1) B10(4,289,0) U5
set-cookie: visid_incap_1748743=CMWA4MwbTNGL5G0hHnAZBE/Mb1sAAAAAQUIPAAAAAADakNS0YTyMIvKXh6Zh0cjx; expires=Sun, 11 Aug 2019 09:31:38 GMT; path=/; Domain=.test.com
set-cookie: incap_ses_705_1748743=z9lvBtlqCnHsdSffSqrICU/Mb1sAAAAAgZliHJa2lcppoIp0iVqtng==; path=/; Domain=.test.com
08-12 11:27:35.088 13457-13593/com.example.user.retrofit D/OkHttp: <html>
<head>
<META NAME="robots" CONTENT="noindex,nofollow">
<script src="/_Incapsula_Resource?SWJIYLWA=5074a744e2e3d891814e9a2dace20bd4,719d34d31c8e3a6e6fffd425f7e032f3">
08-12 11:27:35.089 13457-13593/com.example.user.retrofit D/OkHttp: </script>
<body>
</body></html>
<-- END HTTP (210-byte body)
Android Activity class for login is as below
package com.example.user.retrofit;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import java.io.IOException;
import java.security.cert.CertificateException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.Body;
import retrofit2.http.Headers;
import retrofit2.http.POST;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.test.com/api/")
.addConverterFactory(GsonConverterFactory.create())
.client(getUnsafeOkHttpClient().build())
.build();
LoginRequest login = new LoginRequest();
login.setData("VTJGc2RHVmtYMWdNYj1E");
GitHubService service = retrofit.create(GitHubService.class);
service.login(login).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
Log.d("OnResponse", response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e("OnFailure", "Failed", t);
}
});
}
public static OkHttpClient.Builder getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
// add logging as last interceptor
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
builder.addInterceptor(logging); // <-- this is the important line!
return builder;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public interface GitHubService {
@Headers({
"Accept: application/json"
})
@POST("authenticate")
Call<ResponseBody> login(@Body LoginRequest user);
}
private static class LoginRequest {
private String data;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
}
Please anybody can tell me why I am getting HTML content when I tried from Android. What needs to be done to get the correct JSON response?
发送User-Agent:“您的应用名称”标头主体Alsoo
Thank you for the question, this problem is related to the server side framework like laravel php which protects unauthorized access and prevents from unknown client requests( in your case your retrofit is the client). It checks for the "User-Agent" header value, if not supplied captcha error is thrown ". This also happens when you avoid the "sessions cookies" sent by the server. Browser can handle and maintaining sessions cookies very easily but retrofit seems to have problem maintaining the sessions cookies by default.
1.Add a new interceptor to your okhttpClientBuilder
okhttpClientBuilder.addInterceptor(new Interceptor(){
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Response response;
Request request = original.newBuilder()
.addHeader("User-Agent", System.getProperty("http.agent"))//important
.addHeader("Accept", "application/json")
.method(original.method(), original.body())
.build();
request.headers().getAll("Cookie"));
response= chain.proceed(request);
response.headers().getAll("Set-Cookie"));
return response;
}
});
2.In your android studio-> build.gradle file(project level) , find below similar structure in the build.gradle file and add a maven repo like below
allprojects {
repositories {
//other configs.....
//add this if not present
maven { url "https://jitpack.io" }
}
}
3.Add the dependency in your build.gradle file (app level)
dependencies {
//other important dependency....
//add this dependency for handling cookies
implementation 'com.github.franmontiel:PersistentCookieJar:v1.0.1'
}
Sync your project
Add this below code after creating your okhttpClientBuilder
CookieJar cookieJar1=new PersistentCookieJar(new SetCookieCache(),new SharedPrefsCookiePersistor(context)); okhttpClientBuilder.cookieJar(cookieJar1);//important okhttpClientBuilder.build();//returns OkHttpClient instance
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.