`

Android学习笔记之一谁动了我的接口附checkPermission流程(Dean)[转]

 
阅读更多

前段时间接到一个有趣的需求!我们实现的某某功能的手机对外提供了API!结果有希望只有自己承认的厂商的APK才能使用这些接口!其他的过滤掉! 

哈哈!看上去挺变态的!对外公布的API又不让人家用!没办法啊!需求就是爷!一个字做! 
回顾android安全机制貌似没有这么一项功能!不过咱能做!谁叫咱能改源码呢!有源码什么不能改了啊!哈哈!。。。。 

那么方案调研过程我们省略这里面涉及的知识比较多!直接上方案了! 

步骤是先想法知道谁调用了你的接口!然后把调用接口的apk的厂商信息找出来! 
同一个厂商的apk的签名应该是一样的!拥有同样的signature以及pubkeyid!所以最终目的是得到signature! 
研究查到有如下接口 

Java代码




  1. PackageInfo pkgInfo;  
  2.         try {  
  3.             pkgInfo = getPackageManager().getPackageInfo("packagename", PackageManager.GET_SIGNATURES);  
  4.   
  5.             Signature enterproidSign = pkgInfo.signatures[0];  
  6.               
  7.             if (!enterproidSign.toCharsString().equals(key)) {  
  8.                 // Wrong signature  
  9.                 return;  
  10.             }  
  11.         } catch (NameNotFoundException e) {  
  12.             // TODO Auto-generated catch block  
  13.             e.printStackTrace();  
复制代码

也就是说当务之急就是找到谁调用了这个接口!即是packagename! 
本来我们知道想知道谁调用了你只要在参数中加入context的信息就很容易得到apk的唯一标识包名了! 
如下面的code 

Java代码  




  1. String packageName = this.getApplicationInfo().packageName;  
  2. Log.e("Dean", "getApplicationInfo:"+packageName);  
  3. String dataDir = this.getApplicationInfo().dataDir;  
  4. Log.e("Dean", "getApplicationInfo:dataDir"+dataDir);  
  5. String sourceDir = this.getApplicationInfo().sourceDir;  
  6. Log.e("Dean", "getApplicationInfo:sourceDir"+sourceDir);      
  7. String publicSourceDir = this.getApplicationInfo().publicSourceDir;  
  8. Log.e("Dean", "getApplicationInfo:publicSourceDir"+publicSourceDir);  
  9. int descriptionRes = this.getApplicationInfo().descriptionRes;  
  10. Log.e("Dean", "getApplicationInfo:descriptionRes"+descriptionRes);
复制代码


偏偏接口中没有context的参数!而且这个方式貌似就有局限性了! 
那么我们可以想想在做checkpermission的判断的时候也需要知道是哪个apk吧!可以看看别人是怎么做到的! 
看一下源代码: 

Java代码




  1. public int checkCallingOrSelfPermission(String permission) {  
  2.     if (permission == null) {  
  3.         throw new IllegalArgumentException("permission is null");  
  4.     }  
  5.     return checkPermission(permission, Binder.getCallingPid(),  
  6.             Binder.getCallingUid());  
  7. }  
复制代码

这里可以通过Binder.getCallingPid(),Binder.getCallingUid()的到apk的 pid 和 uid! 
那看看源码流程是怎么样的 

Java代码




  1. /** 
  2.      * This can be called with or without the global lock held. 
  3.      */  
  4.     int checkComponentPermission(String permission, int pid, int uid,  
  5.             int owningUid, boolean exported) {  
  6.         // We might be performing an operation on behalf of an indirect binder  
  7.         // invocation, e.g. via {@link #openContentUri}.  Check and adjust the  
  8.         // client identity accordingly before proceeding.  
  9.         Identity tlsIdentity = sCallerIdentity.get();  
  10.         if (tlsIdentity != null) {  
  11.             Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"  
  12.                     + tlsIdentity.pid + "," + tlsIdentity.uid + "}");  
  13.             uid = tlsIdentity.uid;  
  14.             pid = tlsIdentity.pid;  
  15.         }  
  16.   
  17.         // Root, system server and our own process get to do everything.  
  18.         if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||  
  19.             !Process.supportsProcesses()) {  
  20.             return PackageManager.PERMISSION_GRANTED;  
  21.         }  
  22.         // If there is a uid that owns whatever is being accessed, it has  
  23.         // blanket access to it regardless of the permissions it requires.  
  24.         if (owningUid >= 0 && uid == owningUid) {  
  25.             return PackageManager.PERMISSION_GRANTED;  
  26.         }  
  27.         Log.e("Dean", "ActivityManagerService checkComponentPermission uid:" + uid + "pid:" + pid  
  28.                 + "!Process.supportsProcesses()" + !Process.supportsProcesses() + "owningUid:"  
  29.                 + owningUid + "exported:" + exported + "permission:" + permission);  
  30.   
  31.         // If the target is not exported, then nobody else can get to it.  
  32.         if (!exported) {  
  33.             Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);  
  34.             return PackageManager.PERMISSION_DENIED;  
  35.         }  
  36.         if (permission == null) {  
  37.             return PackageManager.PERMISSION_GRANTED;  
  38.         }  
  39.         try {  
  40.             return AppGlobals.getPackageManager()  
  41.                     .checkUidPermission(permission, uid);  
  42.         } catch (RemoteException e) {  
  43.             // Should never happen, but if it does... deny!  
  44.             Slog.e(TAG, "PackageManager is dead?!?", e);  
  45.         }  
  46.         return PackageManager.PERMISSION_DENIED;  
  47.     }  
复制代码

这样我们发现在对apk拥有的是否是root等权限判断后调用了

Java代码




  1. AppGlobals.getPackageManager()  
  2.                     .checkUidPermission(permission, uid);  
复制代码

这样就调回到packagemanage里面来通过uid群找它所拥有的permission,code 如下 

Java代码




  1. public int checkUidPermission(String permName, int uid) {  
  2.   
  3.     synchronized (mPackages) {  
  4.         Object obj = mSettings.getUserIdLP(uid);  
  5.         if (obj != null) {  
  6.             GrantedPermissions gp = (GrantedPermissions)obj;  
  7.             Log.e("Dean", "PackageManagerService checkUidPermission obj != null");  
  8.             if (gp.grantedPermissions.contains(permName)) {  
  9.                 return PackageManager.PERMISSION_GRANTED;  
  10.             }  
  11.         } else {  
  12.             HashSet<String> perms = mSystemPermissions.get(uid);  
  13.             Log.e("Dean", "PackageManagerService checkUidPermission obj == null");  
  14.             if (perms != null && perms.contains(permName)) {  
  15.                 return PackageManager.PERMISSION_GRANTED;  
  16.             }  
  17.         }  
  18.     }  
  19.     Log.e("Dean", "PackageManagerService checkUidPermission");  
  20.     return PackageManager.PERMISSION_DENIED;  
  21. }  
复制代码

通过这个uid获得GrantedPermissions!这个就是他所拥有的permission列表! 
这个方法后面的部分貌似对我们的需求么用! 
我们需要得到的是apk的唯一标识包名! 
这里有两个方法 

一个用uid 获得包名 

Java代码




  1. public String[] getPackagesForUid(int uid)  
复制代码

这里得到的是一个数组 
这里之所以会得到一个数组是因为有一个属性android:sharedUserId 
多个apk可以共享一个userid!那么这会不会影响我们的结果了! 
答案是不会!当然这个答案是做过测试的!如果有android:sharedUserId那么两个apk必须有相同的证书!否则会报INSTALL_FAILED_SHARED_USER_INCOMPATIBLE 
错误!也就是说得到的数组的任何一个packagename取到的Signature应该是一样的! 
所以此方案可行! 

另一个通过pid可以知道当前的进程运行pkglist! 

Java代码


  1. List<RunningAppProcessInfo> getRunningAppProcesses = null;  
  2.         try {  
  3.             getRunningAppProcesses = ActivityManagerNative.getDefault()  
  4.                     .getRunningAppProcesses();  
  5.         } catch (Exception e) {  
  6.         }  
  7.           
  8.         for (RunningAppProcessInfo runningappprocessinfo : getRunningAppProcesses) {  
  9.             Log.e("Dean", "runningappprocessinfo.pid:"+runningappprocessinfo.pid+"runningappprocessinfo.processName"+runningappprocessinfo.processName);  
  10.               
  11.             for(int i = 0;i<runningappprocessinfo.pkgList.length;i++){  
  12.                 Log.e("Dean","pkgname:"+runningappprocessinfo.pid+":"+runningappprocessinfo.pkgList[i]);  
  13.             }  
  14.         }  
  15.         Log.e("Dean", "...................................................");  
  16.         for (RunningAppProcessInfo runningappprocessinfo : getRunningAppProcesses) {  
  17.             Log.e("Dean","runningappprocessinfo.pid:"+runningappprocessinfo.pid);  
  18.             if (runningappprocessinfo.pid == Binder.getCallingPid()) {  
  19.                 Log.e("Dean","runningappprocessinfo.pid:"+runningappprocessinfo.pid);  
  20.                 Log.e("Dean", "runningappprocessinfo" + runningappprocessinfo  
  21.                         + "runningappprocessinfo.processName:"  
  22.                         + runningappprocessinfo.processName  
  23.                         + "runningappprocessinfo.pkgList:"  
  24.                         + runningappprocessinfo.pkgList);  
  25.                 ApplicationInfo mAppInfo = null;  
  26.                 try {  
  27.                 Log.e("Dean","runningappprocessinfo.pkgList"+runningappprocessinfo.pkgList);  
  28.                   
  29.                 Log.e("Dean","runningappprocessinfo.pkgList"+runningappprocessinfo.pkgList.length);  
  30.   
  31.                 for(int i = 0;i<runningappprocessinfo.pkgList.length;i++){  
  32.                     Log.e("Dean","pkgname:"+runningappprocessinfo.pkgList[i]);  
  33.                 }  
  34.                   
  35.                 mAppInfo = getPackageManager().getApplicationInfo(runningappprocessinfo.processName,  
  36.                         PackageManager.GET_UNINSTALLED_PACKAGES);  
  37.                   
  38.                 Log.e("Dean", "mAppInfo.publicSourceDir"+mAppInfo.publicSourceDir);  
  39.                 Log.e("Dean", "mAppInfo.sourceDir"+mAppInfo.sourceDir);  
  40.                 } catch (Exception e) {  
  41.                 }  
  42.             }  
  43.         }
复制代码

分享到:
评论

相关推荐

    Android代码-HeiPermission

    Android M 动态权限解决方案,Let You Fly! []() Demo_APK下载 动图(相信你会Star的) 使用方式 导入permlib到Project中,app添加库依赖。(建议拷贝源码,可根据需求定制) 奇淫技巧: checkPermission...

    基于框架的Web开发-静态代理和动态代理原理.docx

    Java动态代理的实现 1 程序架构 创建包proxy.jdk,里面包含下面类和接口,详见批注。 类,实现了UserDao接口接口类测试类...下面要学习使用代理技术,将检查权限和记录日志两个方法自动切入addUser和deleteUser方法的开

    permission.zip

    两行代码解决 Android 6+ 动态申请权限方案 使用一工具类就能完成复杂代码编写 在Activity 中写二行代码就够了 从我的项目中移出来的 供参考 @Override protected void onCreate(@Nullable Bundle ...

    使用RxJava处理Android6.0运行时动态权限获取

    但是第三方ROM并不能提供给我们权限请求成功或失败的接口,这就导致我们无法通过PackageManager提供的checkPermission()方法来准确的获取到我们是否获得该权限。只能根据具体的权限来做相应的处理。但是在Android6.0...

    Android编程检测手机录音权限是否打开的方法

    本文实例讲述了Android编程检测...pm.checkPermission(android.permission.RECORD_AUDIO, 包名)); Boolean flag = PermissionChecker.checkSelfPermission(this, Manifest.permission.)== PermissionChecker.PERMISSI

    permissionCheck2.zip

    NULL 博文链接:https://love2java.iteye.com/blog/1128192

    Android studio 将字符串写入本地的操作方法

    File 类的操作: 1.首先需要添加相关权限: &lt;uses android:name=android.permission.WRITE_EXTERNAL_...private void checkPermission(){ if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.M) {//6.0以上 in

    CheckPermission Subscription-crx插件

    CheckPermission Subscription是面向美国亚马逊卖家的精简且安全的Chrome扩展程序。 现在使用危险品检查器! 如果您被限制销售任何实体的亚马逊产品-甚至书籍,它都会立即在屏幕(Windows / Mac)上向您显示! 当您...

    Android_M_requestPermissions:简单的Android权限请求

    requestPermissions 简单的Android权限请求支持SYSTEM_ALERT_WINDOW和WRITE_SETTINGS权限请求PermissionChecker.checkSelfPermission()检查权限GrantAndroidPermission库Gradle从获取库 repositories { maven { ...

    Android ble简单使用(初始化)

    网上已经有很多优秀的开源框架了,为了熟悉ble的整个流程还是要自己写一下的。 蓝牙权限 动态申请权限 因为这里只有一个权限需要动态申请,所以用下面的代码 //检查权限是否打开 private void checkPermission()...

    详解Android 检测权限的三种写法

    本文介绍了详解Android 检测权限的三种写法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 权限检测生效条件: targetSdkVersion 以及 compileSdkVersion 升级到 23 及以上 运行 ...

    AudioCapture.rar

    private void checkPermission() { if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.M) { String[] permissions = new String[]{Manifest.permission.RECORD_AUDIO,Manifest.permission.WRITE_EXTERNAL_STORAGE...

    HaruVideoBaseOnAli:基于阿里SDK封装的安卓播放器

    主要用于视频的控制,然后再通知Panel的改变状态,项目中是由一个FrameLayout来实现控制器的功能,初始化的时候会添加视频的View到内部。 ###权限 视频播放时的缓存,需要文件读写权限 /** * 检查权限 * 缓存需要...

    Android打开图库选择照片功能代码

    public void checkPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions...

    customcheckboxlist.ftl

    解决struts2里checkboxlist 换行 在struts核心jar包下的template里创建custom文件夹。把该文件放到custom下。替换工程里的jar文件。解决问题。 ... value="checkPermission"&gt; &lt;/td&gt;

    HTML5 Notification(桌面提醒)功能使用实例

    一、HTML5 Notification 简介HTML5 Notification ,即桌面通知。...复制代码代码如下:requestPermission 请求桌面通知checkPermission 检查桌面通知许可(PERMISSION_ALLOWED = 0, PERMISSION_NOT_ALLOWED = 1, PE

    GAEAuth0Callback:重新制作的 Auth0Callback 以与 Google App Engine 配合使用

    引起的 java.security.AccessControlException: access denied ("java.net.NetPermission" "setDefaultAuthenticator")at java.security.AccessControlContext.checkPermission(AccessControlContext.java:375)设置...

    cordova-async-contacts-plugin:**[Deprecated]** 从 iOS 地址簿异步加载联系人

    addressbook.checkPermission addressbook.getAsync window.plugins.addressbook.getAsync(function(contacts){ console.log(contacts.length); }, function(error){ console.log(error); }) 可用字段: 名 ...

    java_model_simple:java_model简单实现

    组织结构├── common -- 项目常用工具与基类包 ├── annotation -- 自定义注解 ├── ActionLog -- 操作日志注解 ├── CheckPermission -- 操作权限注解 ├── aspect -- AOP编程 ├── ActionLogAspect --...

Global site tag (gtag.js) - Google Analytics