>>分享Android开发相关的技术 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 19374 个阅读者 刷新本主题
 * 贴子主题:  Android中的Intent Filter与安全 回复文章 点赞(0)  收藏  
作者:mary    发表时间:2020-03-31 20:17:32     消息  查看  搜索  好友  邮件  复制  引用

  
   Intent是Android应用程序核心组件之间通信和传递信息的核心机制。与之相关的IntentFilter也具有相关的安全机制(测试)来进行约束。本文将对其进行详细介绍。

           一、Intent和IntentFilter简介

一个应用程序的三个核心组件(活动,服务和广播接收器)都是通过消息即意图(Intents)来激活的。Intent消息传送是相同或不同应用中组件运行时晚绑定的一种机制。意图本身(一个意图对象)是一个包含被执行操作抽象描述的被动的数据结构。或,对于广播而言,是某件已经发生并被声明的事情的描述。存在如下几种不同的机制来传送意图到每种组件中:

(1) 一个意图对象是传递给Context.startActivity()或者Activity.startActivityForResult()来启动一个活动或者让一个存在的活动去做某些新的事情。

(2) 一个意图对象是传递给Context.startService()来发起一个服务或者递交新的指令给运行中的服务。
     类似的,一个意图能被传递给Context.bindService() 来在调用组件和一个目标服务之间建立连接。作为一个可选项,它可以发起这个服务如果还没运行的话。

(3) 传递给任意广播方法(例如Context.sendBroadcast(),Context.sendOrderedBroadcast(),
    或者Context.sendStickyBroadcast())的意图对象被传递给所有感兴趣的广播接收者。许多种广播产生于系统代码。

在每个例子里,Android系统找到合适的活动、服务或者一组广播接收者来回应这个意图,必要时实例化它们。这些消息传送系统没有重叠:广播意图仅被传递给广播接收者,永远不会给活动或者服务。一个传送给startActivity()的意图是只会被传递给一个活动,永远不会给一个服务或广播接收者,如此类推。

为了通知系统它们可以处理哪些意图,活动、服务和广播接收器可以有一个或多个意图过滤器。每个过滤器描述组件的一个能力,一系列组件想要接收的意图。它实际上按照一个期望的类型来进行意图滤入,同时滤出不想要的意图-但是只有不想要的隐式意图会被滤出(那些没有命名目标的对象类)。一个显式意图总能够被递交给它的目标,而无论它包含什么。这种情况下过滤器不起作用。但是一个显式意图仅当它能通过组件的一个过滤器时才可以被递交到这个组件。

组件为它能做的每项工作,每个呈现给用户的不同方面分有不同的过滤器。比如,范例记事本应用程序中的主要活动有三个过滤器:一个是空白板,另一个是用户可以查看、编辑、或选择的一个指定的记事目录,第三是在没有初始目录说明的情况下查找一个特定的记录。一个意图过滤器是Context.registerReceiver()来注册的广播接收器的过滤器;它们是作为意图过滤器对象而被直接创建的。

二 、过滤器与安全Filters and security

我们不能信赖一个意图过滤器的安全性。当它打开一个组件来接收某些特定类型的隐式意图,它并不能阻止以这个组件为目标的显式意图。即使过滤器对组件要处理的意图限制某些动作和数据源,总有人能把一个显式意图和一个不同的动作及数据源组合在一起,然后命名该组件为目标。

一个过滤器和意图对象有同样的动作、数据以及类别字段。一个隐式意图在过滤器的所有三个方面都被测试。为了递交到拥有这个过滤器的组件,它必须通过所有这三项测试。即便只有一个不通过,Android系统都不会把它递交给这个组件。不过,由于一个组件可以包含多个意图过滤器,一个不能通过其中一个组件过滤器的意图可能在另外的过滤器上获得通过。

与之相关的三个测试详细描述如下 :

测试一:动作测试( Actiontest)  

清单文件中的意图过滤器元素里列举了动作元素,比如:
  1.    < intent-filter.  . .  >  
  2.    < action   android:name = "com.example.project.SHOW_CURRENT"   />  
  3.    < action   android:name = "com.example.project.SHOW_RECENT"   />  
  4.    < action   android:name = "com.example.project.SHOW_PENDING"   />  
  5.   . . .
  6.    </ intent-filter >  
  如同例子所示,一个意图对象只对单个动作命名,而一个过滤器可能列举多个。列表不能为空;一个过滤器必须包含至少一个动作元素,否则它将阻塞所有的意图。

为了通过这个测试,在意图对象中指定的动作必须匹配过滤器中所列举的动作之一。如果意图对象或过滤器不指定一个动作,结果将是:如果这个过滤器没有列出任何动作,那意图就没有什么可匹配的,因此所有的意图都会测试失败。没有意图能够通过这个过滤器。另一方面,一个未指定动作的意图对象自动通过这个测试-只要过滤器包含至少一个动作。

  

