好用的VPN,推荐,可以试用

slide1-e5661d23e047e1af27cdf3d85ce04120
由于各种各样的原因, 我国访问国际互联网 从来就没有 通畅过。

工作的原因,总是需要 和 外边的人沟通, 试过各种各样的 代理,goagent, 自己搭建代理服务器, 各种VPN。之后,最终我发现还是VPN 比较稳定。

尝试了几个VPN之后,我发现云梯牌VPN最合适我。

一个云梯帐号可以支持同时登陆3个设备,手机, 电脑可以同时用。可以按照国内国际流量 走不同的路线。

N个服务器,可以新加坡,香港,日本,美国都有服务器。

说明文档是系统的截图,很好看明白。新手也很容易配置。​

youtube 480P 稳定访问。

根据我的使用经验​, 上海电信,使用新加坡和日本的服务器,最稳定。youtube 白天可以720P., 晚上可以480P。

不过,没有一个VPN。可以在任何一个网络都很好,云梯可以试用3天,不满意退款。

现在有优惠活动。通过访问优惠链接 http://igotvpn.com/?r=a322705a81af163f可以优惠10元。

Django 单元测试 学习笔记

场景描述:

有一个函数,功能从输入的内容中解析出数据,保存为字典或列表。内容来源为文件,目前测试文件都保存在了一个目录下面,因为原来并没有测试,所以这些文件的正确解析结果没有保存。

现在需要测试这个函数,保证在每次更改之后,原来所有的测试文件都能被正确的解析。

 

问题:

1。被测试函数不需要数据库就可以运行,而我们使用的Django 1.4 版本,默认会生成一个 测试用数据库,而且这个数据库每次测试都会生成,测试完成之后,删除。而数据库的表字段很多,还要添加索引等,这导致初始化很慢。实际显示需要5分钟左右才能创建好数据库。

2.。测试用例太多(200多个),不可能手工确定每一个测试用例的结果,并保存起来。

3。需要知道是那个测试用例失败了。

 

解决方法:

1。创建一个新的 test_runner, 在setting 文件中指定 TEST_RUNNER = “XXX.XXX.test_runner”

代码:


# -*- coding: utf-8 -*-
import unittest
from django.conf import settings
from django.test.utils import setup_test_environment, teardown_test_environment
from django.test.testcases import OutputChecker, DocTestRunner, TestCase
from django.test.simple import DjangoTestSuiteRunner

TEST_MODULE = 'tests'
class EmailprocTestSuitRunner(DjangoTestSuiteRunner):

    def build_suite(self, label):
        suite = unittest.TestSuite()
        try:
                app_path = label + '.' + TEST_MODULE
                 test_module = __import__(app_path, {}, {}, TEST_MODULE)
        except ImportError, e:
                test_module = None
        if test_module:
                if hasattr(test_module, 'suite'):
                        suite.addTest(test_module.suite())
                else:
                        suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(test_module))
        return suite

    def run_tests(self, test_labels = None, *argv, **kwargs):
        print test_labels, type(test_labels)
print argv, kwargs

        setup_test_environment()
        settings.DEBUG = True
        suite = unittest.TestSuite()

        if test_labels:
                for label in test_labels:
                    suite.addTest(self.build_suite(label))

        result = unittest.TextTestRunner().run(suite)
        teardown_test_environment()

        return len(result.failures) + len(result.errors)

2。用一个脚本动态生成一个测试用例,使用pickle 保存到文件中。

import pickle
def savetestcase(fpath):

    data_path = "../tests.data"
    if os.path.exists(data_path):
        data = pickle.load(open(data_path, "rb"))

    else:
        data = {}
    open(data_path, "wb").close()
    relative_path = fpath.rsplit("/", 1)[-1]
    data[relative_path] = []
    for x in be_tested_function(fpath):
        if isinstance(x, tuple):
            x = list(x)
        elif isinstance(x, dict):
             x = [x]
    data[relative_path] = data[relative_path] + x
    pickle.dump(data, open(data_path, "wb"))
return

3.  测试是,从文件中读取测试用例,key是 需要测试的文件的相对路径,value 是 该文件解析之后的正确的结果

from django.utils import unittest

class Test(unittest.TestCase):                                        
    pass                                                                                                                         
                                                                              
import pickle                                                                  
import os                                                                      
data_path = "../tests.data"                                                    
if os.path.exists(data_path):                                                  
    data = pickle.load(open(data_path))                                        
else:                                                                          
     data = {}                                                                  
                                                                               
 for k, v in data.iteritems():                                                  
    print k, v                                                                 
     setattr(Test, "test_%s" % k ,  generatetest({k : v})) 

def generatetest(testcase):
    def test(self, testcase = testcase):
         ....
    return test

现在,每次有新格式需要处理的文件时,只要把相应的处理类写完, 保存一下,就可以跑测试了,不需要手动添加测试用例。

遇到的问题:
刚开始的时候 使用lambda 表达式代替 generatetest , 不行。 应该是因为 lambda 只生成 一次?
test_runner 功能还不完善。

利用树莓派做无线中继路由器

因为各种各样的原因,搬到了一个网络环境不太好的地方,距离无线路由器有点远,笔记本自带的 无线网卡 即使更新到最新的驱动程序 也无法连接。
用一个ubs 无线网卡 勉强连上了。但是速度非常的慢。

陆续采取的方法:

1、更新驱动,效果显著。
2、无线网卡放到外边,进一步提高。

最终采用的解决方法是,利用树莓派 + 一个普通路由器/最中继,具体操作如下。

需要的设备, 树莓派一个,usb 无线网卡一个,具体型号是 磊科nw336 普通无线路由器一个。

首先 配置 无线路由器,采用静态IP方法。
设置为;
IP: 192.168.20.100
netmask : 255.255.255.0
gateway : 192.168.20.1
dns : 114.114.114.114 / 8.8.8.8

树莓派 一共两块网卡,一个 自带有线网卡,一个 usb 无线网卡。

有线网卡设置:
ip:192.168.20.1
netmask : 255.255.255.0

无线网卡 连接 一个无线网络。根据自己实际情况连接。

好了。现在 无线路由器 和 树莓派 是可以拼通的。

现在 需要 在树莓派 上 利用iptables 做一个 NAT ,

具体命令:
echo “1″ > /proc/sys/net/ipv4/ip_forward 打开包转发

设置iptables

iptables -F
iptables -PINPUT ACCEPT
iptables -PFORWARD ACCEPT
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE # 这个 wlan0 应该是你的连外网的设备名称。无线网卡只有一个花 就是 wlan0

保存起来:
iptables-save > /etc/iptables.up.rules

自动启动

vi /etc/network/interfaces

添加一句
pre-up iptables-restore < /etc/iptables.up.rules

然后就可以了。

树莓派的 有线网络连接 路由器的 wan口

现在其他设备 可以和 以前一样 连到 路由器 即可 自动上网。

ubuntu 编译安装 qemu 和 kvm

在公司重新换了电脑,dell的 760 换到了 780,配置提升了不少,再也不出现开多网页也卡的现象了。哈哈哈哈。

配置详情:

Intel(R) Core(TM)2 Duo CPU     E8400  @ 3.00GHz

