دسترسی حسابرسی به داده ها

با انجام حسابرسی دسترسی به داده‌ها ، می‌توانید در مورد نحوه دسترسی برنامه و وابستگی‌های آن به داده‌های خصوصی کاربران، بینش‌هایی کسب کنید. این فرآیند که در دستگاه‌هایی که اندروید ۱۱ (سطح API 30) و بالاتر را اجرا می‌کنند، موجود است، به شما امکان می‌دهد دسترسی‌های داده‌ای غیرمنتظره بالقوه را بهتر شناسایی کنید. برنامه شما می‌تواند نمونه‌ای از AppOpsManager.OnOpNotedCallback را ثبت کند، که می‌تواند هر بار که یکی از رویدادهای زیر رخ می‌دهد، اقداماتی را انجام دهد:

حسابرسی دسترسی به داده‌ها در نخی که درخواست داده در آن انجام می‌شود، فراخوانی می‌شود. این بدان معناست که اگر یک SDK یا کتابخانه شخص ثالث در برنامه شما، APIای را فراخوانی کند که به داده‌های خصوصی دسترسی دارد، حسابرسی دسترسی به داده‌ها به OnOpNotedCallback شما اجازه می‌دهد اطلاعات مربوط به فراخوانی را بررسی کند. معمولاً، این شیء فراخوانی می‌تواند با بررسی وضعیت فعلی برنامه، مانند ردیابی پشته نخ فعلی، تشخیص دهد که آیا فراخوانی از برنامه شما یا SDK انجام شده است.

دسترسی به داده‌ها را ثبت کنید

برای انجام ممیزی دسترسی به داده‌ها با استفاده از یک نمونه از AppOpsManager.OnOpNotedCallback ، منطق فراخوانی را در مؤلفه‌ای که قصد دارید دسترسی به داده‌ها را ممیزی کنید، پیاده‌سازی کنید، مانند درون متد onCreate() یک فعالیت یا متد onCreate() یک برنامه.

قطعه کد زیر یک AppOpsManager.OnOpNotedCallback را برای حسابرسی دسترسی به داده‌ها در یک اکتیویتی واحد تعریف می‌کند:

کاتلین

override fun onCreate(savedInstanceState: Bundle?) {
    val appOpsCallback = object : AppOpsManager.OnOpNotedCallback() {
        private fun logPrivateDataAccess(opCode: String, trace: String) {
            Log.i(MY_APP_TAG, "Private data accessed. " +
                    "Operation: $opCode\nStack Trace:\n$trace")
        }

        override fun onNoted(syncNotedAppOp: SyncNotedAppOp) {
            logPrivateDataAccess(
                    syncNotedAppOp.op, Throwable().stackTrace.toString())
        }

        override fun onSelfNoted(syncNotedAppOp: SyncNotedAppOp) {
            logPrivateDataAccess(
                    syncNotedAppOp.op, Throwable().stackTrace.toString())
        }

        override fun onAsyncNoted(asyncNotedAppOp: AsyncNotedAppOp) {
            logPrivateDataAccess(asyncNotedAppOp.op, asyncNotedAppOp.message)
        }
    }

    val appOpsManager =
            getSystemService(AppOpsManager::class.java) as AppOpsManager
    appOpsManager.setOnOpNotedCallback(mainExecutor, appOpsCallback)
}

جاوا

@Override
public void onCreate(@Nullable Bundle savedInstanceState,
        @Nullable PersistableBundle persistentState) {
    AppOpsManager.OnOpNotedCallback appOpsCallback =
            new AppOpsManager.OnOpNotedCallback() {
        private void logPrivateDataAccess(String opCode, String trace) {
            Log.i(MY_APP_TAG, "Private data accessed. " +
                    "Operation: $opCode\nStack Trace:\n$trace");
        }

        @Override
        public void onNoted(@NonNull SyncNotedAppOp syncNotedAppOp) {
            logPrivateDataAccess(syncNotedAppOp.getOp(),
                    Arrays.toString(new Throwable().getStackTrace()));
        }

        @Override
        public void onSelfNoted(@NonNull SyncNotedAppOp syncNotedAppOp) {
            logPrivateDataAccess(syncNotedAppOp.getOp(),
                    Arrays.toString(new Throwable().getStackTrace()));
        }

        @Override
        public void onAsyncNoted(@NonNull AsyncNotedAppOp asyncNotedAppOp) {
            logPrivateDataAccess(asyncNotedAppOp.getOp(),
                    asyncNotedAppOp.getMessage());
        }
    };

    AppOpsManager appOpsManager = getSystemService(AppOpsManager.class);
    if (appOpsManager != null) {
        appOpsManager.setOnOpNotedCallback(getMainExecutor(), appOpsCallback);
    }
}

