0

Today i wanted to implement a login form. The User has to have connection to the internet to login because i want to send the username and the hashed password (sha 512?!) to a server and to get an answer if the username and the password are accepted or not.

The User should be able to store his login but its optional. If the user does not store his login he has to get some kind of session token so he can use the full functionality of the app until he closes the app. If the user stores his login he should be able to automatically login into the app to use the full functionality at any time.

what are the 'best practices' to do the following things:

  1. Checking if the user has connection to the internet or not
  2. Creating a sha 512 hash for the password
  3. Sending the username and the password to the server (save)
  4. Getting a save session token
  5. Storing login information for automatic login after restart

I read something about storing the login in the SharedPreferences but i dont know how i can use it to make a session token if the user does not want to store his login information and i also guess that this is not the most save way.

Mulgard
  • 9,877
  • 34
  • 129
  • 232

1 Answers1

0

Ill try to answer all of your question but be aware that it could not be the 'best practice' you was looking for. It is just one possible way to do it.

1. Checking if the user has connection to the internet or not

First you need to add some permissions into your Manifest.xml:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

Note that for your first question you would just need the first of those permissions. The second permission is needed to connect to the internet when you want to send username and password.

Now you need the ConnectivityManager to get the Network Informations. If the Network Informations contain NetworkInfo.State.CONNECTED = true the mobile device is connected to the internet:

public static boolean isConnectedToInternet(Context context) {
    ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

    if (connectivity != null) {
        NetworkInfo[] info = connectivity.getAllNetworkInfo();

        if (info != null) {
            for (int i = 0; i < info.length; i++) {
                if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                    return true;
                }
            }
        }

    }

    return false;
}

I recommend you to always check internet connection first before you try to connect to the Internet to avoid exceptions.

2. Creating a sha 512 hash for the password

Use the standard MessageDigest from Java Security to do this. Consider this Post:

private static final char[] HEX_ARRAY = ("0123456789ABCDEF").toCharArray();

public static String getSHA512HahsOfString(String toHash) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    String hash = null;

    MessageDigest digest = MessageDigest.getInstance("SHA-512");
    byte[] bytes = toHash.getBytes("UTF-8");

    digest.update(bytes, 0, bytes.length);
    bytes = digest.digest();
    hash = bytesToHex(bytes);

    return hash;
}

public static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];

    for (int j = 0; j < bytes.length; j++) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }

    return new String(hexChars);
}

3. Sending the username and the password to the server (save)

I would use SSL for this purpose but you will need a valid certificate for this purpose. A very basic solution would be:

DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(params));

HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();

return httpEntity.getContent();

where the url is the url to your (secure(https)) webpage and params is the list of Key-Value pairs of parameters you want to post.

4. Getting a save session token 5. Storing login information for automatic login after restart

I put 4 and 5 together because the answer is belongs to both of them. You can create SessionTokens very simple just by using the Singleton Pattern. When the user logs in and does not want to save his login data you just need to create a Singleton Session which will be deleted automatically after the app is closed or the user logs out:

public class SessionManagerSingleton {
    private Context context = null;
    private static SessionManagerSingleton sessionManagerSingleton = null;
    private boolean isLoggedIn = false;

    private SessionManagerSingleton(Context context) {
        this.context = context;
        this.isLoggedIn = false;
    }

    public void login() {
        this.isLoggedIn = true;
    }

    public void logout() {
        this.isLoggedIn = false;

        Intent newIntent = new Intent(this.context, LoginActivity.class);

        newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        this.context.startActivity(newIntent);
    }

    public boolean isLoggedIn() {
        return this.isLoggedIn;
    }

    public static SessionManagerSingleton getInstance(Context context) {
        if(sessionManagerSingleton == null) {
            sessionManagerSingleton = new SessionManagerSingleton(context);
        }

        return sessionManagerSingleton;
    }
}

In Activities where the user needs to be logged in you now just need to check your SessionManager using isLoggedIn().

If you want to store the login data even when the user closes the app you can use the shared preferences instead:

public class SessionManagerPreferences {
    private Context context = null;
    private SharedPreferences sharedPreferences = null;
    private Editor editor = null;

    public SessionManagerPreferences(Context context){
        this.context = context;
        this.sharedPreferences = this.context.getSharedPreferences(Globals.KEY_PREF_NAME, Globals.PRIVATE_MODE);
        this.editor = this.sharedPreferences.edit();
    }

    public void login(){
        this.editor.putBoolean(Globals.KEY_LOGGED_IN, true);
        this.editor.commit();
    }

    public void logout() {
        this.editor.clear();
        this.editor.commit();

        Intent newIntent = new Intent(this.context, LoginActivity.class);

        newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        this.context.startActivity(newIntent);
    }

    public boolean isLoggedIn(){
        return this.sharedPreferences.getBoolean(Globals.KEY_LOGGED_IN, false);
    }
}

I wont specify things any deeper because it is already a big answer. If you want
to get some more details please specify your questions.
Community
  • 1
  • 1
user1882812
  • 936
  • 5
  • 18
  • 41