对于单独的Web app应用来说,加载进来的url一般不能保证它的安全性。那么如何来处理url安全性的问题呢。

让我们来看看PhoneGap是如何做的。

PhoneGap采用了白名单的形式,认为在白名单中的url认为是安全的,不在白名单中的url是不安全的。对于安全的url,PhoneGap的Web app会直接打开,对于不安全的url,会通过浏览器打开。

那么怎么增加白名单呢?PhoneGap是需要在配置文件res/xml/config.xml中设置,如下:

 <cordova>
- <!-- access elements control the Android whitelist.
Domains are assumed blocked unless set otherwise -->
<access origin="http://127.0.0.1*" />
- <!-- allow local pages
-->
- <!-- <access origin="https://example.com" /> allow any secure requests to example.com
-->
- <!-- <access origin="https://example.com" subdomains="true" /> such as above, but including subdomains, such as www
-->
<access origin=".*" />
<log level="DEBUG" />
<preference name="useBrowserHistory" value="false" />
<preference name="exit-on-suspend" value="false" />
- <plugins>
<plugin name="App" value="org.apache.cordova.App" />
<plugin name="Geolocation" value="org.apache.cordova.GeoBroker" />
<plugin name="Device" value="org.apache.cordova.Device" />
<plugin name="Accelerometer" value="org.apache.cordova.AccelListener" />
<plugin name="Compass" value="org.apache.cordova.CompassListener" />
<plugin name="Media" value="org.apache.cordova.AudioHandler" />
<plugin name="Camera" value="org.apache.cordova.CameraLauncher" />
<plugin name="Contacts" value="org.apache.cordova.ContactManager" />
<plugin name="File" value="org.apache.cordova.FileUtils" />
<plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager" />
<plugin name="Notification" value="org.apache.cordova.Notification" />
<plugin name="Storage" value="org.apache.cordova.Storage" />
<plugin name="Temperature" value="org.apache.cordova.TempListener" />
<plugin name="FileTransfer" value="org.apache.cordova.FileTransfer" />
<plugin name="Capture" value="org.apache.cordova.Capture" />
<plugin name="Battery" value="org.apache.cordova.BatteryListener" />
<plugin name="SplashScreen" value="org.apache.cordova.SplashScreen" />
<plugin name="Echo" value="org.apache.cordova.Echo" />
<plugin name="Globalization" value="org.apache.cordova.Globalization" />
</plugins>
</cordova>

其中,<access origin="http://127.0.0.1*" />就是加的白名单,我们只需要将网址后面加上*,上格式加进配置文件即可。

