Android 如果使用webview进行身份验证,如何使用意图过滤器处理OAuth URL回调?
我正在开发一个使用OAuth进行身份验证的应用程序,但是我在处理OAuth回调时遇到了一个小问题 身份验证 我的应用程序有一个webview作为登录屏幕,我得到了一个url,可以在我的webview中加载auth表单。假设url是:Android 如果使用webview进行身份验证,如何使用意图过滤器处理OAuth URL回调?,android,authentication,webview,callback,oauth-2.0,Android,Authentication,Webview,Callback,Oauth 2.0,我正在开发一个使用OAuth进行身份验证的应用程序,但是我在处理OAuth回调时遇到了一个小问题 身份验证 我的应用程序有一个webview作为登录屏幕,我得到了一个url,可以在我的webview中加载auth表单。假设url是: https://myoauthhost.com/oauth/auth?response_type=code&client_id=XXXXXXX&redirect_uri=YYYYYYYY&scope=ZZZZZZZZZZ 在auth活动(A
https://myoauthhost.com/oauth/auth?response_type=code&client_id=XXXXXXX&redirect_uri=YYYYYYYY&scope=ZZZZZZZZZZ
在auth活动(AuthActivity.java)中,我有以下内容:
String authURL = https://myoauthhost.com/oauth/auth?response_type=code&client_id=XXXXXXX&redirect_uri=YYYYYYYY&scope=ZZZZZZZZZZ
myWebView.loadUrl(authURL);
在manifest.xml中,我为oauth回调处理提供了以下内容:
<activity
android:name=".AuthActivity"
android:label="@string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="authprovider"
android:scheme="auth" />
</intent-filter>
</activity>
因此,使用这段代码,“在webview中”处理重定向,并显示登录屏幕
然后,我可以输入凭据(例如:通过Twitter输入oauth),但是当身份验证完成时,会收到回拨,但是应该处理回拨的活动(AuthActivity配置为在清单中接收回拨)不会启动。相反,我让webview显示一条消息,表示url回调(在我们的示例中为:authprovider://auth/XXX?xxx=yyy 找不到在清单中配置的
原因可能是以下代码:
myWebView.setWebViewClient(new WebViewClient());
之前介绍过,告诉Android webview可以处理一切。所以现在,由于回调url不是web url,它很难处理它,甚至无法启动可以处理它的意图
问题
我怎样才能解决这个问题?
我应该能够让活动处理回调,但不能让webview尝试加载它
任何帮助都将不胜感激
提前感谢首先,您可能需要调用服务提供商提供的URL,如果存在任何重定向,您将获得HTTP状态代码3xx。接下来,如果存在任何重定向,您可以尝试调用实际URL。对于正常的HTTP响应,您将获得HTTP 2xx状态代码。首先,在清单中,将这些属性设置为启动WebView的活动
android:launchMode="singleInstance"
并添加一个意图过滤器,如下所示:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="oauth-testing" />
</intent-filter>
这里的回调url是private static final String CALLBACK_URL=“oauth testing://”代码>
您正在创建一个动态网络视图并向用户显示。登录webview后,代码将被关闭,并进入onNewIntent()
。您需要在登录后实现您的功能
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
dealWithTwitterResponse(intent);
}
private void dealWithTwitterResponse(Intent intent) {
Uri uri = intent.getData();
System.out.println("URI=" + uri);
if (uri != null && uri.toString().startsWith(CALLBACK_URL)) {
String oauthVerifier = uri.getQueryParameter("oauth_verifier");
authoriseNewUser(oauthVerifier);
}
}
我知道我已经添加了很多代码片段,其中一些可能不相关,但我希望有一天它会帮助别人 因为您有WebView的对象,所以您可以重载它,然后通过以下两种方式处理您导航到活动的url
private class MyWebView extends WebViewClient{
@TargetApi(Build.VERSION_CODES.N)
@Override
public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest request)
{
Uri uri = request.getUrl();
return shouldOverrideUrlLoading(uri.toString());
}
private boolean shouldOverrideUrlLoading(final String url)
{
Log.i(TAG, "shouldOverrideUrlLoading() URL : " + url);
//your code to handle the url for navigation will go here
try{
if(url.contains("yourcondition")){
//1st way to handle
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}else{
//2nd way
Intent intent = new Intent(YourActivity.this,NewActivity.class);
//you can set the data
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}
}catch(ActivityNotFoundException e) {
Log.e(LOGTAG,"Could not load url"+url);
}
return false;
// return true; // this True means that application wants to leave the WebView and try to go to browser and handle the url itself, otherwise return false.
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
try {
if(url.contains("yourcondition")){
//1st way to handle
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}else{
//2nd way
Intent intent = new Intent(YourActivity.this,NewActivity.class);
//you can set the data
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}
} catch(ActivityNotFoundException e) {
Log.e(LOGTAG,"Could not load url"+url);
}
return false;
}
}
您可以设置mWebView.setWebViewClient(新的WebViewClient())代码>这是默认值,但由
仅添加默认自定义WebViewClient将只允许WebView本身处理任何加载的URL,即在WebView中而不是在浏览器中处理任何加载的URL
但是如果您通过传递上面的类MyWebView
重载,比如mWebView.setWebViewClient(newmywebview())
然后你可以控制url的加载,就像你可以实现的一样
myWebView.setWebViewClient(new WebViewClient(){
@TargetApi(Build.VERSION_CODES.N)
@Override
public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest request)
{
Uri uri = request.getUrl();
return shouldOverrideUrlLoading(uri.toString());
}
private boolean shouldOverrideUrlLoading(final String url)
{
Log.i(TAG, "shouldOverrideUrlLoading() URL : " + url);
//your code to handle the url for navigation will go here
try{
if(url.contains("yourcondition")){
//1st way to handle
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}else{
//2nd way
Intent intent = new Intent(YourActivity.this,NewActivity.class);
//you can set the data
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}
}catch(ActivityNotFoundException e) {
Log.e(LOGTAG,"Could not load url"+url);
}
return false;
// return true; // this True means that application wants to leave the WebView and try to go to browser and handle the url itself, otherwise return false.
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
try {
if(url.contains("yourcondition")){
//1st way to handle
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}else{
//2nd way
Intent intent = new Intent(YourActivity.this,NewActivity.class);
//you can set the data
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}
} catch(ActivityNotFoundException e) {
Log.e(LOGTAG,"Could not load url"+url);
}
return false;
}});
如果您没有对webview对象的控制权,那么这不是我将在解决此问题后更新的解决方案。我有一个不同的案例,尝试将OAuth与AccountManager
和android:launchMode=“singleInstance”
集成在一起对我有效。
private class MyWebView extends WebViewClient{
@TargetApi(Build.VERSION_CODES.N)
@Override
public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest request)
{
Uri uri = request.getUrl();
return shouldOverrideUrlLoading(uri.toString());
}
private boolean shouldOverrideUrlLoading(final String url)
{
Log.i(TAG, "shouldOverrideUrlLoading() URL : " + url);
//your code to handle the url for navigation will go here
try{
if(url.contains("yourcondition")){
//1st way to handle
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}else{
//2nd way
Intent intent = new Intent(YourActivity.this,NewActivity.class);
//you can set the data
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}
}catch(ActivityNotFoundException e) {
Log.e(LOGTAG,"Could not load url"+url);
}
return false;
// return true; // this True means that application wants to leave the WebView and try to go to browser and handle the url itself, otherwise return false.
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
try {
if(url.contains("yourcondition")){
//1st way to handle
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}else{
//2nd way
Intent intent = new Intent(YourActivity.this,NewActivity.class);
//you can set the data
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}
} catch(ActivityNotFoundException e) {
Log.e(LOGTAG,"Could not load url"+url);
}
return false;
}
}
myWebView.setWebViewClient(new WebViewClient(){
@TargetApi(Build.VERSION_CODES.N)
@Override
public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest request)
{
Uri uri = request.getUrl();
return shouldOverrideUrlLoading(uri.toString());
}
private boolean shouldOverrideUrlLoading(final String url)
{
Log.i(TAG, "shouldOverrideUrlLoading() URL : " + url);
//your code to handle the url for navigation will go here
try{
if(url.contains("yourcondition")){
//1st way to handle
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}else{
//2nd way
Intent intent = new Intent(YourActivity.this,NewActivity.class);
//you can set the data
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}
}catch(ActivityNotFoundException e) {
Log.e(LOGTAG,"Could not load url"+url);
}
return false;
// return true; // this True means that application wants to leave the WebView and try to go to browser and handle the url itself, otherwise return false.
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
try {
if(url.contains("yourcondition")){
//1st way to handle
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}else{
//2nd way
Intent intent = new Intent(YourActivity.this,NewActivity.class);
//you can set the data
intent.setData(Uri.parse(url));
YourActivity.this.startActivity(intent);
}
} catch(ActivityNotFoundException e) {
Log.e(LOGTAG,"Could not load url"+url);
}
return false;
}});