4GB 内存

操作系统默认的是32位的xp,这肯定是不行的,晚上就换成了 ubuntu 12.04 64位  桌面版本。第一件事情就是 卸载了 unity 桌面。不习惯啊。

工作效率降低了不少。

然后呢就是安装 qemu 和kvm。这到不是为了 什么。就是想装。已经用 visual box 装了一个 xp,运行阿里旺旺。

源代码编译 太麻烦了。

编译kvm 很简单,从官网下载最新的代码。

http://sourceforge.net/projects/kvm/files/kvm-kmod/ 下载最新的代码。除非是特别老的内核需要旧版本,一般都是直接用最新的,

编译qemu 就比较麻烦了。

因为需要安装很多库,来支持很多特性。

我需要的特性:

1、spice   显示好一些。

2、AIO

3、SDL  VNC  显示

一般就这些就可以了。

sudo apt-get  build-dep qemu-kvm

这一个命令就可以安装好很多东西。configure 一下,很多都选项都 yes了。

sudo apt-get install spice-protocol spice-server spice-client  支持spice

./configure –target-list=i386-softmmu,x86_64-softmmu  这个最好加上。否则要会支持N

多平台,编译时间长。

特别是 arm部分编译会出点问题。将config-host.mak 里面的 编译选项- fPIE 改为 -fPIC 才可以。

其他都没问题了。安装好之后,安装 qxl  驱动,显示果然好了很多。驱动可以从 spice 官网 下载。

http://spice-space.org/download/binaries/spice-guest-tools-0.1.exe

qemu 启动时, -vga qxl 参数即可。

Android 安全体系概述


Android 安全机制概述

——内容翻译自Google 官方文档。

 完整版可以从此下载:https://docs.google.com/open?id=0Bx0lAP-TDpepOVZoWk04VTJ5eEU


引言
Andriod被设计为一个真正开发的,现代化的移动平台。Android 应用程序利用先进的硬件和软件,以及本地和服务器上的数据,通过Android平台为消费者带来创新和价值。为了保护这些价值,平台必须提供一个安全环境,确保用户、数据、应用程序、设备和网络的安全性。
保护一个开放平台,需要一个强壮的安全架构和严格的安全计划。Android采用多层次的安全设计,提供了开放平台所需的灵活性,同时为平台的所有用户提供保护。
Android设计时,时刻将开发人员放在脑子中。安全控制的设计,要减少开发人员的负担。了解安全知识的开发人员可以很容易和灵活的安全控制机制合作,并且可以依赖灵活的安全控制机制。不熟悉安全知识的开发人员使用默认的安全设置。
Android设计时,考虑了设备用户。用户可以看到应用如何工作,并且通过这些应用实行控制。这个设计考虑到了攻击者可能尝试进行常见攻击,比如社工攻击说服用户安装恶意软件;攻击Android上的第三方应用;Android的设计既要减少这些攻击的可能性,而且当这些攻击成功的时,要极大的限制这些攻击的影响。
本文档概述Android安全计划的目标,描述Android安全架构的基础,并且回答系统架构师和安全分析人员最相关的问题。本文档侧重于Android核心平台的安全特性,不讨论针对特定应用程序的独立的安全问题,比如那些和浏览器或者SMS应用程序有关的。为构建Android设备、部署Android设备或者Android应用开发推荐最佳实践不是本文档的目标,在其他地方提供相关文档。
背景
Android为移动设备提供了一个开源平台和应用环境。
主要的Android平台基础包括:
硬件设置:Android可以运行在一个很宽范围的硬件配置上,包括智能手机,平板电脑和机顶盒。Android于处理器无关。但是它可以利用一些特定硬件的安全功能,比如ARM v6的 eXecute-Never。
Android操作系统:核心操作系统构建在Linux内核之上。所有的设备资源,比如照相机功能,GPS数据,蓝牙功能,电话功能,网络连接等等,通过操作系统访问。
Android应用程序运行时:Android应用程序通常使用Java编写,运行在Dalvik虚拟机。然而,许多应用程序,包括核心的Android服务和应用程序是native应用或者保护native库。Dalvik和native应用运行在同样的安全环境,包含在同样的应用程序沙盒。应用程序获得文件系统的一个私有部分,用来写入私有数据,包括数据库和原始文件。
Android应用程序扩展核心Android操作系统。有个主要的应用程序来源:
预安装的应用程序:Android包括了一个预安装的应用程序集合,有电话、电子邮件、日历、浏览器和联系人。这些工具都作为用户应用程序,提供可被其他应用访问的关键的设备功能。预安装的应用程序可能是Android开源平台的一部分,或者是OEM为特定设备开发的。
用户安装的应用程序:Android提供了一个开放的开发平台,支持任何的第三方应用。Google Play为用户提供了几十万个应用程序。
Google提供了一个基于云的服务集合,在任意兼容Android的设备上都是可用的。主要的服务是:
Google Play: Google Play 是一个服务的聚集,允许用户从他们的Android设备或者web上,发现,安装和购买应用。Google Play是得开发人员更容易接近Android用户和潜在的客户。Google Play也提供社区审查,应用程序证书验证,和其他安全服务。
Android 更新: Android更新服务为Android设备提供新的功能和安全更新,包括通过web或者OTA升级。
应用程序服务:框架运行Android应用使用云服务功能,比如备份应用程序数据、设置,和云到设备的消息来推送消息。
这些服务不是Android开源工程的一部分,不在本文档的范围之内。但是他们和大多数的Android设备的安全有关,因此,一个相关的安全文档,标题为“Google Services for Android: Security Overview”,可供参考。
Android安全计划概述
开发早期,核心的Android开发团队已经认识到,维持一个云服务提供支持,构建在Android平台上的一个繁荣的生态系统,需要强大的安全模型。因为,在整个开发周期,Android都受到一个专业的安全计划的约束。Android开发团队有机会观察移动、桌面、服务器平台如何预防和应对安全问题,并且针对在这些平台观察到的弱点,建立一个安全计划。
Android安全计划的关键组件包括:
设计审查: Android的安全处理过程开始于开发周期的早期,创造了一个丰富的和可配置的安全模型和设计。平台的每一个主要特性都被工程和安全资源审查,把合适的安全控制集成到系统架构中。
渗透测试和代码审查:平台的开发期间,Android创建的和开源组件受到严格的安全审查。这些审查由Android安全团队,Google的信息安全工程团队和独立的安全顾问执行。审查的目标是在平台开源之前,尽可能的找出薄弱点和可能的漏洞,并且模拟平台发布之后,外部安全专家将进行的分析类型。
开源和社区审查:Android开源工程可以被任何感兴趣的组织进行广泛的安全审查。Android也使用了已经经历过意义重大的外部安全审查的开源技术,比较Linux内核。Google Play为用户和公司提供了一个论坛,直接向用户提供相关应用程序的信息。
事件响应:即使采用所有的这些预防措施,安全问题仍然可能发生。这是为什么Android团队创建了一个全面的安全响应过程。一个全职的Android安全团队持续的监控Android和一般的安全社区,讨论可能的安全漏洞。当发现一个确定的问题是,Android团队有一个响应过程,使得快速的减缓漏洞,确保对所有的Android用户潜在的危害最小。这些云支持的响应包括更新Android平台(通过OTA),从Google Play移除应用,从硬件设备上移除应用。
Android平台安全架构
Android旨在通过重新利用传统操作系统的安全控制,成为移动平台最安全的和最实用的操作系统。传统操作系统的安全控制包括:
保护用户数据
保护系统资源 (包括网络)
提供给应用程序的隔离
为了实现这些目标, Android提供了一些关键的安全特性:
通过Linux内核提供OS 层面强健的安全。
强制所有应用程序使用沙盒
安全的进程间通信
应用程序签名
应用程序定义权限和用户授权机制