那么PhoneGap又是如何实现白名单的呢?让我们看一下源代码:CordovaWebView.java。CordovaWebView是显示的WebView的基类。它在初始化时,会加载配置文件的配置项,源代码如下:

    /**
* Load Cordova configuration from res/xml/cordova.xml.
* Approved list of URLs that can be loaded into DroidGap
* <access origin="http://server regexp" subdomains="true" />
* Log level: ERROR, WARN, INFO, DEBUG, VERBOSE (default=ERROR)
* <log level="DEBUG" />
*/
private void loadConfiguration() {
int id = getResources().getIdentifier("config", "xml", this.cordova.getActivity().getPackageName());
if(id == 0)
{
id = getResources().getIdentifier("cordova", "xml", this.cordova.getActivity().getPackageName());
Log.i("CordovaLog", "config.xml missing, reverting to cordova.xml");
}
if (id == 0) {
LOG.i("CordovaLog", "cordova.xml missing. Ignoring...");
return;
}
XmlResourceParser xml = getResources().getXml(id);
int eventType = -1;
while (eventType != XmlResourceParser.END_DOCUMENT) {
if (eventType == XmlResourceParser.START_TAG) {
String strNode = xml.getName();
if (strNode.equals("access")) {
String origin = xml.getAttributeValue(null, "origin");
String subdomains = xml.getAttributeValue(null, "subdomains");
if (origin != null) {
this.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
}
}
else if (strNode.equals("log")) {
String level = xml.getAttributeValue(null, "level");
LOG.i("CordovaLog", "Found log level %s", level);
if (level != null) {
LOG.setLogLevel(level);
}
}
else if (strNode.equals("preference")) {
String name = xml.getAttributeValue(null, "name");
String value = xml.getAttributeValue(null, "value"); LOG.i("CordovaLog", "Found preference for %s=%s", name, value);
Log.d("CordovaLog", "Found preference for " + name + "=" + value); // Save preferences in Intent
this.cordova.getActivity().getIntent().putExtra(name, value);
}
}
try {
eventType = xml.next();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} // Init preferences
if ("true".equals(this.getProperty("useBrowserHistory", "false"))) {
this.useBrowserHistory = true;
}
else {
this.useBrowserHistory = false;
} if ("true".equals(this.getProperty("fullscreen", "false"))) {
this.cordova.getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
this.cordova.getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}

在解析xml文件时,会将origin标签中的内容加入白名单,调用的是addWhiteListEntry方法。下面我们来看看addWhiteListEntry方法的源代码:

    public void addWhiteListEntry(String origin, boolean subdomains) {
try {
// Unlimited access to network resources
if (origin.compareTo("*") == 0) {
LOG.d(TAG, "Unlimited access to network resources");
this.whiteList.add(Pattern.compile(".*"));
} else { // specific access
// check if subdomains should be included
// TODO: we should not add more domains if * has already been added
if (subdomains) {
// XXX making it stupid friendly for people who forget to include protocol/SSL
if (origin.startsWith("http")) {
this.whiteList.add(Pattern.compile(origin.replaceFirst("https?://", "^https?://(.*\\.)?")));
} else {
this.whiteList.add(Pattern.compile("^https?://(.*\\.)?" + origin));
}
LOG.d(TAG, "Origin to allow with subdomains: %s", origin);
} else {
// XXX making it stupid friendly for people who forget to include protocol/SSL
if (origin.startsWith("http")) {
this.whiteList.add(Pattern.compile(origin.replaceFirst("https?://", "^https?://")));
} else {
this.whiteList.add(Pattern.compile("^https?://" + origin));
}
LOG.d(TAG, "Origin to allow: %s", origin);
}
}
} catch (Exception e) {
LOG.d(TAG, "Failed to add origin %s", origin);
}
}

我们可以看到,它用正则表达式解析后将白名单中的url加入到whiteList这个属性中,而whiteList是个ArrayList类型的属性。

那么PhoneGap的Web app在显示网页时又是如何利用白名单的呢?让我们继续来看下面的源代码,这是加载网页时会调用的方法:

    /**
* Load the specified URL in the Cordova webview or a new browser instance.
*
* NOTE: If openExternal is false, only URLs listed in whitelist can be loaded.
*
* @param url The url to load.
* @param openExternal Load url in browser instead of Cordova webview.
* @param clearHistory Clear the history stack, so new page becomes top of history
* @param params DroidGap parameters for new app
*/
public void showWebPage(String url, boolean openExternal, boolean clearHistory, HashMap<String, Object> params) {
LOG.d(TAG, "showWebPage(%s, %b, %b, HashMap", url, openExternal, clearHistory); // If clearing history
if (clearHistory) {
this.clearHistory();
} // If loading into our webview
if (!openExternal) { // Make sure url is in whitelist
if (url.startsWith("file://") || url.indexOf(this.baseUrl) == 0 || isUrlWhiteListed(url)) {
// TODO: What about params? // Clear out current url from history, since it will be replacing it
if (clearHistory) {
this.urls.clear();
} // Load new URL
this.loadUrl(url);
}
// Load in default viewer if not
else {
LOG.w(TAG, "showWebPage: Cannot load URL into webview since it is not in white list. Loading into browser instead. (URL=" + url + ")");
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
cordova.getActivity().startActivity(intent);
} catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error loading url " + url, e);
}
}
} // Load in default view intent
else {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
cordova.getActivity().startActivity(intent);
} catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error loading url " + url, e);
}
}
}

我们可以看到,里面会用isUrlWhiteListed等方法判断该url是否在白名单中,或者是否安全,然后对安全的url直接通过loadUrl来 加载进该Web app,对于PhoneGap认为不安全的url会通过发Intent的形式打开浏览器加载该网页。

下面再贴一段isUrlWhiteListed方法的源代码:

    /**
* Determine if URL is in approved list of URLs to load.
*
* @param url
* @return
*/
public boolean isUrlWhiteListed(String url) { // Check to see if we have matched url previously
if (this.whiteListCache.get(url) != null) {
return true;
} // Look for match in white list
Iterator<Pattern> pit = this.whiteList.iterator();
while (pit.hasNext()) {
Pattern p = pit.next();
Matcher m = p.matcher(url); // If match found, then cache it to speed up subsequent comparisons
if (m.find()) {
this.whiteListCache.put(url, true);
return true;
}
}
return false;
}

