Überprüfen ob eine HttpAuthRequest genehmigt wurde

  • Antworten:17
  • OffenNicht stickyNicht beantwortet
  • Forum-Beiträge: 23

06.11.2016 12:08:29 via Website

Ich bin am Verzweifeln, ich versuche herauszufinden, ob der Zugriff mit onReceivedHttpAuthRequest genehmigt oder verweigert wurde. Warum hat onReceivedHttpAuthRequest nicht soetwas wie:
public void onReceivedHttpAuthRequest(WebView view,
HttpAuthHandler handler, String host, String realm, int isGranted?)

Gibt es noch andere Möglichkeiten?
onPageFinished hab ich versucht, aber die Website wird immer fertig geladen, egal ob er gerade Authentiziert oder nicht.

Vielen dank im Voraus
aphi

Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 9.302

06.11.2016 14:26:56 via App

Beim Verweigern dürfte der Http Statuscode != 200 sein. Vorausgesetzt die Seite hält sich an standards.

Brauchst du das für eine Spezielle Seite oder allgemein?
Wenn speziell könntest du auch die Html analysieren ob eingeloggt. Evtl. hat man dann ein Feld eingeloggt als o.ä. nachdem du im Quellcode suchen könntest.

LG Pascal //It's not a bug, it's a feature. :) ;)

  • Forum-Beiträge: 23

06.11.2016 15:33:36 via Website

Ich brauch das Allgemein.
Wie detected man Fehler 200?
Ich hab schon onErrorReceived gemacht, aber da kommt kein Fehler an.
PS: Wenn die Zugangsdaten fehlerhaft sind wird der Login erneut aufgerufen, da kommt nicht sowas wie Error- Zugriff verweigert.

— geändert am 06.11.2016 15:35:17

Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 9.302

06.11.2016 15:45:33 via Website

Hmm, wenn die Webseite nicht mitspielt wirds schwierig.
Du musst das irgendwie selber feststellen.
Wirst du auf eine andere URL umgeleitet wenn erfolgreich?
Wenn ja dann könntest du das Kriterunm darauf festlegen.
Ansonsten geht das nur bei webseiten die ihren http statuscode entsprechend apassen bzw. irgend eine Error Meldung ausgeben.

Sehe gerade:
http://stackoverflow.com/questions/3134389/access-the-http-response-headers-in-a-webview
Die WebView bietet keine Möglichkeit die http header zu lesen, du müsstest sowas selber programmieren...

LG Pascal //It's not a bug, it's a feature. :) ;)

  • Forum-Beiträge: 23

06.11.2016 15:53:47 via Website

Nein ich werde leider nicht umgeleitet, aber könnte man es nicht so machen, dass wenn die Loginanfrage öfter als 3 mal wiederkommt, dass es dann nicht geht und wenn sie nicht wiederkommt (erfolgreich) dann gehts?

Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 9.302

06.11.2016 15:58:30 via Website

Theoretisch ja, kommt darauf an was für ein Login- Verfahren verwendet wird.

Bsp:
Basic-Authentifizierung - Das ist dieser PopUp Dialog im Browser
HTTP_Post authentifizierung: So wie das hier im Forum ist - eine html mit Feldern und anschleißen ein Login Button
Das wären die beiden die mir gerade so einfallen

LG Pascal //It's not a bug, it's a feature. :) ;)

Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 9.302

06.11.2016 16:27:13 via App

Da sollte es normalerweise ne Error Page geben.
Aber da es keine gibt kann ich dir im moment nicht helfen

— geändert am 06.11.2016 16:27:25

LG Pascal //It's not a bug, it's a feature. :) ;)

  • Forum-Beiträge: 23

19.11.2016 12:18:35 via Website

So ich hab das jetzt mal mit okHttp versucht und -tadaaa- jetzt gibt es auf einmal status 401 bei falschen zugangsdaten :)
Aber , wenn ich auf die richtige Url gehe, und mich mit richtigen Zugangsdaten anmelde, kommt auch status 401. Obwohl es im Browser mit dem pop-Up geht ! Hier mal mein aktueller Code:

package intern.csg_germering.de.csg_info;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.http.SslError;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.RequiresApi;
import android.support.annotation.RequiresPermission;
import android.util.Base64;
import android.view.View;
import android.support.v7.app.AppCompatActivity;
import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import org.apache.http.*;


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringWriter;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Objects;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
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.Request;
import okhttp3.Response;