以下部分描述这些和Android平台其他的安全特性。图1总结了安全组件,考虑Android软件栈的各个层级。每一个组件假设该组件下面的部分是完全安全的。除了一小块Android OS代码作为root运行,所有Linux内核之上的代码都受到应用程序沙盒限制。
图1 Android软件栈

系统和内核层安全
在操作系统层面,Android平台提供了Linux内核的安全性,以及一个安全的进程间通信方式,使得运行在不同进程的应用可以安全的通信。OS层的安全特性确保,即使是native代码也受到应用程序沙盒的限制。无论该代码是应用程序自身的行为,或者是利用程序漏洞的造成的结果,系统都可以阻止恶意应用危害其他应用程序、Android系统或者设备自身。
Linux Security
Android平台的基础是Linux内核。Linux内核已经被广泛的使用了很多年,用在了上百万的安全敏感的环境中。在它不断的被研究,攻击和上千个开发人员修复的历史上,Linux已经成为一个稳定的和安全的内核,被许多企业和安全专家信任。
As the base for a mobile computing environment, the Linux kernel provides Android with several key security features, including:
作为移动计算环境的基础,Linux内核为Android提供了几个关键的安全特性:
基于用户的授权模型
进程隔离
安全IPC的可扩展机制
移除内核中不必要的和可能的不安全部分的能力
作为一个多用户操作性,Linux内核的一个基本安全目标是,隔离用户资源。Linux的安全理念是,保护用户的资源不受其他用户危害。因为,Linux提供了一下功能:
阻止用户A读取用户B的文件
确保用户A没有用尽用户B的内存
确保用户A没有用尽用户B的CPU资源
确保用户A没有用尽用户B的设备(比如:电话,GPS,蓝牙)
应用程序沙盒
Android平台充分利用了Linux基于用户的保护,将其作为标识和隔离应用程序资源的方式。Android系统为每一个应用程序分配哟个单独的用户ID(UID),并且将它以该用户身份运行在一个单独的进程。这个方法与其他使用相同用户权限运行多个应用程序的传统操作系统是不同的(包括传统的Linux配置方式)。
这设置了一个内核级的应用程序沙盒。内核使用标准的Linux攻击,比如分配给应用的用户和组ID,在进程级增强应用程序和系统之间的安全。默认的,应用程序之间互相无法交互,并且应用程序只能有限的访问操作系统。假如应用程序A(它是一个单独的应用程序)试图私自做一些恶意的事情,比如读应用程序B的数据,或者拨打电话,然后,操作系统会阻止该行为,因为应用程序A没有合适的用户权限。沙盒是简单的,可审计的,基于几十年前UNIX风格的用户进程分离和文件权限。
因为这个应用程序沙盒在内核中,安全模型扩展到了native代码和操作系统应用程序。图1中,所有的在内核之上的软件,包括操作系统库,应用程序框架,应用程序运行时,所有的应用程序都运行在沙盒中。在一些平台,开发被限制为使用特定的开发框架,API集合,或者语言,增强安全性。在Android平台,没有限制如何编写应用程序增强安全性的要求,在这方面,native代码和解释型代码一样安全。
在一些操作系统中,内存损坏错误一般会导致完全危及设备的安全性。在Android平台,因为所有的应用程序和他们的资源在OS层沙盒化,不会有这种情况发生。内存损坏错误只会允许任意代码运行在特定应用程序(指出问题的应用程序)上下文,同时具有操作系统指定的权限(既只有当前应用程序的权限)。
与所有的安全功能类似,应用程序沙盒不是不可打破的。然而,在一个配置正确的设备中,要跳出应用程序沙盒,必须攻破Linux 内核。
系统分区和安全模式
系统分区包括Android内核,以及操作系统库,应用程序运行时,应用程序框架和应用程序。该分区设置为只读模式。当用户启动设备到安全模式,只有核心的Android应用程序是可用的。确保用户可以将他们的手机启动到一个没有第三方软件的环境。
文件系统权限
UNIX风格的环境,文件系统权限确保一个用户不能改变或者读其他用户的文件。在Android情景下,每一个应用程序作为自己的用户运行。除非开发人员显式的向其他应用程序公开文件,应用程序创建的文件不能被其他应用程序读或者改变。
文件系统加密
Android3.0及仪式上的版本,提供整个文件系统的加密,所以可以使用AES128(CBC模式)和ESSIV-SHA256加密算法,在内核加密所有的用户数据。加密密钥使用128位的AES的算法,从用户密码生成的一个密钥,加密保护。阻止没有用户设备密码的非授权访问用户数据。为了抵抗猜解系统密码攻击(彩虹表,暴力破解),在使用密码解密文件系统加密密钥之前,密码加上一个随机盐值,使用标准PBKDF2算法,反复进行SHA1哈希。为了抵抗字典密码猜解攻击,Android允许设备管理员设置密码复杂度规则,操作系统执行该规则。文件系统加密要求使用用户密码,。基于图形的屏幕锁是不支持的。
更详细的文件系统加密实现可以访问:https://source.android.com/tech/encryption/android_crypto_implementation.html
密码保护
Android可被配置为,在访问设备之前,验证用户密码。更近一步的,为了阻止未授权使用设备,这个密码保护用来加密文件系统的加密密钥。
设备管理员可以要求使用密码或者密码复杂度规则。
设备管理
Android 2.2和以上版本,提供了Android设备管理API,在系统层提供了设备管理功能。比如,内置的Android Email程序使用这些API改善了Exchange支持。通过Email程序,Exchange管理员可以跨设备的强迫执行密码策略—包括字母数字密码或者数字PIN码。管理员可以远程擦除丢失的或被盗的手机(默认恢复出厂设置)。
除了应用程序和Android系统使用之外,这些API集对第三方提供的设备管理解决方案也是可用的。关于API的详细情况,可以访问:: https://developer.android.com/guide/topics/admin/device-admin.html.
内存管理的安全性增强
Android包括很多功能,使得通常的安全问题更难被利用。Android SDK,编译器,和OS使用工具使得通常的内存损坏错误明显的更难被利用,措施包括:
地址布局随机化(ASLS),随机化内存中的关键地址
基于应用的不可执行(NX),阻止栈和堆上的代码执行
ProPolice阻止栈缓冲区溢出
safe_iop减少整数溢出
扩展OpenBSD的dlmallco,阻止两次free()漏洞,和连续块攻击(chunk consolidation attacks),是利用堆损坏的常见的利用方式
OpenBSD calloc 防止内存分配时的整数溢出
Linux mmap_min_addr() 减轻空指针引用造成的权限提升
设备的Root
默认的,Android上只有内核和一个很小的内核应用程序子集运行在root权限。Android不会阻止root权限的用户或应用程序更改操作系统,内核和其他应用程序。一般的,roo可以访问所有的应用程序和应用程序数据。在Android设备上,用户更改权限,授予应用程序root权限,增加恶意软件和潜在的应用程序漏洞的安全缺陷。
对于工作在Android平台的开发人员来说,更改Android设备的能力是很重要的。需要Android设备用户有能力解锁bootloader,允许安装其他操作系统。这些操作系统可能允许拥有者获得root访问权限,以便调试应用程序和系统组件,或者访问Android API未提供给应用程序的功能。
有一些设备,采用物理手段控制了该设备的人,使用USB数据线安装可提供root权限的操作系统。当bootloader解锁机制被破坏之后,要保护所有已经存在的用户数据,要求Bootloader能够消除所有存在的用户数据作为解锁的步骤。通过内核bug或者安全漏洞或者root访问权限,可以绕过该保护机制。
使用存储在设备上的密钥加密数据,无法保护应用程序数据不受root用户的危害。应用程序可以增加一层数据保护方法,使用存储在设备之外的密钥加密。比如在服务器上或用户密码。这个方法可以提供临时的保护,当密钥不存在的时候,但是在一些时间点,密码必须提供给应用程序,此时,root用户可以访问到。
更加强健的保护用户数据不受root用户危害的方法是使用硬件解决方案。OEM厂商可能选择实现硬件解决方案,限制对特定类型内容的访问,比如用于视频播放的DRM,或者用于Google wallet的NFC相关的可信存储。
设备被偷或者丢失的情况下,Android设备上的的全文件系统加密方案,使用设备密码保护加密密钥,所以在没有用户设备密码的情况下,更改bootloader或操作系统是无效的,仍然无法访问用户数据。
Android应用程序安全
应用程序元素
Android为移动设备提供了一个开源平台和应用环境。核心的操作系统基于Linux内核。Android应用程序通常使用Java编写,运行在Dalvik虚拟机。应用程序也可以写成native代码。应用程序使用一个单一的文件安装,文件扩展名为.apk。
Android应用程序主要部分包括:
AndroidManifest.xml: AndroidManifest.xml是一个控制文件,告诉系统如何处理应用程序中所有的顶层组件(特别是activities,services,广播接收器,以及下文描述的ContentProviders)。该文件也指定请求哪些权限。
Activities: 一般的,Activity指独立的,以用户为中心的任务代码。它通常用来展示UI,但是这不是必须的——一些Activity从来不显示UI,通常情况下,Activity是应用程序的入口。
Services: Service 是代码的身体,运行在后台。它可以运行在自己的进程,或者运行在另一个应用程序进程的上下文。其他组件绑定到Services,通过远程过程调用(RPC)调用Service提供的方法。一个例子:Service作为媒体播放器,即使用户退出了多媒体选择用户界面,但是仍然希望继续播放音乐,一个Service保持应用播放,即使UI已经退出。
Broadcast Receiver: BroadcastReceiver 是一个对象,当操作系统或另一个应用程序发出一个称为Intent的IPC方式时,实力化一个Broadcast Receiver。一个应用程序可能注册一个receiver,接受电量低的消息,并基于该信息改变自身行为。
Android权限模型:访问受保护的API
默认的。Android应用程序只能访问有效范围的系统资源。系统管理Android应用程序访问资源,因为不正确的或者恶意的使用,可能对用户体验,网络,设备上的数据产生不利影响。
限制措施的实现使用了大量不同的方式。一些功能通过故意缺少API函数进行限制(比如没有API可以直接操控SIM卡),在一些例子中,角色分离提供了安全措施,与每个应用隔离存储一样。其他一些例子中,敏感的API用于可信任的应用程序,并且通过成为 Permissons 的安全机制进行保护。
受保护的API包括:
摄像功能
本地数据(GPS)
蓝牙功能Telephony functions
SMS/MMS 功能
网络/数据连接
这些资源只能通过操作系统访问,要在设备上使用受保护的API,应用程序必须在他的manifest文件中定义需要的能力。安装应用程序时候,系统会显示一个窗口,向用户说明应用程序要求的权限,并询问是否继续安装。假如用户继续安装,系统认为,用户已经授予所有请求的权限。用户不能授予或者拒绝个别的权限——用户必须授予或者拒绝所有要求的权限。
一旦授权,权限既适用于应用程序。为了避免用户疑惑,系统不会再次通知用户向应用程序授权。包含在核心操作性和OEM厂商绑定的应用程序不会向用户要求权限。当应用程序被选卸载时,权限被移除。所以之后的重新安装将会再次显示权限要求。
在设备设置里,用户能够看到他们之前安装的应用程序的权限。用户可以在全局范围关闭一些功能,比如关闭GPS,无线,或者wi-fi。
当应用程序尝试使用未在manifest文件中声明的受保护的功能时,授权会失败,系统向应用程序抛出一个安全异常。受保护的API权限检查在尽可能低的层次执行,避免被绕过。应用程序安装时,请求访问受保护的API的用户通知消息示例见图2。
系统默认的权限在以下链接描述:
https://developer.android.com/reference/android/Manifest.permission.html
应用程序可能定义私有权限,提供给其他程序使用。这样的权限没有列在上面的地址。.
定义权限时,保护层级属性告诉系统,当请求该权限时,如何通知用户。更详细的细节请访问:
https://developer.android.com/guide/topics/security/security.html.
有一些设备功能,比如发送SMS广播intents的功能,对于第三方应用是不可用的,但是可能被OEM厂商预置的应用程序使用。这些权限使用signatureOrSystem 权限。

