Android 如果使用webview进行身份验证,如何使用意图过滤器处理OAuth 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

我正在开发一个使用OAuth进行身份验证的应用程序,但是我在处理OAuth回调时遇到了一个小问题

身份验证

我的应用程序有一个webview作为登录屏幕,我得到了一个url,可以在我的webview中加载auth表单。假设url是:

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;      

    }});