public class Unlock extends AppCompatActivity {

public Button unlockbt;
public EditText pass;
public EditText user;
public WebView webbi;
public static final String SEED = "065487";
public String getUser() {
    String getUserForAsync = user.getEditableText().toString();
    return getUserForAsync;
}
public String getPass() {
    String getPassForAsync = pass.getEditableText().toString();
    return getPassForAsync;
}


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_unlock);
    unlockbt = (Button) findViewById(R.id.unlockbt);
    pass = (EditText) findViewById(R.id.pass);
    user = (EditText) findViewById(R.id.user);
    webbi = (WebView) findViewById(R.id.webbi);
    ActivityRegistry.register(this);
    HttpsTrustManager.allowAllSSL();
    unlockbt.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Authorization auti = new Authorization();
            auti.execute();
        }
    });

    /*webbi.setWebViewClient(new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {

            return false;
        }

        @Override
        public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {

            handler.proceed();
        }
        boolean doubleBackToExitPressedOnce = false;
        boolean incLogin = false;
        @Override
        public void onReceivedHttpAuthRequest(WebView view,
                                              HttpAuthHandler handler, String host, String realm) {

            handler.proceed(user.getEditableText().toString(), pass.getEditableText().toString());

            if (doubleBackToExitPressedOnce) {
                Toast.makeText(Unlock.this, "Inkorrekte Zugangsdaten", Toast.LENGTH_LONG).show();
                webbi.stopLoading();
                incLogin = true;
                return;
            }

            this.doubleBackToExitPressedOnce = true;
            Toast.makeText(Unlock.this, "Überprüfung ...", Toast.LENGTH_SHORT).show();
            Handler Handu = new Handler();
            Runnable runni = new Runnable() {

                @Override
                public void run() {
                    doubleBackToExitPressedOnce = false;
                    try {
                        Toast.makeText(Unlock.this, "Zugangsdaten korrekt.", Toast.LENGTH_SHORT).show();

                        String passToEncrypt = pass.getEditableText().toString();
                        String userToEncrypt = user.getEditableText().toString();

                        String cryptpass = SimpleCrypto.encrypt(SEED, passToEncrypt);
                        String cryptuser = SimpleCrypto.encrypt(SEED, userToEncrypt);
                        Setup.getInstance().setString("cryptuser", cryptuser);
                        Setup.getInstance().setString("cryptpass", cryptpass);
                        Setup.getInstance().setString("unlocked", "true");
                        finish();

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                };
            Handu.postDelayed(runni, 2000);
            if(incLogin) {

                Handu.removeCallbacks(runni);
                incLogin = false;
            }






        }

        @RequiresApi(api = Build.VERSION_CODES.M)
        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {






        }



    });
    */



}
public static String getStringFromInputStream(InputStream stream) throws IOException
{
    int n = 0;
    char[] buffer = new char[1024 * 4];
    InputStreamReader reader = new InputStreamReader(stream, "UTF8");
    StringWriter writer = new StringWriter();
    while (-1 != (n = reader.read(buffer))) writer.write(buffer, 0, n);
    return writer.toString();
}

class Authorization extends AsyncTask<Void,Void,Void>
{


    protected void onPreExecute() {
        //display progress dialog.

    }
    protected Void doInBackground(Void... params) {
        OkHttpClient client = getUnsafeOkHttpClient().newBuilder()

                .addInterceptor(new BasicAuthInterceptor(getUser(), getPass()))
                .build();
        Request request = new Request.Builder()
                .url("myUrl")
                .get()
                .build();
        try {
            Response httpResponse = client.newCall(request).execute();
            int Status = httpResponse.code();




        if(httpResponse.isSuccessful()) {

                try {
                    runOnUiThread(new Runnable() {
                        public void run() {

                            Toast.makeText(Unlock.this, "Zugangsdaten korrekt.", Toast.LENGTH_SHORT).show();
                        }
                    });


                    String passToEncrypt = getPass();
                    String userToEncrypt = getUser();

                    String cryptpass = SimpleCrypto.encrypt(SEED, passToEncrypt);
                    String cryptuser = SimpleCrypto.encrypt(SEED, userToEncrypt);
                    Setup.getInstance().setString("cryptuser", cryptuser);
                    Setup.getInstance().setString("cryptpass", cryptpass);
                    Setup.getInstance().setString("unlocked", "true");
                    finish();

                } catch (Exception e) {
                    e.printStackTrace();
                }




            }
            else if(Status == 401) {
                runOnUiThread(new Runnable() {
                    public void run() {

                        Toast.makeText(Unlock.this, "Inkorrekte Zugangsdaten", Toast.LENGTH_LONG).show();
                    }
                });





            }


        } catch (IOException e1) {
            e1.printStackTrace();
        }






    return null;
    }



     protected void onPostExecute(Void result) {
        // dismiss progress dialog and update ui
    }
}




boolean doubleBackToExitPressedOnce = false;

@SuppressLint("NewApi")
@Override
public void onBackPressed() {

    if (doubleBackToExitPressedOnce) {
        ActivityRegistry.finishAll();

        return;
    }

    this.doubleBackToExitPressedOnce = true;
    Toast.makeText(this, "Zum Verlassen der Anwendung, 'Zurück' erneut drücken.", Toast.LENGTH_SHORT).show();

    new Handler().postDelayed(new Runnable() {

        @Override
        public void run() {
            doubleBackToExitPressedOnce=false;
        }
    }, 2000);

}



private static OkHttpClient 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);
        builder.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });

        OkHttpClient okHttpClient = builder.build();
        return okHttpClient;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}



}

Und hier die Interceptor

package intern.csg_germering.de.csg_info;

import java.io.IOException;
import okhttp3.Credentials;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

public class BasicAuthInterceptor implements Interceptor {