用户如何理解第三方应用程序
Android努力的使用户清晰的和第三方应用程序交互,通知用户这些应用程序拥有的功能。安装任何应用之前,用户都会收到一个清晰的消息,说明应用程序请求的权限。安装之后,不会再次提示用户确认任何权限。
有很多理由要求在安装之前立即显示权限。此时,用户正在积极的审查关于应用程序、开发人员和功能的相关信息,决定应用程序是否符合需要和期望。同时也很重要的是,用户还没有对app建立心理和经济上的承诺,可以很容易和其他可选择的应用程序进行比较。
其他一些平台使用了不同的方法,在每一个会话开始或者应用程序使用时,通知用户,请求权限。Android的想法是,用户可以随意的无缝的在应用程序之间切换。每一次都要求确认将会使用户动作变慢,导致Android无法提供一个伟大的用户体验。用户在安装时审查权限,使得用户如果感觉不合适,可以选择不安装应用程序。
同时,许多用户界面的研究表明,过多的提示导致用户对任何显示的对话框都说:OK。Android的安全目标是有效的向用户提供重要的安全信息,不能使得用户被训练成忽略这些信息。只在中央的时候,展示一次重要的信息,用户更可能思考他们同意了什么。
一些平台选择不显示任何关于应用程序功能的信息。这个方法阻止用户容易的了解和讨论应用程序的能力。要求所有的用户做出明智的决定是不可能的,Android的授权模型使得应用程序的信息很容易的被大范围的用户所理解。比如,意外的权限请求促使更高级的用户询问关于应用程序功能的关键问题,并在一些地方分享他们的担心,比如Google Play,他们对所有用户都是可见的。
安装Google Maps时的权限 安装 gMail时的权限

