如何在Blazor Server登录页面中使“记住我”功能在Android WebView中稳定工作?

huangapple go评论63阅读模式
英文:

How to make the 'Remember Me' function in Blazor Server login page work consistently in Android WebView?

问题

在我的Blazor Server应用程序中,我使用了内置的AuthenticationStateProvider服务进行Blazor Server的身份验证。该服务的登录页面具有正常工作的“记住我”功能。

在我的Android应用程序中,我使用WebView显示Blazor Server网站。

MainActivity.java:

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    private WebView webView;
    private ProgressBar progressBar;

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.webview);
        progressBar = findViewById(R.id.progressBar);

        // 配置WebView设置
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);

        CookieManager.getInstance().setAcceptCookie(true);
        CookieManager.getInstance().acceptThirdPartyCookies(webView);

        // 设置WebView客户端
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
                progressBar.setVisibility(View.VISIBLE);
                webView.setVisibility(View.GONE);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                progressBar.setVisibility(View.GONE);
                webView.setVisibility(View.VISIBLE);
            }
        });

        webView.setWebChromeClient(new WebChromeClient() {
            public void onProgressChanged(WebView view, int progress) {
                progressBar.setProgress(progress);
            }
        });

        // 加载网站
        webView.loadUrl("URL HERE");
    }

    @Override
    public void onBackPressed() {
        // 处理WebView内的返回按钮按下
        if (webView.canGoBack()) {
            webView.goBack();
        } else {
            super.onBackPressed();
        }
    }
}

添加到AndroidManifest.xml:

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

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context=".MainActivity">

    <WebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:indeterminate="false"
        android:max="100"
        android:progress="0"
        android:visibility="gone" />

</RelativeLayout>

当我通过WebView应用程序登录时,“记住我”功能在100次尝试中只有1次成功,并将凭据存储在我的手机上的应用数据中。我知道这是因为:

  • 即使在Google Chrome中清除浏览器历史记录后,我仍然保持登录状态。
  • 即使清除应用程序的缓存存储后,我仍然保持登录状态。
  • 当我清除应用程序的所有数据(应用信息 -> 存储 -> 清除数据)时,我不再保持登录状态。

在其他99次尝试中,它不会记住登录,当我再次打开WebView应用程序时,我必须重新登录。

如何使此功能在100次尝试中都能正常工作?我从未弄清楚应用程序何时保存登录凭据以及何时不保存...

我已激活了JavaScript和(第三方)Cookie。问题仍未解决。

英文:

I have a Blazor Server app where I use the build-in AuthenticationStateProvider service for Blazor Server. The login page of this service has a remember me function that works properly.

Within my Android App I show the Blazor Server website with a WebView

MainActivity.Java:

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private WebView webView;
private ProgressBar progressBar;
@SuppressLint(&quot;SetJavaScriptEnabled&quot;)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webview);
progressBar = findViewById(R.id.progressBar);
// Configure WebView settings
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
CookieManager.getInstance().setAcceptCookie(true);
CookieManager.getInstance().acceptThirdPartyCookies(webView);
// Set WebView clients
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
progressBar.setVisibility(View.VISIBLE);
webView.setVisibility(View.GONE);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
progressBar.setVisibility(View.GONE);
webView.setVisibility(View.VISIBLE);
}
});
webView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
progressBar.setProgress(progress);
}
});
// Load the website
webView.loadUrl(&quot;URL HERE&quot;);
}
@Override
public void onBackPressed() {
// Handle back button press inside WebView
if (webView.canGoBack()) {
webView.goBack();
} else {
super.onBackPressed();
}
}
}

Added to the AndroidManifest.xml:
&lt;uses-permission android:name=&quot;android.permission.INTERNET&quot;/&gt;