    private String credentials;

    public BasicAuthInterceptor(String user, String password) {
        this.credentials = Credentials.basic(user, password);
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Request authenticatedRequest = request.newBuilder()
                .header("Authorization", credentials).build();
        return chain.proceed(authenticatedRequest);
    }

}

— geändert am 19.11.2016 18:50:34 durch Moderator

Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 9.302

19.11.2016 17:59:21 via Website

Bist du dir sicher, dass der Intercept greift?
Hast du dir mal deine eigene Webseite mit BasicAuth bebastelt um das verhalten der App zu testen?
Auch schonmal mit Anmeldedaten in der Url probiert:
http s://user:pass@domain.de

PS: Falls die Url nicht öffentlich sein soll, gib mir bescheid, dann entferne ich diese wieder.

— geändert am 19.11.2016 18:49:46

LG Pascal //It's not a bug, it's a feature. :) ;)

  • Forum-Beiträge: 23

19.11.2016 18:23:21 via Website

Bei ner anderen URL auf demselben Server gehts... aber da sinds auch andere logindaten.
Also bin ich mir ziemlich sicher.
Und im Browser gehts auch?!
was ist da los?
Ich habs auch schon mit HTTPUrlConnction probiert, dasselbe Ergebnis.
Bei der einen URL mit den einen Zugangsdaten gehts , bei der anderen mit den andere Zugansdaten nicht.

PS: Wäre nett, wenn du die Url entfernen könntest. :)

Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 9.302

19.11.2016 18:53:16 via Website

Ich habe die Url mal aus deinem Code und aus meinem Post entfernt ;)



Dann scheint es an der Webseite zu liegen, wenn die selbe Technik woanders funktioniert...
Dann musst du dir entweder etwas anderes ausdenken (Workaround).
Oder du fragst an deiner Schule den Webmaster, ob er den Zugriff nicht über HTTP POST o.ä. auch anlegen will.

Versuche mal nicht nur den HTTP Status Code auszuwerten sondern auch den ResponseBody. Vlt bekommst du mit einer kombination aus beidem mehr Heraus.

LG Pascal //It's not a bug, it's a feature. :) ;)

  • Forum-Beiträge: 23

26.11.2016 20:20:24 via Website

Ich glaub das jetzt nicht...
Wenn ich die Authentizierung wieder per WebView mache... WIRD DIE WEBSITE ANGEZEIGT!!!
Nur mit den nicht-grafischen Webtools geht es nicht und es kommt immer 401
WARUM???
PS Der responsebody ist 401 Authorization Required
Es kann nur an etwas clientseitigem liegen, aber das muss ein komischer Bug sein, oder ich übersehe hierbei etwas.
Hast du irgendein Plan was das sein könnte?
lg aphi

edit:
Und ich hab ja immer noch das problem, dass ich mit dem WebView die statuscodes nicht auslesen kann.
(angry)

— geändert am 26.11.2016 20:21:40

Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 9.302

26.11.2016 21:30:56 via Website

Ja die WebView unterstütz das auslesen der Statuscode nicht, deswegen geht da nicht...
Und ich habe keine Ahnung warum sich das alles so komish verhält, kann ich mir jetzt auch nicht erklären...

LG Pascal //It's not a bug, it's a feature. :) ;)

  • Forum-Beiträge: 23

27.11.2016 10:11:50 via Website

Also, ich hab das jetzt mit mehreren URLs versucht auf dem Server, es will nicht.
Ich werde jetzt den Webmaster kontaktieren.
lg aphi

  • Forum-Beiträge: 23

27.11.2016 10:38:12 via Website

Außerdem ist es so, dass das keine normale Basic Authentizierung ist, sondern eine Https Basic Auth, davon hab ich davor noch nie was gehört, scheint es aber zu geben , aber das ssl zertifikat der schule ist selbst-signiert, daher auch das getUnsafeOkhttpclient schnipsel.
Kann es daran liegen?
Weil da ist es ja normalerweise ssl verschlüsselt.
Oder an einem Zeichen und Benutzer oder Passwort, das nicht akzeptiert wird von der ssl-Verschlüsselung?
Welche Zeichen könnten das sein?
lg aphi

Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 9.302

27.11.2016 10:54:13 via App

Eigentlich nicht weil wenn du es Manuell eingibst geht es ja. hast du es mal in Chrone auf deinem Gerät probiert?
Du hast das Problem nur weil du die Eigabedaten speichern willst.
Würdest du dem User immer ein Dialog anzeigen wo er es selber immer eingeben muss würde es wahrscheinlich gehen wie in Chrone oder anderen Browsern.

LG Pascal //It's not a bug, it's a feature. :) ;)

  • Forum-Beiträge: 23

02.12.2016 20:51:44 via Website

Das ist ein Problem mit allen nicht-grafischen Web Clients.
Sie versuchen erst, ohne AUthorization reinzukommen , dann getten sie 401, und erst nachdem sie 401 bekommen haben, senden sie die Zugansdaten.
Von daher müsste man 2 Requests akzeptieren, quasi einen Second Try.
Irgendeine Idee?