Figure 2: 显示应用程序的权限
进程间通信
进程可以使用任何传统的UNIX风格的机制进行通信。例子包括文件系统,本地sockets,信号。并且,Linux权限仍然适用。
Android也提供了新的IPC机制:
Binder: 一个轻量级的基于能力的远程过程调用机制。设计为当在进程内和跨进程调用时,具有高性能。Binder的实现使用了通常的Linux驱动。详情见: https://developer.android.com/reference/android/os/Binder.html.
Services: Services (上面讨论的)可以提供使用Binder直接访问的接口。
Intents: Intent 是一个简单的消息对象,表示想要做某些事情。比如,你的应用程序想要展示一个web页面,它创建一个intents的实例表达它的意图来看到URL,并把实例提交给系统。系统中其他位置的代码(这个例子中是浏览器)知道如何处理这个个Intent,并运行它。Intents可以用于在系统范围内广播感兴趣的事件(比如通知)。详情请看: [https://developer.android.com/reference/android/content/Intent.html](https://developer.android.com/reference/android/content/Intent.html.
ContentProviders: ContentProvider 是一个数据仓库,用来访问设备上的数据。经典的例子是,用于访问用户的联系人列表。应用程序可以通过ContenProvider访问其他程序导出的数据,也可以定义自己的ContenProvider,导出自己的数据。详情: https://developer.android.com/reference/android/content/ContentProvider.html.
使用其他机制实现IPC也是可行的,比如网络socket,全局可写的文件。上面是Android推荐使用的IPC框架。Android鼓励开发人员围绕用户数据安全使用最好的做法,避免引入安全漏洞。
成本敏感的API
成本敏感的API指可能给用户或者网络带来成本的功能。Android将成本敏感型API放到操作系统控制的受保护的API列表中。用户必须显式的向申请使用成本敏感型API的第三方应用授权。这些API包括:
通讯
短信/彩信
网络/数据
应用内账单
访问NFC
访问SIM卡
底层的访问SIM卡对第三方应用是可不用的。OS处理所有和SIM卡的通信,包括访问SIM卡上的个人信息(通讯录)。应用程序不能访问AT命令,这些命令专门由无线接口层(Radio Interface Layer)访问。RIL没有提供上层API。
个人信息
Android将访问用户数据的API放入受保护的API集合。正常使用情况下,Android设备也会积累用户安装的第三方应用产生的用户数据。选择共享这些信息的应用可以使用Android OS权限检查保护这些数据。

图3:只能通过受保护的API访问敏感的用户数据
系统内容提供者可能包含个人的或个人身份信息,比如联系人和日历,这些内容已经建立了明确的权限。这个粒度提供给用户,清晰的表示可能提供给应用的信息类型。安装期间,第三方应用程序可能请求访问这些资源的权限。加入权限被授予,应用程序可以被安装,并且可以在任何时候访问这些数据。
任何手机个人信息的应用程序,默认的,将仅限于特定的应用程序。如果一个应用程序,选择使得这些数据对其他应用是可用的,授权应用程序可以申请由操作系统强制执行的IPC权限。
敏感数据输入设备
Android设备通常提供敏感数据输入设备,允许应用程序和周边环境进行交互。比如摄像头,麦克风。GPS。访问这些设备的第三方应用程序,首先,它必须由用户通过使用Android OS权限显式的提供访问。安装时,安装程序会通过名字提示用户请求传感器的权限。
假如一个应用程序想要知道用户的位置,应用程序请求权限访问用户位置。安置时,安装程序会提示用户,询问是否应用程序可以访问用户位置。任何时候,假如用户不想任何程序访问它的位置,用户可以运行“设置”,选择“位置和安全”,取消选中“使用无线网络”和“启动GPS卫星定位系统”。这将禁用设备上所有应用程序基于位置的服务。
设备元数据
Android也努力限制本质上不敏感的,但是可能间接泄漏用户、用户喜好、使用习惯等数据。
默认,应用程序无法访问操作系统日志,浏览器日,手机号码或者硬件/网络身份信息。假如应用程序在安装时,请求这些权限,安装程序将提示用户,询问是否可以访问这些信息,假如用户不授权,应用程序不会被安装。
应用程序签名
代码签名使开发人员可以识别应用程序的作者,无需创建复杂的接口和权限更新他们的应用程序。每一个运行在Android上的应用程序必须由开发人员签名。尝试安装未签名的应用程序,会被Google Play或者设备上的包安装程序拒绝。
在Google Play中,应用程序签名作为桥梁,连接Google对开发人员的信任和开发人员对他们应用程序的信任。开发者知道他们的应用程序未被修改的提供给Android设备,并且开发者对他们的应用程序的行为负责。
在Android上。应用程序签名是将程序放入它的应用程序沙箱的第一步。签名的应用程序证书定义应用程序与用户id的关联;不同的应用程序运行在不同的用户ID。应用程序签名确保应用程序不能访问其他程序的数据,除非通过已经定义好的IPC。
一个程序(APK文件)被安装到设备时,包管理程序验证该APK使用了APK文件中的证书进行签名。假如证书(更准确,证书中的公钥)匹配设备中用于其他APK签名的密钥,新的APK文件有一个选项,可以在manifest文件中指明,它和其他签名一样的APK使用同一个UID。
应用程序可以被第三方(OEM,运营商,其他应用市场)签名,或者自签名。Android提供自签名证书签名代码,开发者无需辅助和权限就可以生成自签名证书。应用程序没有必要由一个中央结构签名。Android当前不使用CA认证应用程序证书。
应用程序也可以定义在签名保护级别的安全权限,限制只允许使用同样密钥签名的应用程序访问,同时保持不同的UID和应用程序沙盒。共享应用程序沙盒的亲密关系是允许的。,通过共享UID机制,两个或更多的程序,由同一个开发者密钥签名的程序可以在他们的manifest中定义共享UID。
数字版权保护
Android平台提供了一个扩展的DRM框架,应用程序可以依据和内容绑定的许可证管理受版权保护的内容。DRM框架支持许多DRM方案,设备支持的DRM方案由设备开发商决定。
Android的DRM框架使用两层架构实现(见下图):
DRM框架API通过Android应用程序框架导出,提供给应用程序。通过Dalvik虚拟机做为标准的应用程序运行。
一个native代码DRM管理程序,实现了DRM框架,为DRM插件(代理)导出了接口,处理版权保护和为各种DRM方案解密。

图 4: 版权保护框架
Android更新
Android为安全和功能相关的目的提供系统的更新。
有两种方式更新代码:通过无线(OTA)或 side-loaded 更新。OTA更新可以通过在预定的时间放出,或者一次推送到所有的设备。这两个方式依赖于OEM厂商的喜好。Side-loaded 更新提供一个中心地址,用户可以从该地址下载zip包到本地的桌面设备或手持设备。一旦,更新拷贝或下载到SD卡,Android会识别更新,验证它的完整性和真实性,自动的更新设备。
假如一个危险的漏洞被内部发现,或者外部负责任的报告给Google,Android安全团队将会开始一些流程。
Android团队将会通知签署了不公开协议的公司,开始讨论解决方案。
.代码所有人开始fix。
团队修复Android相关的安全问题。
补丁可用时,修复方案提交给签署协议的公司。
Android团队在Android开源工程公布补丁。
OEM/承运人 向消费者推送更新。
NDA要求取保,在修复方案可用之前,安全问题不会被公开,给用户带来威胁。需要OHA成员在Android设备上运行他们自己的代码,比如bootloader,wifi驱动,和无线。一旦Android安全团队被通知,安全问题在这些合作者的代码中,他们会咨询OHA合作者,快速找到问题和相似问题的解决方案。但是,写出错误代码的OHA成员最终为修复问题负责。
假如危险的漏洞被不负责任的泄漏(例如,它被发送到一个开放论坛),Google和/或Android开源工程将会尽可能快的创建补丁。补丁通过测试可以被使用时,会发布给公众(任何合作者)。
在2011年的Google I/O,许多最大的OHA合作者在第一个版本提交18个月之后,提交了更新。提供给了用户使用最近的Android功能,也包括安全更新。
任何开发者,Android用户,安全研究人员,可以通过email发送可能的安全问题给Android安全团队,Email地址:security@android.com。如果需要,可以使用Android安全团队的PGP密钥加密。密钥可以从此下载: https://developer.android.com/security_at_android_dot_com.txt.
其他资源
The Android Security team can be reached at security@android.com.
Security information exists throughout the Android Open Source and Developer Sites. A good place to start is here: https://developer.android.com/guide/topics/security/security.html.
A Security FAQ for developers is located here: https://developer.android.com/resources/faq/security.html.
A community resource for discussion about Android security exists here: https://groups.google.com/forum/?fromgroups#!forum/android-security-discuss.

Android系统和内核层安全

系统和内核层安全

——一下内容翻译自Google官方文档。

     在操作系统层面,Android平台提供了Linux内核的安全性,以及一个安全的进程间通信方式,使得运行在不同进程的应用可以安全的通信。OS层的安全特性确保,即使是native代码也受到应用程序沙盒的限制。无论该代码是应用程序自身的行为,或者是利用程序漏洞的造成的结果,系统都可以阻止恶意应用危害其他应用程序、Android系统或者设备自身。

Linux Security

Android平台的基础是Linux内核。Linux内核已经被广泛的使用了很多年,用在了上百万的安全敏感的环境中。在它不断的被研究,攻击和上千个开发人员修复的历史上,Linux已经成为一个稳定的和安全的内核,被许多企业和安全专家信任。

作为移动计算环境的基础,Linux内核为Android提供了几个关键的安全特性:

1)        基于用户的授权模型

2)        进程隔离

3)        安全IPC的可扩展机制

4)        移除内核中不必要的和可能的不安全部分的能力

作为一个多用户操作性,Linux内核的一个基本安全目标是,隔离用户资源。Linux的安全理念是,保护用户的资源不受其他用户危害。因为,Linux提供了一下功能:

1)        阻止用户A读取用户B的文件

2)        确保用户A没有用尽用户B的内存

3)        确保用户A没有用尽用户B的CPU资源

4)        确保用户A没有用尽用户B的设备(比如:电话,GPS,蓝牙)

应用程序沙盒

Android平台充分利用了Linux基于用户的保护,将其作为标识和隔离应用程序资源的方式。Android系统为每一个应用程序分配哟个单独的用户ID(UID),并且将它以该用户身份运行在一个单独的进程。这个方法与其他使用相同用户权限运行多个应用程序的传统操作系统是不同的(包括传统的Linux配置方式)。

这设置了一个内核级的应用程序沙盒。内核使用标准的Linux攻击,比如分配给应用的用户和组ID,在进程级增强应用程序和系统之间的安全。默认的,应用程序之间互相无法交互,并且应用程序只能有限的访问操作系统。假如应用程序A(它是一个单独的应用程序)试图私自做一些恶意的事情,比如读应用程序B的数据,或者拨打电话,然后,操作系统会阻止该行为,因为应用程序A没有合适的用户权限。沙盒是简单的,可审计的,基于几十年前UNIX风格的用户进程分离和文件权限。

因为这个应用程序沙盒在内核中,安全模型扩展到了native代码和操作系统应用程序。图1中,所有的在内核之上的软件,包括操作系统库,应用程序框架,应用程序运行时,所有的应用程序都运行在沙盒中。在一些平台,开发被限制为使用特定的开发框架,API集合,或者语言,增强安全性。在Android平台,没有限制如何编写应用程序增强安全性的要求,在这方面,native代码和解释型代码一样安全。

在一些操作系统中,内存损坏错误一般会导致完全危及设备的安全性。在Android平台,因为所有的应用程序和他们的资源在OS层沙盒化,不会有这种情况发生。内存损坏错误只会允许任意代码运行在特定应用程序(指出问题的应用程序)上下文,同时具有操作系统指定的权限(既只有当前应用程序的权限)。

与所有的安全功能类似,应用程序沙盒不是不可打破的。然而,在一个配置正确的设备中,要跳出应用程序沙盒,必须攻破Linux 内核。

系统分区和安全模式

系统分区包括Android内核,以及操作系统库,应用程序运行时,应用程序框架和应用程序。该分区设置为只读模式。当用户启动设备到安全模式,只有核心的Android应用程序是可用的。确保用户可以将他们的手机启动到一个没有第三方软件的环境。

文件系统权限

UNIX风格的环境,文件系统权限确保一个用户不能改变或者读其他用户的文件。在Android情景下,每一个应用程序作为自己的用户运行。除非开发人员显式的向其他应用程序公开文件,应用程序创建的文件不能被其他应用程序读或者改变。

文件系统加密

Android3.0及仪式上的版本,提供整个文件系统的加密,所以可以使用AES128(CBC模式)和ESSIV-SHA256加密算法,在内核加密所有的用户数据。加密密钥使用128位的AES的算法,从用户密码生成的一个密钥,加密保护。阻止没有用户设备密码的非授权访问用户数据。为了抵抗猜解系统密码攻击(彩虹表,暴力破解),在使用密码解密文件系统加密密钥之前,密码加上一个随机盐值,使用标准PBKDF2算法,反复进行SHA1哈希。为了抵抗字典密码猜解攻击,Android允许设备管理员设置密码复杂度规则,操作系统执行该规则。文件系统加密要求使用用户密码,。基于图形的屏幕锁是不支持的。

更详细的文件系统加密实现可以访问:https://source.android.com/tech/encryption/android_crypto_implementation.html

密码保护

Android可被配置为,在访问设备之前,验证用户密码。更近一步的,为了阻止未授权使用设备,这个密码保护用来加密文件系统的加密密钥。

设备管理员可以要求使用密码或者密码复杂度规则。

设备管理

Android 2.2和以上版本,提供了Android设备管理API,在系统层提供了设备管理功能。比如,内置的Android Email程序使用这些API改善了Exchange支持。通过Email程序,Exchange管理员可以跨设备的强迫执行密码策略—包括字母数字密码或者数字PIN码。管理员可以远程擦除丢失的或被盗的手机(默认恢复出厂设置)。