متدهای onAsyncNoted() و onSelfNoted() در موقعیت‌های خاص فراخوانی می‌شوند:

  • اگر دسترسی به داده‌ها در طول فراخوانی API برنامه شما اتفاق نیفتد، تابع onAsyncNoted() فراخوانی می‌شود. رایج‌ترین مثال زمانی است که برنامه شما یک شنونده (listener) ثبت می‌کند و دسترسی به داده‌ها هر بار که فراخوانی شنونده (listener) فراخوانی می‌شود، اتفاق می‌افتد.

    آرگومان AsyncNotedOp که به onAsyncNoted() ارسال می‌شود، حاوی متدی به نام getMessage() است. این متد اطلاعات بیشتری در مورد دسترسی به داده‌ها ارائه می‌دهد. در مورد فراخوانی‌های موقعیت مکانی، پیام حاوی system-identity-hash شنونده است.

  • onSelfNoted() در موارد بسیار نادری فراخوانی می‌شود که یک برنامه، شناسه کاربری (UID) خود را به noteOp() ارسال می‌کند.

دسترسی به داده‌های حسابرسی بر اساس برچسب انتساب

برنامه شما ممکن است چندین مورد استفاده اصلی داشته باشد، مانند اجازه دادن به کاربران برای گرفتن عکس و به اشتراک گذاری این عکس‌ها با مخاطبین خود. اگر یک برنامه چند منظوره توسعه می‌دهید، می‌توانید هنگام بررسی دسترسی به داده‌های برنامه، یک برچسب انتساب را به هر بخش از آن اعمال کنید. زمینه attributionTag در اشیاء ارسالی به فراخوانی‌های onNoted() بازگردانده می‌شود. این به شما کمک می‌کند تا دسترسی به داده‌ها را به بخش‌های منطقی کد خود راحت‌تر ردیابی کنید.

برای تعریف تگ‌های انتساب در برنامه خود، مراحل بخش‌های زیر را دنبال کنید.

تگ‌های انتساب را در مانیفست اعلام کنید

اگر برنامه شما اندروید ۱۲ (سطح API 31) یا بالاتر را هدف قرار می‌دهد، باید تگ‌های انتساب را در فایل مانیفست برنامه خود، با استفاده از فرمت نشان داده شده در قطعه کد زیر، اعلام کنید. اگر سعی کنید از یک تگ انتساب که در فایل مانیفست برنامه خود اعلام نکرده‌اید استفاده کنید، سیستم یک تگ null برای شما ایجاد می‌کند و پیامی را در Logcat ثبت می‌کند.

<manifest ...>
    <!-- The value of "android:tag" must be a literal string, and the
         value of "android:label" must be a resource. The value of
         "android:label" is user-readable. -->
    <attribution android:tag="sharePhotos"
                 android:label="@string/share_photos_attribution_label" />
    ...
</manifest>

ایجاد برچسب‌های انتساب

در متد onCreate() مربوط به activity که در آن به داده‌ها دسترسی دارید، مانند activity که در آن درخواست موقعیت مکانی می‌کنید یا به لیست مخاطبین کاربر دسترسی پیدا می‌کنید، createAttributionContext() را فراخوانی کنید و تگ attribution مورد نظر خود را که می‌خواهید با بخشی از برنامه خود مرتبط کنید، وارد کنید.

قطعه کد زیر نحوه ایجاد یک تگ انتساب برای بخش اشتراک‌گذاری موقعیت مکانی عکس در یک برنامه را نشان می‌دهد:

کاتلین

class SharePhotoLocationActivity : AppCompatActivity() {
    lateinit var attributionContext: Context

    override fun onCreate(savedInstanceState: Bundle?) {
        attributionContext = createAttributionContext("sharePhotos")
    }

    fun getLocation() {
        val locationManager = attributionContext.getSystemService(
                LocationManager::class.java) as LocationManager
        // Use "locationManager" to access device location information.
    }
}

جاوا

public class SharePhotoLocationActivity extends AppCompatActivity {
    private Context attributionContext;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState,
            @Nullable PersistableBundle persistentState) {
        attributionContext = createAttributionContext("sharePhotos");
    }

    public void getLocation() {
        LocationManager locationManager =
                attributionContext.getSystemService(LocationManager.class);
        if (locationManager != null) {
            // Use "locationManager" to access device location information.
        }
    }
}

برچسب‌های انتساب را در گزارش‌های دسترسی وارد کنید

تابع فراخوانی AppOpsManager.OnOpNotedCallback خود را به‌روزرسانی کنید تا گزارش‌های برنامه شما شامل نام تگ‌های انتسابی تعریف‌شده توسط شما باشند.

قطعه کد زیر منطق به‌روز شده‌ای را نشان می‌دهد که تگ‌های انتساب را ثبت می‌کند:

کاتلین

val appOpsCallback = object : AppOpsManager.OnOpNotedCallback() {
    private fun logPrivateDataAccess(
            opCode: String, attributionTag: String, trace: String) {
        Log.i(MY_APP_TAG, "Private data accessed. " +
                    "Operation: $opCode\n " +
                    "Attribution Tag:$attributionTag\nStack Trace:\n$trace")
    }

    override fun onNoted(syncNotedAppOp: SyncNotedAppOp) {
        logPrivateDataAccess(syncNotedAppOp.op,
                syncNotedAppOp.attributionTag,
                Throwable().stackTrace.toString())
    }

    override fun onSelfNoted(syncNotedAppOp: SyncNotedAppOp) {
        logPrivateDataAccess(syncNotedAppOp.op,
                syncNotedAppOp.attributionTag,
                Throwable().stackTrace.toString())
    }

    override fun onAsyncNoted(asyncNotedAppOp: AsyncNotedAppOp) {
        logPrivateDataAccess(asyncNotedAppOp.op,
                asyncNotedAppOp.attributionTag,
                asyncNotedAppOp.message)
    }
}

جاوا

@Override
public void onCreate(@Nullable Bundle savedInstanceState,
        @Nullable PersistableBundle persistentState) {
    AppOpsManager.OnOpNotedCallback appOpsCallback =
            new AppOpsManager.OnOpNotedCallback() {
        private void logPrivateDataAccess(String opCode,
                String attributionTag, String trace) {
            Log.i("MY_APP_TAG", "Private data accessed. " +
                    "Operation: $opCode\n " +
                    "Attribution Tag:$attributionTag\nStack Trace:\n$trace");
        }

        @Override
        public void onNoted(@NonNull SyncNotedAppOp syncNotedAppOp) {
            logPrivateDataAccess(syncNotedAppOp.getOp(),
                    syncNotedAppOp.getAttributionTag(),
                    Arrays.toString(new Throwable().getStackTrace()));
        }

        @Override
        public void onSelfNoted(@NonNull SyncNotedAppOp syncNotedAppOp) {
            logPrivateDataAccess(syncNotedAppOp.getOp(),
                    syncNotedAppOp.getAttributionTag(),
                    Arrays.toString(new Throwable().getStackTrace()));
        }

        @Override
        public void onAsyncNoted(@NonNull AsyncNotedAppOp asyncNotedAppOp) {
            logPrivateDataAccess(asyncNotedAppOp.getOp(),
                    asyncNotedAppOp.getAttributionTag(),
                    asyncNotedAppOp.getMessage());
        }
    };

    AppOpsManager appOpsManager = getSystemService(AppOpsManager.class);
    if (appOpsManager != null) {
        appOpsManager.setNotedAppOpsCollector(appOpsCollector);
    }
}