Android PhoneGap源码分析——白名单的更多相关文章

  1. Appium Android Bootstrap源码分析之启动运行

    通过前面的两篇文章<Appium Android Bootstrap源码分析之控件AndroidElement>和<Appium Android Bootstrap源码分析之命令解析 ...

  2. Appium Android Bootstrap源码分析之命令解析执行

    通过上一篇文章<Appium Android Bootstrap源码分析之控件AndroidElement>我们知道了Appium从pc端发送过来的命令如果是控件相关的话,最终目标控件在b ...

  3. Appium Android Bootstrap源码分析之控件AndroidElement

    通过上一篇文章<Appium Android Bootstrap源码分析之简介>我们对bootstrap的定义以及其在appium和uiautomator处于一个什么样的位置有了一个初步的 ...

  4. Android HandlerThread 源码分析

    HandlerThread 简介: 我们知道Thread线程是一次性消费品,当Thread线程执行完一个耗时的任务之后,线程就会被自动销毁了.如果此时我又有一 个耗时任务需要执行,我们不得不重新创建线 ...

  5. Android Choreographer 源码分析

    Choreographer 的作用主要是配合 Vsync ,给上层 App 的渲染提供一个稳定的 Message 处理的时机,也就是 Vsync 到来的时候 ,系统通过对 Vsync 信号周期的调整, ...

  6. Appium Android Bootstrap源码分析之简介

    在上一个系列中我们分析了UiAutomator的核心源码,对UiAutomator是怎么运行的原理有了根本的了解.今天我们会开始另外一个在安卓平台上基于UiAutomator的新起之秀--Appium ...

  7. Android base-adapter-helper 源码分析与扩展

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/44014941,本文出自:[张鸿洋的博客] 本篇博客是我加入Android 开源项 ...

  8. android消息处理源码分析

    一.简介消息处理机制主要涉及到这几个类:1.Looper2.MessageQueue3.Message4.Handler 二.源码分析 Looper.class的关键源码: //保存Looper对象, ...

  9. Android -- ViewGroup源码分析+自定义

    1,我们前三篇博客了解了一下自定义View的基本方法和流程 从源码的角度一步步打造自己的TextView 深入了解自定义属性 onMeasure()源码分析 之前,我们只是学习过自定义View,其实自 ...

随机推荐

  1. POJ 1811 Prime Test

    题意:对于一个大整数,判断是否质数,如果不是质数输出最小质因子. 解法:判断质数使用Miller-Rabin测试,分解质因子使用Pollard-Rho,Miller-Rabin测试用的红书模板,将测试 ...

  2. Android之APK文件签名——keytool和jarsigner

    一.生成密钥库将位置定位在jdk的bin文件中,输入以下命名行:keytool -genkey -alias ChangeBackgroundWidget.keystore -keyalg RSA - ...

  3. util-C# 复杂条件查询(sql 复杂条件查询)查询解决方案

    ylbtech-funcation-util:  C# 复杂条件查询(sql 复杂条件查询)查询解决方案 C# 复杂条件查询(sql 复杂条件查询)查询解决方案 1.A,Ylbtech.Model返回 ...

  4. new trip

    离开YY已经快一周了,特别感谢以前的老大姚冬和朱云峰,从他俩身上学到了很多.这个决定也经过了很长的纠结,不想再做个犹豫不决的人,所以最后还是坚定了最初的信念,也算是对半年前自己的一个完好交代,以防将来 ...

  5. JQuery插件之图片轮播插件–slideBox

    来源:http://www.ido321.com/852.html 今天偶然发现了一个比较好用的图片轮播插件—slideBox 先看看效果:http://slidebox.sinaapp.com/ 代 ...

  6. XNA Game Studio 4.0 Programming 随便读,随便记 “Game Class”

    XNA 中的 Game 类,是所有神奇事情发生的地方.几乎游戏中所有的事情都由它来操办. 它是项目中的王者,让我们深入窥探一番: 虚方法 Game 本身从众多其它地方继续了许多能力才能完成游戏中的事情 ...

  7. matlab特征值分解和奇异值分解

    特征值分解 函数 eig 格式 d = eig(A)         %求矩阵A的特征值d,以向量形式存放d. d = eig(A,B)       %A.B为方阵,求广义特征值d,以向量形式存放d. ...

  8. HDU5744:Keep On Movin(字符串)

    题意: 给出t组测试数据,每组给出正整数n表示有n种字符,接下来给出n个数表示该种字符的数目,操作一下,使得可以构造的最小回文串字符数目最大且输出. 分析: 如果每个字符出现次数都是偶数, 那么答案显 ...

  9. Spark SQL概念学习系列之Spark生态之Spark SQL(七)

    具体,见

  10. picture to string

    图片转化为字符原理: 一张m*n大小的图片,实际上可以看成是一个m*n的矩阵.矩阵的每一个元素就是一个Color值,不同的Color值,用不同的Ascii可以在屏幕上打印显示的字符来代替,于是可以得到 ...