除了应用程序和Android系统使用之外,这些API集对第三方提供的设备管理解决方案也是可用的。关于API的详细情况,可以访问:: https://developer.android.com/guide/topics/admin/device-admin.html.

内存管理的安全性增强

Android包括很多功能,使得通常的安全问题更难被利用。Android SDK,编译器,和OS使用工具使得通常的内存损坏错误明显的更难被利用,措施包括:

1)        地址布局随机化(ASLS),随机化内存中的关键地址

2)        基于应用的不可执行(NX),阻止栈和堆上的代码执行

3)        ProPolice阻止栈缓冲区溢出

4)        safe_iop减少整数溢出

5)        扩展OpenBSD的dlmallco,阻止两次free()漏洞,和连续块攻击(chunk consolidation attacks),是利用堆损坏的常见的利用方式

6)        OpenBSD calloc 防止内存分配时的整数溢出

7)        Linux mmap_min_addr() 减轻空指针引用造成的权限提升

设备的Root

默认的,Android上只有内核和一个很小的内核应用程序子集运行在root权限。Android不会阻止root权限的用户或应用程序更改操作系统,内核和其他应用程序。一般的,roo可以访问所有的应用程序和应用程序数据。在Android设备上,用户更改权限,授予应用程序root权限,增加恶意软件和潜在的应用程序漏洞的安全缺陷。

对于工作在Android平台的开发人员来说,更改Android设备的能力是很重要的。需要Android设备用户有能力解锁bootloader,允许安装其他操作系统。这些操作系统可能允许拥有者获得root访问权限,以便调试应用程序和系统组件,或者访问Android API未提供给应用程序的功能。

有一些设备,采用物理手段控制了该设备的人,使用USB数据线安装可提供root权限的操作系统。当bootloader解锁机制被破坏之后,要保护所有已经存在的用户数据,要求Bootloader能够消除所有存在的用户数据作为解锁的步骤。通过内核bug或者安全漏洞或者root访问权限,可以绕过该保护机制。

使用存储在设备上的密钥加密数据,无法保护应用程序数据不受root用户的危害。应用程序可以增加一层数据保护方法,使用存储在设备之外的密钥加密。比如在服务器上或用户密码。这个方法可以提供临时的保护,当密钥不存在的时候,但是在一些时间点,密码必须提供给应用程序,此时,root用户可以访问到。

更加强健的保护用户数据不受root用户危害的方法是使用硬件解决方案。OEM厂商可能选择实现硬件解决方案,限制对特定类型内容的访问,比如用于视频播放的DRM,或者用于Google wallet的NFC相关的可信存储。

设备被偷或者丢失的情况下,Android设备上的的全文件系统加密方案,使用设备密码保护加密密钥,所以在没有用户设备密码的情况下,更改bootloader或操作系统是无效的,仍然无法访问用户数据。

Android平台安全架构

Android平台安全架构

Android旨在通过重新利用传统操作系统的安全控制,成为移动平台最安全的和最实用的操作系统。传统操作系统的安全控制包括:

保护用户数据

保护系统资源 (包括网络)

提供给应用程序的隔离

为了实现这些目标, Android提供了一些关键的安全特性:

通过Linux内核提供OS 层面强健的安全。

强制所有应用程序使用沙盒

安全的进程间通信

应用程序签名

应用程序定义权限和用户授权机制

以下部分描述这些和Android平台其他的安全特性。图1总结了安全组件,考虑Android软件栈的各个层级。每一个组件假设该组件下面的部分是完全安全的。除了一小块Android OS代码作为root运行,所有Linux内核之上的代码都受到应用程序沙盒限制。

 

图1 Android软件栈

Android安全计划概述

Android安全计划概述

——以下内容翻译自Google官方文档

开发早期,核心的Android开发团队已经认识到,维持一个云服务提供支持,构建在Android平台上的一个繁荣的生态系统,需要强大的安全模型。因为,在整个开发周期,Android都受到一个专业的安全计划的约束。Android开发团队有机会观察移动、桌面、服务器平台如何预防和应对安全问题,并且针对在这些平台观察到的弱点,建立一个安全计划。

Android安全计划的关键组件包括:

设计审查: Android的安全处理过程开始于开发周期的早期,创造了一个丰富的和可配置的安全模型和设计。平台的每一个主要特性都被工程和安全资源审查,把合适的安全控制集成到系统架构中。

渗透测试和代码审查:平台的开发期间,Android创建的和开源组件受到严格的安全审查。这些审查由Android安全团队,Google的信息安全工程团队和独立的安全顾问执行。审查的目标是在平台开源之前,尽可能的找出薄弱点和可能的漏洞,并且模拟平台发布之后,外部安全专家将进行的分析类型。

开源和社区审查:Android开源工程可以被任何感兴趣的组织进行广泛的安全审查。Android也使用了已经经历过意义重大的外部安全审查的开源技术,比较Linux内核。Google Play为用户和公司提供了一个论坛,直接向用户提供相关应用程序的信息。

事件响应:即使采用所有的这些预防措施,安全问题仍然可能发生。这是为什么Android团队创建了一个全面的安全响应过程。一个全职的Android安全团队持续的监控Android和一般的安全社区,讨论可能的安全漏洞。当发现一个确定的问题是,Android团队有一个响应过程,使得快速的减缓漏洞,确保对所有的Android用户潜在的危害最小。这些云支持的响应包括更新Android平台(通过OTA),从Google Play移除应用,从硬件设备上移除应用。

Android 安全机制概述

Android 安全机制概述

——以下内容翻译自google官方文档

引言

Andriod被设计为一个真正开发的,现代化的移动平台。 阅读余下文章

chrome NPAPI插件和扩展

最近没什么事情,随便整点什么。

插件功能是提高QVOD 的chrome支持。好像已经有好的了,只是想学习下怎么写插件。

这里记录下学到的几个知识点。

1、因为有的网页会动态刷新,因此选择执行插件的时机和重新执行很重要。

1)页面更新是执行某js或js代码

function InsertFunc(tabId,changeInfo,tab)
{
chrome.tabs.executeScript(tabId,{file : “q.js”,allFrames :true});
return true;
}

//注册事件的响应函数
chrome.tabs.onUpdated.addListener(InsertFunc);  页面更新时,执行一个js文件。

2)js执行时间