测试二:类别测试( Categorytest

一个意图过滤器<intent-filter>元素也列举了类别作为子元素。比如:
  1.    < intent-filter.  . .  >  
  2.    < category   android:name = "android.intent.category.DEFAULT"   />  
  3.    < category   android:name = "android.intent.category.BROWSABLE"   />  
  4.   . . .
  5.    </ intent-filter >  
  注意前面描述的动作和类别常量没有在清单文件中使用。相反使用了完整的字符串。比如,对应于前述CATEGORY_BROWSABLE常量,上面的例子里使用了"android.intent.category.BROWSABLE"字符串。类似的,字符串"android.intent.action.EDIT" 对应于ACTION_EDIT常量。

对一个通过类别测试的意图,每个意图对象中的类别必须匹配一个过滤器中的类别。这个过滤器可以列举另外的类别,但它不能遗漏任何在这个意图中的类别。

因此,原则上一个没有类别的意图对象应该总能够通过测试,而不管过滤器里有什么。绝大部分情况下这个是对的。但有一个例外,Android把所有传给startActivity()的隐式意图当作他们包含至少一个类别:"android.intent.category.DEFAULT"(CATEGORY_DEFAULT常量)。 因此,想要接收隐式意图的活动必须在它们的意图过滤器中包含"android.intent.category.DEFAULT"。,而带"android.intent.action.MAIN"和"android.intent.category.LAUNCHER"设置的过滤器是例外。它们标记那些启动新任务和呈现在启动屏幕的活动。它们可以在类别列表中包含"android.intent.category.DEFAULT",但不是必要的。

测试三:数据测试( Data test

就像动作和类别,一个意图过滤器的数据规格被包含在一个子元素中。而且这个子元素可以出现多次或一次都不出现。例如:
  1.    < intent-filter.  . .  >  
  2.    < data   android:type = "video/mpeg"   android:scheme = "http"  .. .  />  
  3.    < data   android:type = "audio/mpeg"   android:scheme = "http"  .. .  />  
  4.   . . .
  5.    </ intent-filter >  
  每个数据<data>元素可以指定一个URI和一个数据类型(MIME媒体类型)。有一些单独的属性-模式,主机,端口和路径-URI的每个部分:        
scheme://host:port/path


比如,在下面的URI里面,        
  content://com.example.project:200/folder/subfolder/etc


模式是"内容",主机是"com.example.project",端口是"200",路经是"folder/subfolder/etc"。主机和端口一起组成URI鉴权(authority);如果未指定主机,端口会被忽略。

这些属性都是可选的,但彼此有依赖关系:一个授权要有意义,必须指定一个模式。一个路经要有意义,必须同时指定模式和鉴权。

当一个意图对象中的URI被用来和一个过滤器中的URI规格比较时,它实际上比较的是上面提到的URI的各个部分。比如,如果过滤器仅指定了一个模式,所有那个模式的URIs和这个过滤器相匹配;如果过滤器指定了一个模式、鉴权但没有路经,所有相同模式和鉴权的URIs可以匹配上,而不管它们的路经;如果过滤器指定了一个模式、鉴权和路经,只有相同模式、鉴权和路经的URIs可以匹配上。当然,一个过滤器中的路径规格可以包含通配符,这样只需要部分匹配即可。

数据<data>元素的类型属性指定了数据的MIME类型。这在过滤器里比在URI里更为常见。意图对象和过滤器都可以使用一个"*"通配符指定子类型字段-比如,"text/*"或者"audio/*"-指示任何匹配的子类型。

数据测试同时比较意图对象和过滤器中指定的URI和数据类型。规则如下:

1) 一个既不包含URI也不包含数据类型的意图对象仅在过滤器也同样没有指定任何URIs和数据类型的情况下才能通过测试。

2) 一个包含URI但没有数据类型的意图对象仅在它的URI和一个同样没有指定数据类型的过滤器里的URI匹配时才能通过测试。这通常发生在类似于mailto:和tel:这样的URIs上:它们并不引用实际数据。

3) 一个包含数据类型但不包含URI的意图对象仅在这个过滤器列举了同样的数据类型而且也没有指定一个URI的情况下才能通过测试。

4) 一个同时包含URI和数据类型(或者可从URI推断出数据类型)的意图对象可以通过测试,如果它的类型和过滤器中列举的类型相匹配的话。如果它的URI和这个过滤器中的一个URI相匹配或者它有一个内容content:或者文件file: URI而且这个过滤器没有指定一个URI,那么它也能通过测试。换句话说,一个组件被假定为支持content:和file: 数据如果它的过滤器仅列举了一个数据类型。

如果一个意图可以通过不止一个活动或服务的过滤器,用户可能会被询问要激活那个组件,并且,如果没有发现目标对象将会出现异常。


----------------------------
原文链接:https://blog.51cto.com/patterson/940924

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2020-04-08 09:22:22 重新编辑]
  Java面向对象编程-->图形用户界面(下)
  JavaWeb开发-->访问数据库(Ⅰ)
  JSP与Hibernate开发-->域对象在持久化层的四种状态
  Java网络编程-->基于UDP的数据报和套接字
  精通Spring-->Vue组件开发基础
  Vue3开发-->Vue Router路由管理器
  Android面试题汇总
  Android JSON网络数据交换
  Android 自定义Menu
  Android ExpandableListView 使用范例
  Android开发实践:用脚本编译Android工程
  Android API 中Toast类的用法
  Android ListView滑动加载
  Android语音识别 android.speech 包分析
  Android Broadcast receiver 编程-Mobile and Linux Develop...
  Android使用讯飞SDK开发语音识别及合成小Demo
  Android性能优化:App启动原理分析及启动时间优化
  Android 应用程序组件
  Android 概述
  Android 启动页倒计时自定义view实现
  Android 判断当前设备是手机还是平板
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。