使用Intent协议在webview中跳转三方app

最近项目上有个需求,是关于在webview加载一个url的形式使用Intent协议跳转到指定的app页面,查看Intent源码发现Intent.parseUri()方法的第二个参数flag有三种类型: Intent.URI_ANDROID_APP_SCHEME 和 Intent.URI_INTENT_SCHEME 还有 URI_ALLOW_UNSAFE ;第三种不安全,一般不使用。 前俩种的格式为intent://host/#Intent;scheme=hansel;package=com.hansel.app;end 在#Intent之前可以带一些参数
android-app://{package_id}[/{scheme}[/{host}[/{path}]]][#Intent;{...}] 这个是第二种(PS:这种的scheme总是android-app)
在接收的app的manifest中的Activity注册这些信息

这里写图片描述

(intent://协议默认的是Action_View ; app-android 默认在格式中只指定了包名的话,actionMain ,如果有scheme和host则默认为actionView,当然如果协议中指定了action的话,就是你指定的action, 下面是官方的截图
这里写图片描述

接收的app注册这些信息,这里MainActivity 是接收intent:// 协议 Main2Activity接收android-app:// 协议。使用intent://时候一定要注册data的scheme 用来和发起请求的scheme匹配对应; 但是android-app则不太一样,可以不注册data的scheme,但是请求的时候要指定component即:"android-app://com.ebensz.appmanager/#Intent;component=com.ebensz.appmanager/com.ebensz.appmanager.MainActivity;end"; 而且android-app时候接收到的scheme 是android-app; intent://则是指定的scheme

发起请求的代码:在shouldoverride 加入判断 链接: 网上通用的方法

 Intent intent = null;
        // perform generic parsing of the URI to turn it into an Intent.
        try {
            if (url.startsWith("android-app://")){
                intent = Intent.parseUri(url,Intent.URI_ANDROID_APP_SCHEME);
            }else if (url.startsWith("intent://")){
                intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
            }
        } catch (URISyntaxException ex) {
            LogUtil.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
            return false;
        }
        if (intent!=null && !TextUtils.isEmpty(intent.getScheme()) && BrowserUtils.isBlackScheme(intent.getScheme())) {
            return true;
        }

        // check whether the intent can be resolved. If not, we will see
        // whether we can download it from the Market.
        // 如果本地没装能响应特殊协议的应用则return
        if (getPackageManager().resolveActivity(intent, 0) == null) {

            return true;
        }

        // sanitize the Intent, ensuring web pages can not bypass browser
        // security (only access to BROWSABLE activities).
        intent.addCategory(Intent.CATEGORY_BROWSABLE);


        try {

            if (startActivityIfNeeded(intent, -1)) {
                LogUtil.d("tag","sucess use the intent ");

                return true;
            }


        } catch (ActivityNotFoundException ex) {
            LogUtil.d("tag","error message is --> " + ex.getMessage());
            // ignore the error. If no application can handle the URL,
            // eg about:blank, assume the browser can handle it.
        } catch (SecurityException se) {
            se.printStackTrace();
        }复制代码

小结:intent.parseUri()方法中会对协议进行解析,返回一个带有action和data的intent,注意这样的写法肯定是不行的, 因为parseUri返回的intent实例并不是我们 new 出来的intent,下面代码运行的话会报cant find activtiy to handle intent{} ,intents是空的,所以还是需要按照上面的代码执行(PS:这个其实挺简单的,但是我在这儿卡了好久,总有一种错觉,这个自己new出来的intent调用parseUri会将协议的信息赋值进去,还是得读源码才能搞清楚啊!)

Intent intent = new Intent(); 
intent.parseUri("url",Intent.URI_INTENT_SCHEME);
startActivityIfNeeded(intent);复制代码

附上android文档的解释

复制代码

/**

 * Flag for use with {@link #toUri} and {@link #parseUri}: the URI string
 * always has the "intent:" scheme.  This syntax can be used when you want
 * to later disambiguate between URIs that are intended to describe an
 * Intent vs. all others that should be treated as raw URIs.  When used
 * with {@link #parseUri}, any other scheme will result in a generic
 * VIEW action for that raw URI.
 */
public static final int URI_INTENT_SCHEME = 1<<0;复制代码
/**
 * Flag for use with {@link #toUri} and {@link #parseUri}: the URI string
 * always has the "android-app:" scheme.  This is a variation of
 * {@link #URI_INTENT_SCHEME} whose format is simpler for the case of an
 * http/https URI being delivered to a specific package name.  The format
 * is:
 *
 * <pre class="prettyprint">
 * android-app://{package_id}[/{scheme}[/{host}[/{path}]]][#Intent;{...}]</pre>
 *
 * <p>In this scheme, only the <code>package_id</code> is required.  If you include a host,
 * you must also include a scheme; including a path also requires both a host and a scheme.
 * The final #Intent; fragment can be used without a scheme, host, or path.
 * Note that this can not be
 * used with intents that have a {@link #setSelector}, since the base intent
 * will always have an explicit package name.</p>
 *
 * <p>Some examples of how this scheme maps to Intent objects:</p>
 * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
 *     <colgroup align="left" />
 *     <colgroup align="left" />
 *     <thead>
 *     <tr><th>URI</th> <th>Intent</th></tr>
 *     </thead>
 *
 *     <tbody>
 *     <tr><td><code>android-app://com.example.app</code></td>
 *         <td><table style="margin:0;border:0;cellpadding:0;cellspacing:0">
 *             <tr><td>Action: </td><td>{@link #ACTION_MAIN}</td></tr>
 *             <tr><td>Package: </td><td><code>com.example.app</code></td></tr>
 *         </table></td>
 *     </tr>
 *     <tr><td><code>android-app://com.example.app/http/example.com</code></td>
 *         <td><table style="margin:0;border:0;cellpadding:0;cellspacing:0">
 *             <tr><td>Action: </td><td>{@link #ACTION_VIEW}</td></tr>
 *             <tr><td>Data: </td><td><code>http://example.com/</code></td></tr>
 *             <tr><td>Package: </td><td><code>com.example.app</code></td></tr>
 *         </table></td>
 *     </tr>
 *     <tr><td><code>android-app://com.example.app/http/example.com/foo?1234</code></td>
 *         <td><table style="margin:0;border:0;cellpadding:0;cellspacing:0">
 *             <tr><td>Action: </td><td>{@link #ACTION_VIEW}</td></tr>
 *             <tr><td>Data: </td><td><code>http://example.com/foo?1234</code></td></tr>
 *             <tr><td>Package: </td><td><code>com.example.app</code></td></tr>
 *         </table></td>
 *     </tr>
 *     <tr><td><code>android-app://com.example.app/<br />#Intent;action=com.example.MY_ACTION;end</code></td>
 *         <td><table style="margin:0;border:0;cellpadding:0;cellspacing:0">
 *             <tr><td>Action: </td><td><code>com.example.MY_ACTION</code></td></tr>
 *             <tr><td>Package: </td><td><code>com.example.app</code></td></tr>
 *         </table></td>
 *     </tr>
 *     <tr><td><code>android-app://com.example.app/http/example.com/foo?1234<br />#Intent;action=com.example.MY_ACTION;end</code></td>
 *         <td><table style="margin:0;border:0;cellpadding:0;cellspacing:0">
 *             <tr><td>Action: </td><td><code>com.example.MY_ACTION</code></td></tr>
 *             <tr><td>Data: </td><td><code>http://example.com/foo?1234</code></td></tr>
 *             <tr><td>Package: </td><td><code>com.example.app</code></td></tr>
 *         </table></td>
 *     </tr>
 *     <tr><td><code>android-app://com.example.app/<br />#Intent;action=com.example.MY_ACTION;<br />i.some_int=100;S.some_str=hello;end</code></td>
 *         <td><table border="" style="margin:0" >
 *             <tr><td>Action: </td><td><code>com.example.MY_ACTION</code></td></tr>
 *             <tr><td>Package: </td><td><code>com.example.app</code></td></tr>
 *             <tr><td>Extras: </td><td><code>some_int=(int)100<br />some_str=(String)hello</code></td></tr>
 *         </table></td>
 *     </tr>
 *     </tbody>
 * </table>
 */
public static final int URI_ANDROID_APP_SCHEME = 1<<1;复制代码

转载于:https://juejin.im/post/5a094096518825585132312c

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要检测App是否有Intent协议解析越权漏洞,可以使用Frida来hook相关的方法,然后在回调函数进行检测。 具体来说,可以hook Intent的setComponent和setClass方法,这两个方法用于设置Intent的组件信息。在回调函数,可以检测组件的包名和类名是否与预期一致,如果不一致,则表示存在Intent协议解析越权漏洞。 以下是使用Frida进行hook的示例代码: ```javascript Java.perform(function () { var Intent = Java.use("android.content.Intent"); Intent.setComponent.implementation = function (component) { if (component != null) { var packageName = component.getPackageName(); var className = component.getClassName(); if (packageName != "com.example.app" || className != "com.example.app.MainActivity") { console.log("Found Intent protocol authorization vulnerability: " + packageName + "/" + className); } } this.setComponent(component); } Intent.setClass.implementation = function (context, cls) { if (cls != null) { var packageName = cls.getPackage().getName(); var className = cls.getName(); if (packageName != "com.example.app" || className != "com.example.app.MainActivity") { console.log("Found Intent protocol authorization vulnerability: " + packageName + "/" + className); } } this.setClass(context, cls); } }); ``` 需要注意的是,使用Frida进行hook可能会触发一些App的反抗措施,因此需要谨慎使用。同时,为了保持隐蔽性,建议在hook代码不要输出过多的日志信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值