“content_scripts”: [ {
“js”: [ “q.js” ],

“matches”: [ “http://*/*&#8221;, “https://*/*&#8221;,”file://*/*” ],

“run_at”: “document_end”,//start”,//”document_end”, // 共三个选项,还有一个 document_idle。
“all_frames”: true //在所有的iframe 中起作用 作用于有多个 iframe的网页。

3、NPAPI插件开发模型:

很简单,但是各个浏览器不太一样,在chrome中,如果 hasProperty  、getProperty 没有实现,需要返回 false,而不是 ture。

其他函数 都很简单,看例子就可以明白。

#include <stdio.h>
#include <windows.h>
#include <npapi.h>
#include <npfunctions.h>
#include <npruntime.h>
static NPNetscapeFuncs Browser;
NPNetscapeFuncs * browser=&Browser;

char * MIMEtype=”application/xl_qvod_plugin”;

static const char *plugin_method_name_open = “GetQvodPlayerStart”;

char processpath[256] = “”;//”D:\\Program Files\\QvodPlayer\\QvodPlayer.exe”;

char processpath_1[] = “D:\\Program Files\\QvodPlayer\\QvodPlayer.exe”;

bool plugin_has_method(NPObject *obj, NPIdentifier methodName);
bool plugin_invoke(NPObject *obj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result);
bool hasProperty(NPObject *obj, NPIdentifier propertyName);
bool getProperty(NPObject *obj, NPIdentifier propertyName, NPVariant *result);
bool invokeDefault(NPObject *obj, const NPVariant *args, uint32_t argCount, NPVariant *result);
static struct NPClass scriptablePluginClass = {
NP_CLASS_STRUCT_VERSION,
NULL,
NULL,
NULL,
plugin_has_method,
plugin_invoke,
invokeDefault,
hasProperty,
getProperty,
NULL,
NULL,
NULL,
NULL,
};
bool plugin_has_method(NPObject *obj, NPIdentifier methodName)
{

NPUTF8 *name = browser->utf8fromidentifier(methodName);

return true;
}

bool plugin_invoke(NPObject *obj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result)
{

NPUTF8 *name = browser->utf8fromidentifier(methodName);

if (strcmp(name,”QvodPlayerStart”) == 0 && processpath && argCount == 1)
{

char * fileurl = (char *)NPVARIANT_TO_STRING(args[0]).UTF8Characters;
char qvodcmd[2048] = “”;
sprintf_s(qvodcmd,”%s%s%s”,processpath,” -qvodurl “,fileurl);
system(qvodcmd);
}
return true;

}

bool invokeDefault(NPObject *obj, const NPVariant *args, uint32_t argCount, NPVariant *result)
{

result->type = NPVariantType_Int32;
result->value.intValue = 42;
return true;
}
bool hasProperty(NPObject *obj, NPIdentifier propertyName)
{

return false;
}

bool getProperty(NPObject *obj, NPIdentifier propertyName, NPVariant *result)
{

return false;
}
//接口的实现

/*
在此函数获得快播地址
*/
NPError OSCALL NP_Initialize(NPNetscapeFuncs * aNPNFuncs)
{

if(aNPNFuncs)
{
browser=aNPNFuncs;
char regkey[] = “CLSID\\{F3D0D36F-23F8-4682-A195-74C92B03D4AF}\\InprocServer32″;//”Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders”;

ULONG dType = REG_SZ;
char cachepath[128];
DWORD siz = 128;
HKEY hKey;
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, regkey, 0, KEY_QUERY_VALUE, &hKey)==0)
{
RegQueryValueEx(hKey, NULL, 0, &dType,(LPBYTE) cachepath, &siz);
if(siz != 0)
{
for(int i = siz -1;i >= 0 ;i –)
{
if (cachepath[i] == ‘\\’)
{
cachepath[i+1] = ”;
sprintf_s(processpath,”%s%s”,cachepath,”QvodPlayer.exe”);

break;
}
}
}

RegCloseKey(hKey);
}

return NPERR_NO_ERROR;
}
else
{
return NPERR_INVALID_FUNCTABLE_ERROR;
}

}
NPError OSCALL NP_GetEntryPoints(NPPluginFuncs * pluginFuncs)
{
pluginFuncs->version = 1;
pluginFuncs->size = sizeof(NPPluginFuncs);
pluginFuncs->newp = NPP_New;
pluginFuncs->destroy = NPP_Destroy;
pluginFuncs->setwindow = NPP_SetWindow;
pluginFuncs->newstream = NPP_NewStream;
pluginFuncs->destroystream = NPP_DestroyStream;
pluginFuncs->asfile = NPP_StreamAsFile;
pluginFuncs->writeready = NPP_WriteReady;
pluginFuncs->write = NPP_Write;
pluginFuncs->print = NPP_Print;
pluginFuncs->event = NPP_HandleEvent;
pluginFuncs->urlnotify = NPP_URLNotify;
pluginFuncs->getvalue = NPP_GetValue;
pluginFuncs->setvalue = NPP_SetValue;
pluginFuncs->javaClass=NULL;

return NPERR_NO_ERROR;
}

const char * NP_GetMIMEDescription()
{
return “application/xl_qvod_chrome:.QvodPlayer:qvod_chrome”;
}
NPError OSCALL NP_Shutdown(void)
{
return NPERR_NO_ERROR;

}

NPError NPP_New(NPMIMEType pluginType,
NPP instance, uint16_t mode,
int16_t argc, char* argn[],
char* argv[], NPSavedData* saved)
{
if(!instance->pdata)
{
NPObject * NPO;
if(!(NPO = browser->createobject(instance, &scriptablePluginClass)))
return NPERR_INVALID_INSTANCE_ERROR;
else
{
instance->pdata = NPO;
return NPERR_NO_ERROR;

}
}
return NPERR_INVALID_INSTANCE_ERROR;

}

NPError NPP_Destroy(NPP instance, NPSavedData **save)
{
NPObject *pluginInstance=(NPObject *)instance->pdata;
if(!pluginInstance)
{
browser->releaseobject(pluginInstance);
pluginInstance = NULL;
}
return NPERR_NO_ERROR;
}
BOOL _stdcall DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{

return true;
}
NPError NPP_SetWindow(NPP instance, NPWindow* window)
{
return NPERR_NO_ERROR;
}
NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype)
{
*stype = NP_ASFILEONLY;
return NPERR_NO_ERROR;
}

NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason)
{
return NPERR_NO_ERROR;
}

int NPP_WriteReady(NPP instance, NPStream* stream)
{
return 0;
}

int NPP_Write(NPP instance, NPStream* stream, int offset, int len, void* buffer)
{
return 0;
}

void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname)
{
}

void NPP_Print(NPP instance, NPPrint* platformPrint)
{

}
int16_t NPP_HandleEvent(NPP instance, void* event)
{
return 0;
}

void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)
{

}

NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
{

NPObject *pluginInstance=NULL;
switch(variable) {
case NPPVpluginScriptableNPObject:

pluginInstance=(NPObject *)instance->pdata;
if (pluginInstance)
{
browser->retainobject(pluginInstance);
}
*(NPObject **)value = pluginInstance;
break;
default:
return NPERR_GENERIC_ERROR;
}

return NPERR_NO_ERROR;
}

NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value)
{
return NPERR_GENERIC_ERROR;
}

4、 js调用方法:

<script type=”text/javascript”>

function InvokeQvodPlayer(url)
{
var xl_plugin = document.getElementById(“xl_qvod_chrome”);
xl_plugin.QvodPlayerStart(“\”” + url + “\””);

}

其中 QvodPlayerStart 是自己实现的方法,浏览器调用 invoke函数,QvodPlayerStart 作为参数传递进去。url也是参数。

其他:

插件的background.html 的console.log 不会显示在网页的 console台。

MIMEType 的类型要在 rc文件里面指定,格式可以使用 npruntime 提供的例子里面的,修改MIMEType 类型就可以了。

最后的功能基本都实现了。小实验到此为止。学了很多。