Activity_main.xml

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;RelativeLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
xmlns:tools=&quot;http://schemas.android.com/tools&quot;
android:layout_width=&quot;match_parent&quot;
android:layout_height=&quot;match_parent&quot;
tools:context=&quot;.MainActivity&quot;&gt;
&lt;WebView
android:id=&quot;@+id/webview&quot;
android:layout_width=&quot;match_parent&quot;
android:layout_height=&quot;match_parent&quot;
android:visibility=&quot;gone&quot; /&gt;
&lt;ProgressBar
android:id=&quot;@+id/progressBar&quot;
style=&quot;?android:attr/progressBarStyleHorizontal&quot;
android:layout_width=&quot;match_parent&quot;
android:layout_height=&quot;wrap_content&quot;
android:layout_centerVertical=&quot;true&quot;
android:layout_centerHorizontal=&quot;true&quot;
android:indeterminate=&quot;false&quot;
android:max=&quot;100&quot;
android:progress=&quot;0&quot;
android:visibility=&quot;gone&quot; /&gt;
&lt;/RelativeLayout&gt;

When I login via the WebView app, the Remember Me function is working 1 out of 100 times and stores the credentials local on my phone within the app data. I know this because:

  • I remain logged in when I clear my browser history on Google Chrome
  • I remain logged in when I clear the cache storage of the app
  • I am no longer logged in when I clear all data of the app (App info -&gt; Storage -&gt; Clear Data)

The other 99 out of 100 times it does not remember the login and when I open de WebView app again I have to login again.

How can I make this functionality work 100 out of 100 times? I never got to figure out when the app does save the login credentials and when it does not...

I activated JavaScript and (third party) coockies. Problem still not solved.

答案1

得分: 0

我发现 WebView 应用程序并不总是正确同步存储的 Cookie。为了修复这个问题,将以下代码添加到 MainActivity 中:

webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url) {
       CookieManager.getInstance().flush();
    }
});

完整代码:

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    private WebView webView;
    private ProgressBar progressBar;

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.webview);
        progressBar = findViewById(R.id.progressBar);

        // 配置 WebView 设置
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);

        CookieManager.getInstance().setAcceptCookie(true);
        CookieManager.getInstance().acceptThirdPartyCookies(webView);

        // 设置 WebView 客户端
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
                progressBar.setVisibility(View.VISIBLE);
                webView.setVisibility(View.GONE);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                CookieManager.getInstance().flush();
                progressBar.setVisibility(View.GONE);
                webView.setVisibility(View.VISIBLE);
            }
        });

        webView.setWebChromeClient(new WebChromeClient() {
            public void onProgressChanged(WebView view, int progress) {
                progressBar.setProgress(progress);
            }
        });

        // 加载网站
        webView.loadUrl("在此处输入网址");
    }

    @Override
    public void onBackPressed() {
        // 处理 WebView 内部的返回按钮按下事件
        if (webView.canGoBack()) {
            webView.goBack();
        } else {
            super.onBackPressed();
        }
    }
}
英文:

I found out the WebView App is not always syncing the stored cookies correctly. To fix this add the following code to the MainActivity:

webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
CookieManager.getInstance().flush();
}
}

full code:

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private WebView webView;
private ProgressBar progressBar;
@SuppressLint(&quot;SetJavaScriptEnabled&quot;)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webview);
progressBar = findViewById(R.id.progressBar);
// Configure WebView settings
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
CookieManager.getInstance().setAcceptCookie(true);
CookieManager.getInstance().acceptThirdPartyCookies(webView);
// Set WebView clients
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
progressBar.setVisibility(View.VISIBLE);
webView.setVisibility(View.GONE);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
CookieManager.getInstance().flush();
progressBar.setVisibility(View.GONE);
webView.setVisibility(View.VISIBLE);
}
});
webView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
progressBar.setProgress(progress);
}
});
// Load the website
webView.loadUrl(&quot;URL HERE&quot;);
}
@Override
public void onBackPressed() {
// Handle back button press inside WebView
if (webView.canGoBack()) {
webView.goBack();
} else {
super.onBackPressed();
}
}
}

huangapple
  • 本文由 发表于 2023年6月1日 15:20:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76379534.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定