Last active
March 3, 2020 03:09
-
-
Save ivanleoncz/f11fb50d35fa1f2b9698bfb06aedcbcd to your computer and use it in GitHub Desktop.
Android Login app, using Self-Signed SSL Certificate. Later on, I'll create a project at GitHub, with the whole App (explanations and details).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<layout> | |
<data> | |
<variable | |
name="handler" | |
type="com.ivanlmj.myapp.LoginScreen" /> | |
</data> | |
<LinearLayout | |
android:orientation="vertical" | |
xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:tools="http://schemas.android.com/tools" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:background="#1a75ff" | |
tools:context=".LoginScreen"> | |
<LinearLayout | |
android:orientation="vertical" | |
android:layout_marginTop="25dp" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content"> | |
<LinearLayout | |
android:orientation="horizontal" | |
android:layout_width="wrap_content" | |
android:layout_height="150dp" | |
android:layout_marginStart="0dp" | |
android:layout_marginLeft="0dp"> | |
<ImageView | |
android:layout_width="110dp" | |
android:layout_height="wrap_content" | |
android:layout_marginTop="10dp" | |
android:layout_marginStart="30dp" | |
android:layout_marginLeft="0dp" | |
android:scaleX="0.8" | |
android:scaleY="0.8" | |
android:src="@drawable/an_image" <!-- must store an image inside ot the drawable directory --> | |
tools:ignore="ContentDescription" /> | |
<TextView | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:layout_marginTop="60dp" | |
android:layout_marginStart="10dp" | |
android:layout_marginLeft="0dp" | |
android:text="MyApp" | |
android:textSize="34sp" | |
android:textColor="#ffffff"/> | |
</LinearLayout> | |
<LinearLayout | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:background="#1a75ff"> | |
<TextView | |
android:layout_width="match_parent" | |
android:layout_height="50dp" | |
android:layout_marginTop="20dp" | |
android:gravity="center" | |
android:text="WELCOME" | |
android:textColor="#ffffff" | |
android:textSize="25sp"/> | |
</LinearLayout> | |
</LinearLayout> | |
<LinearLayout | |
android:orientation="vertical" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent"> | |
<EditText | |
android:id="@+id/tjs_login_screen_usuario" | |
android:layout_marginTop="30dp" | |
android:layout_gravity="center" | |
android:layout_height="42dp" | |
android:layout_width="270dp" | |
android:ems="12" | |
android:hint="@string/login_text_user" | |
android:inputType="text" | |
android:textSize="15sp" | |
android:textColorHint="#ffffff"/> | |
<EditText | |
android:id="@+id/tjs_login_screen_contraseña" | |
android:layout_marginTop="10dp" | |
android:layout_gravity="center" | |
android:layout_height="42dp" | |
android:layout_width="270dp" | |
android:ems="12" | |
android:hint="@string/login_text_password" | |
android:inputType="textPassword" | |
android:textSize="15sp" | |
android:textColorHint="#ffffff"/> | |
<Button | |
android:id="@+id/tjs_login_screen_button" | |
android:layout_marginTop="20dp" | |
android:layout_marginStart="0dp" | |
android:layout_marginLeft="0dp" | |
android:layout_gravity="center" | |
android:layout_width="270dp" | |
android:layout_height="80dp" | |
android:textColor="#ffffff" | |
android:onClick="login" | |
android:text="@string/login_button_name" | |
android:textSize="16sp"/> | |
</LinearLayout> | |
</LinearLayout> | |
</layout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ivanlmj.myapp; | |
import android.content.Context; | |
import android.os.Bundle; | |
import android.support.v7.app.AppCompatActivity; | |
import android.util.Log; | |
import android.view.View; | |
import android.widget.EditText; | |
import android.widget.Toast; | |
import com.android.volley.Request; | |
import com.android.volley.RequestQueue; | |
import com.android.volley.Response; | |
import com.android.volley.VolleyError; | |
import com.android.volley.toolbox.HurlStack; | |
import com.android.volley.toolbox.StringRequest; | |
import com.android.volley.toolbox.Volley; | |
import java.io.InputStream; | |
import java.security.KeyStore; | |
import java.security.cert.Certificate; | |
import java.security.cert.CertificateFactory; | |
import java.util.HashMap; | |
import java.util.Map; | |
import javax.net.ssl.SSLContext; | |
import javax.net.ssl.SSLSocketFactory; | |
import javax.net.ssl.TrustManagerFactory; | |
public class LoginScreenTest extends AppCompatActivity { | |
HurlStack hurlStack = null; | |
EditText username = null; | |
EditText password = null; | |
@Override | |
public void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_1_login_screen); | |
username = (EditText) findViewById(R.id.tjs_login_screen_usuario); | |
password = (EditText) findViewById(R.id.tjs_login_screen_contraseña); | |
try { | |
/* To understand the concept about Self-Signed Certificates, Custom TrustManagers, etc. | |
CertificateFactory: https://docs.oracle.com/javase/7/docs/api/java/security/cert/CertificateFactory.html | |
Certificate: https://docs.oracle.com/javase/7/docs/api/java/security/cert/Certificate.html | |
KeyStore: https://docs.oracle.com/javase/7/docs/api/java/security/KeyStore.html | |
KeyManagerFactory: https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/KeyManagerFactory.html | |
TrustManagerFactory: http://docs.oracle.com/javase/7/docs/api/javax/net/ssl/TrustManagerFactory.html | |
SSLContext: https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLContext.html | |
SSLSocketFactory: https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLSocketFactory.html | |
*/ | |
Context myContext = getApplicationContext(); | |
InputStream inStream = myContext.getResources().openRawResource(R.raw.tdmssl); | |
// Use the .crt file obtained via this script: https://gist.github.com/ivanlmj/a6a93dd142fb623d01262303d5bd8074 | |
CertificateFactory cf = CertificateFactory.getInstance("X.509"); | |
Certificate ca = cf.generateCertificate(inStream); | |
inStream.close(); | |
String keyStoreType = KeyStore.getDefaultType(); | |
KeyStore ks = KeyStore.getInstance(keyStoreType); | |
ks.load(null, null); | |
ks.setCertificateEntry("ca", ca); | |
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); | |
tmf.init(ks); | |
SSLContext sslContext = SSLContext.getInstance("TLS"); | |
sslContext.init(null, tmf.getTrustManagers(), null); | |
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); | |
hurlStack = new HurlStack(null, sslSocketFactory); | |
} catch (Exception e){ | |
Log.d("my_app","LoginScreen.java - SSL Exception: " + e.toString()); | |
e.printStackTrace(); | |
} | |
} | |
public void login(View view) { | |
setProgressBarIndeterminateVisibility(true); | |
RequestQueue queue = Volley.newRequestQueue(this, hurlStack); | |
// In this example, I'm uing Python FLASK with MySQL. | |
// Basically, FLASK performs a query, looking for user + pass in a database (table). | |
final String url = "https://127.0.0.1:5000/login"; | |
StringRequest postRequest = new StringRequest(Request.Method.POST, url, | |
new Response.Listener<String>() | |
{ | |
@Override | |
public void onResponse(String response) { | |
Log.d("my_app", "LoginScreen.java - Request status: SUCCESSFUL"); | |
Log.d("my_app", "LoginScreen.java - Response content:" + response); | |
if (response.equals("ok")) { | |
Log.d("my_app", "LoginScreen.java - Login status: SUCCESSFUL"); | |
Log.d("tjs_app", "LoginScreen.java - Authenticated User: " + username.getText().toString().trim()); | |
Toast.makeText(getApplicationContext(), "Login OK!",Toast.LENGTH_SHORT).show(); | |
} else { | |
Log.d("my_app", "LoginScreen.java - Login status: FAIL"); | |
Log.d("my_app", "LoginScreen.java - Authentication attempt from: " + username.getText().toString().trim()); | |
Toast.makeText(getApplicationContext(), "Check User or Password.",Toast.LENGTH_SHORT).show(); | |
} | |
} | |
}, | |
new Response.ErrorListener() | |
{ | |
@Override | |
public void onErrorResponse(VolleyError error) { | |
Log.d("my_app", "LoginScreen.java - Request status: FAIL"); | |
Log.d("my_app", "LoginScreen.java - Response content:" + error); | |
Toast.makeText(getApplicationContext(), "Check your internet connection.",Toast.LENGTH_SHORT).show(); | |
} | |
} | |
) { | |
@Override | |
protected Map<String, String> getParams() | |
{ | |
Map<String, String> params = new HashMap<String, String>(); | |
params.put("username", username.getText().toString().trim()); | |
params.put("password", password.getText().toString().trim()); | |
return params; | |
} | |
}; | |
queue.add(postRequest); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
HI @ivanlmj any update on this?