sWhitelists.add("org.jssec.android.provider.partneruser", isdebug ?
// Сертификат хэш-значения "androiddebugkey" в debug.keystore.
"0EFB7236 328348A9 89718BAD DF57F544 D5CCB4AE B9DB34BC 1E29DD26 F77C8255" :
// Сертификат хэш-значение "партнёрского ключа" в хранилище ключей.
"1F039BB5 7861C27A 3916C778 8E78CE00 690B3974 3EB8259F E2627B8D 4C0EC35A");
// Зарегистрировать другие партнёрские приложения таким же образом.
}
private static boolean checkPartner(Context context, String pkgname) {
if (sWhitelists == null) buildWhitelists(context);
return sWhitelists.test(context, pkgname);
}
// Получить имя пакета вызывающего приложения.
private String getCallingPackage(Context context) {
String pkgname;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
pkgname = super.getCallingPackage();
} else {
pkgname = null;
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List procList = am.getRunningAppProcesses();
int callingPid = Binder.getCallingPid();
if (procList != null) {
for (RunningAppProcessInfo proc : procList) {
if (proc.pid == callingPid) {
pkgname = proc.pkgList[proc.pkgList.length - 1];
break;
}
}
}
}
return pkgname;
}
@Override
public boolean onCreate() {
return true;
}
@Override
public String getType(Uri uri) {
switch (sUriMatcher.match(uri)) {
case DOWNLOADS_CODE:
case ADDRESSES_CODE:
return CONTENT_TYPE;
case DOWNLOADS_ID_CODE:
case ADDRESSES_ID_CODE:
return CONTENT_ITEM_TYPE;
default:
throw new IllegalArgumentException("Invalid URI:" + uri);
}
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// *** POINT 2 *** Убедитесь, что сертификат запрашивающего приложения зарегистрирован в собственном белом списке.
if (!checkPartner(getContext(), getCallingPackage(getContext()))) {
throw new SecurityException("Вызывающее приложение не является партнёрским приложением.");
}
// *** POINT 3 *** Обработайте полученные данные запроса осторожно и безопасно,
// даже если данные поступают от партнёрского приложения.
// Здесь, является ли uri ожидаемым или нет, проверяется с помощью UriMatcher#match() и switch case.
// Проверка других параметров здесь опущена из-за примера.
// См. «3.2 Обрабатывайте входные данные осторожно и безопасно».
// *** POINT 4 *** Информация, которая предоставляется для раскрытия партнёрским приложениям, может быть возвращена.
// Это зависит от приложения, можно ли раскрыть результат запроса или нет.
switch (sUriMatcher.match(uri)) {
case DOWNLOADS_CODE:
case DOWNLOADS_ID_CODE:
return sDownloadCursor;
case ADDRESSES_CODE:
case ADDRESSES_ID_CODE:
return sAddressCursor;
default:
throw new IllegalArgumentException("Неверный URI:" + uri);
}
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// *** POINT 2 *** Убедитесь, что сертификат запрашивающего приложения зарегистрирован в собственном белом списке.
if (!checkPartner(getContext(), getCallingPackage(getContext()))) {
throw new SecurityException("Вызывающее приложение не является партнёрским приложением.");
}
// *** POINT 3 *** Обработайте полученные данные запроса осторожно и безопасно,
// даже если данные поступают от партнёрского приложения.
// Здесь, является ли uri ожидаемым или нет, проверяется с помощью UriMatcher#match() и switch case
// Здесь опущены проверки для других параметров из-за примера.
// См. «3.2 Осторожно и безопасно обрабатывайте входные данные».
// *** Пункт 4*** Можно вернуть информацию, которую разрешено раскрывать партнёрским приложениям.
// Это зависит от приложения, имеет ли выданный ID чувствительное значение или нет.
switch (sUriMatcher.match(uri)) {
case DOWNLOADS_CODE:
return ContentUris.withAppendedId(Download.CONTENT_URI, 3);
case ADDRESSES_CODE:
return ContentUris.withAppendedId(Address.CONTENT_URI, 4);
default:
throw new IllegalArgumentException("Invalid URI:" + uri);
}
}
Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
// *** Пункт 2*** Проверьте, зарегистрирован ли сертификат запрашивающего приложения в собственном белом списке.
if (!checkPartner(getContext(), getCallingPackage(getContext()))) {
throw new SecurityException("Calling application is not a partner application.");
}
// *** Пункт 3*** Обрабатывайте полученные данные запроса осторожно и безопасно,
// даже если данные поступают от партнёрского приложения.
// Здесь проверяется, соответствует ли uri ожиданиям, с помощью UriMatcher#match() и switch case.
// Опущены проверки для других параметров из-за примера.
// См. «3.2 Осторожно и безопасно обрабатывайте входные данные».
// *** Пункт 4*** Можно вернуть информацию, которая разрешена к раскрытию партнёрским приложениям.
// Зависит от приложения, имеет ли количество обновлённых записей чувствительное значение или нет.
switch (sUriMatcher.match(uri)) {
case DOWNLOADS_CODE:
return 5; // Возвращаем количество обновлённых записей
case DOWNLOADS_ID_CODE:
return 1;
case ADDRESSES_CODE:
return 15;
case ADDRESSES_ID_CODE:
return 1;
default:
throw new IllegalArgumentException("Invalid URI:" + uri);
}
Override public int delete(Uri uri, String selection, String[] selectionArgs)
// *** Пункт 2*** Проверьте, зарегистрирован ли сертификат запрашивающего приложения в собственном белом списке.
if (!checkPartner(getContext(), getCallingPackage(getContext()))) {
throw new SecurityException("Calling application is not a partner application.");
}
// *** Пункт 3*** Обрабатывайте полученные данные запроса осторожно и безопасно,
// даже если данные поступают от партнёрского приложения.
// Здесь проверяется, соответствует ли uri ожиданиям, с помощью UriMatcher#match() и switch case.
// Опущены проверки для других параметров из-за примера.
// См. «3.2 Осторожно и безопасно обрабатывайте входные данные».
// *** Пункт 4*** Можно раскрыть информацию, которая предоставлена партнёрским приложениям.
// Зависит от приложения, имеет ли количество удалённых записей чувствительное значение или нет.
switch (sUriMatcher.match(uri)) {
case DOWNLOADS_CODE:
return 10; // Возвращаем количество удалённых записей
case DOWNLOADS_ID_CODE:
return 1;
case ADDRESSES_CODE:
return 20;
case ADDRESSES_ID_CODE:
return 1;
default:
throw new IllegalArgumentException("Invalid URI:" + uri);
}
Пример использования контент-провайдера для партнёров
Ключевые моменты (использование контент-провайдера):
// Информация о целевом поставщике контента private static final String AUTHORITY = "org.jssec.android.provider.partnerprovider";
private interface Address { public static final String PATH = "addresses"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + PATH); }
// *** ТОЧКА 4 *** Проверьте, зарегистрирован ли сертификат целевого приложения в собственном белом списке. private static PkgCertWhitelists sWhitelists = null;
private static void buildWhitelists(Context context) { boolean isdebug = Utils.isDebuggable(context); sWhitelists = new PkgCertWhitelists(); // Зарегистрируйте значение хеш-функции сертификата партнёрского приложения org.jssec.android.provider.partnerprovider. sWhitelists.add("org.jssec.android.provider.partnerprovider", isdebug ? // Значение хеш-функции сертификата "androiddebugkey" в debug.keystore. "0EFB7236 328348A9 89718BAD DF57F544 D5CCB4AE B9DB34BC 1E29DD26 F77C8255" : // Значение хеш-функции сертификата "партнёрский ключ" в keystore. "D397D343 A5CBC10F 4EDDEB7C A10062DE 5690984F 1FB9E88B D7B3A7C2 42E142CA"); // Аналогичным образом зарегистрируйте другие партнёрские приложения. }
private static boolean checkPartner(Context context, String pkgname) { if (sWhitelists == null) buildWhitelists(context); return sWhitelists.test(context, pkgname); }
// Получите имя пакета целевого поставщика контента. private String providerPkgname(Uri uri) { String pkgname = null; ProviderInfo pi = getPackageManager().resolveContentProvider(uri.getAuthority(), 0); if (pi != null) pkgname = pi.packageName; return pkgname; }
public void onQueryClick(View view) { logLine("[Query]"); // *** ТОЧКА 4 *** Убедитесь, что сертификат целевого приложения зарегистрирован в собственном белом списке. if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) { logLine(" Целевой поставщик контента не обслуживается партнёрскими приложениями."); return; } Cursor cursor = null; try { // *** ТОЧКА 5 *** Можно отправить информацию, которая разрешена к раскрытию партнёрским приложениям. cursor = getContentResolver().query(Address.CONTENT_URI, null, null, null, null); // *** ТОЧКА 6 *** Обработайте полученные данные результата осторожно и безопасно, // даже если данные поступают от партнёрского приложения. // Опущено, поскольку это пример. Пожалуйста, обратитесь к разделу «3.2 Обработка входных данных осторожно и безопасно». if (cursor == null) { logLine(" нулевой курсор"); } else { boolean moved = cursor.moveToFirst(); while (moved) { logLine(String.format(" %d, %s", cursor.getInt(0), cursor.getString(1))); moved = cursor.moveToNext(); } } } finally { if (cursor != null) cursor.close(); } }
public void onInsertClick(View view) { logLine("[Insert]"); // *** ТОЧКА 4 *** Убедитесь, что сертификат целевого приложения зарегистрирован в собственном белом списке. if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) { logLine(" Целевой поставщик контента не обслуживается партнёрскими приложениями."); return; } // *** ТОЧКА 5 *** Информацию, которую разрешено раскрывать партнёрским приложениям, можно отправить. ContentValues values = new ContentValues(); values.put("city", "Tokyo"); Uri uri = getContentResolver().insert(Address.CONTENT_URI, values); // *** ТОЧКА 6 *** Обработайте полученный результат данных. Перевод текста на русский язык:
carefully and securely, // даже если данные поступают от партнёрского приложения. // Опущено, см. «3.2 Тщательная и безопасная обработка входных данных». logLine(" uri:" + uri); }
public void onUpdateClick(View view) { logLine("[Update]"); // *** ТОЧКА 4 *** Убедитесь, что сертификат целевого приложения зарегистрирован в собственном белом списке. if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) { logLine(" Целевой поставщик контента не обслуживается партнёрскими приложениями."); return; } // *** ТОЧКА 5 *** Можно отправить информацию, которая разрешена к раскрытию партнёрским приложениям. ContentValues values = new ContentValues(); values.put("city", "Tokyo"); String where = "_id = ?"; String[] args = { "4" }; int count = getContentResolver().update(Address.CONTENT_URI, values, where, args); // *** ТОЧКА 6 *** Обработайте полученные данные тщательно и безопасно, // даже если они поступают от партнёрского приложения. // Опущено, см. «3.2 Тщательная и безопасная обработка входных данных». logLine(String.format(" %s записей обновлено", count)); }
public void onDeleteClick(View view) { logLine("[Delete]"); // *** ТОЧКА 4 *** Убедитесь, что сертификат целевого приложения зарегистрирован в собственном белом списке. if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) { logLine(" Целевой поставщик контента не обслуживается партнёрскими приложениями."); return; } // *** ТОЧКА 5 *** Можно отправить информацию, которая разрешена к раскрытию партнёрским приложениям. int count = getContentResolver().delete(Address.CONTENT_URI, null, null); // *** ТОЧКА 6 *** Обработайте полученные данные тщательно и безопасно, // даже если они поступают от партнёрского приложения. // Опущено, см. «3.2 Тщательная и безопасная обработка входных данных». logLine(String.format(" %s записей удалено", count)); }
private TextView mLogView;
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mLogView = (TextView)findViewById(R.org.jssec.android.shared.R.id.logview); }
private void logLine(String line) { mLogView.append(line); mLogView.append("¥n"); }
**PkgCertWhitelists.java**
package org.jssec.android.shared;
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
public class PkgCertWhitelists {
private Map<String, String> mWhitelists = new HashMap<String, String>();
public boolean add(String pkgname, String sha256) {
if (pkgname == null) return false;
if (sha256 == null) return false;
sha256 = sha256.replaceAll(" ", "");
if (sha256.length() != 64) return false; // SHA-256 -> 32 bytes -> 64 chars
sha256 = sha256.toUpperCase();
if (sha256.replaceAll("[0-9A-F]+", "").length() != 0) return false; // found non hex char
mWhitelists.put(pkgname, sha256);
return true;
}
public boolean test(Context ctx, String pkgname) {
// Получить правильное значение хеш-функции, соответствующее pkgname.
String correctHash = mWhitelists.get(pkgname);
// Сравнить фактическое значение хеш-функции pkgname с правильным значением хеш-функции.
return PkgCert.test(ctx, pkgname, correctHash);
}
}
**PkgCert.java**
package org.jssec.android.shared;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
public class PkgCert {
public static boolean test(Context ctx, String)
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )