Поширення iOS додатків по посиланню в корпоративному середовищі, використовуючи стек технологій Microsoft



Нещодавно стало відомо про купівлю Xamarin компанією Microsoft. Дана новина не залишилася непоміченою серед спільноти розробників, а також, серед корпоративних клієнтів. У зв'язку з цим, стають більш актуальними історії, де в Microsoft Full Stack оточення необхідно інтегрувати мобільні рішення, не приводячи при цьому до необхідності драматичного розширення набору компетенції IT-отелення, або компанії в цілому. Для таких сценаріїв стає лаконічним вибір Xamarin, як компонента, добре вписується в пазл, що складається з SharePoint, ASP.NET MVC, WebAPI services і Microsoft.
В рамках даної статті описується метод розповсюдження мобільного додатка всередині компанії, переважно на етапі прототипування, використовуючи перерахований стек технологій Microsoft.
Описуваний в статті метод, незважаючи на ухил .NET оточення, застосуємо до iOS-додатків, написаних за допомогою будь-якого іншого інструменту розробки, будь то Apache Cordova або класичний натів.


Введення



У своїй попередній статті я розглядав спосіб поширення корпоративних iOS-додатків через MDM-рішення на прикладі OS X Server. У цій статті мова піде про метод розповсюдження програм за посиланням, використовуючи в арсеналі стек технологій Microsoft.

Чому у статті робиться акцент на інструменти Microsoft? Відповідь лежить на поверхні. Якщо компанія велика, то, швидше за все, ми маємо справу з SharePoint, а значить, і співробітників, що мають досвід розробки .NET. Однак, все теж саме можна зробити і на інших технологіях, наприклад, PHP.

Як правило, метод розповсюдження за посиланням выбрают у випадках, коли кількість користувачів дуже обмежено і їм не потрібно автоматичне оновлення програми, або, на час розробки прототипу, коли є група тестувальників або кураторів проекту всередині компанії.

Примітка
Microsoft також має MDM-рішення, побудоване на базі System Center Configuration Manager і Windows Intune. Ви можете отримати про них більш детальну інформацію, перейшовши за посиланнями раз, два і три.

Постановка завдання



Давате визначимося з завданнями, які перед нами ставлять, і ресурами, наявними у нас, для їх виконання:

  • Додаток має поширюватися просто файл, доступний для установки;
  • Рішення повинне бути реалізоване без використання сторонніх спеціалізованих сервісів;
  • Для створення програми використовується стандартний обліковий запис розробника Apple Developer Program;
Перерахуємо мінуси, які потрібно враховувати перед початком використання обраного нами методу:

  • Для повідомлення користувачів про нової версії додатка, швидше за все, буде використовуватися електронна пошта;
  • У нас немає інструменту для автоматичного оновлення додатків, у разі, якщо буде виявлена критична помилка, або, проблема безпеки;
  • Ви обмежені, грубо, 100 користувачами;
  • При кожному додаванні нового користувача вам доведеться вручну виконувати ряд дій і перезбирати додаток;
Коротка послідовність дій при додаванні нових користувачів iOS-пристроїв) виглядає наступним чином:

  • Отримати UDID пристрою, який потрібно додати;
  • Додати UDID пристрою в консоль розробника на сайті Apple;
  • Додати пристрій у профіль розповсюдження (Provisioning Profile) потрібного додатка;
  • Перезібрати додаток із зміненим Provisioning Profile;
  • Викласти нову версію програми на веб-ресурсі;
Отримання UDID пристрою можливо за допомогою iTunes або Apple Configurator 2. Однак, природним бажанням є автоматизація цього процесу. Це можливо за допомогою профілів (iOS Сonfiguration Profile), які являють собою файли з розширенням *.mobileconfig, і мають XML-структури.
Якщо коротко, то це працює таким чином: у файлі *.mobileconfig ви вказуєте параметри, які хочете отримати у iOS-пристрої (у нашому випадку UDID), і зворотний URL, куди iOS-пристрій надішле відповідь XML-файл з заповненими полями.

Забезпечення можливості скачування і установки програми по прямой ссылке також має ряд особливостей, які ми розглянемо в цій статті. Одна з них — необхідність використання HTTPS.

Концептуальна схема та планування робіт



Щоб ви змогли оцінити обсяг дій при використанні даного методу я підготував дві схеми.

Поширення програми по посиланню з використанням облікового запису Apple Developer Program

Поширення програми по посиланню з використанням облікового запису Apple Enterprise Developer Program


Як бачите, використання стандартної облікового запису Apple Developer Program тягне за собою багато накладних витрат. Тим не менш, ми розглянемо саме цей варіант, як найбільш складний.

Я розбив свою розповідь на три секції, щоб було зручно сприймати інформацію в потрібній послідовності. Будемо називати їх «кроками». Отже, давайте коротко розглянемо, що нам належить зробити.

Крок 1: Отримання UDID в iOS-пристрої користувача:

  • Сформувати профіль *.mobileconfig, із зазначенням необхідних полів;
  • Викласти на веб-сервісі профіль *.mobileconfig, доступний для скачування;
  • Користувач: викачує профіль, розміщеного на html-сторінці через Safari на iPhone;
  • Користувач: встановлює профіль, після чого бачить html-сторінку «Спасибі!»;
  • На сервері зберігаються UDID користувача, після чого адміністратор вручну додає цей UDID в записі iOS-розробника;
Крок 2: Установка програми через посилання:

  • Експортувати *.ipa -пакет програми в XCode і підготувати картинки;
  • При експорті пакету вказати шлях до нього на сервері;
  • Викласти на сервері: manifest.plist, myApp.ipa, image.57x57.png, image.512x512.jpg — наприклад, в одній папці app-files;
  • Дозволити на сервері скачування файлів: .jpg .png .plist .ipa;
  • На html-сторінці дати спец-посилання на manifest.plist, формату itms-services://?action=download-manifest;
  • Веб-ресурс повинен бути доступний через https з валідним SSL сертифікатом;
  • Користувач переходить по спец-ссылке і встановлює програму;
Крок 3: Розгортання в корпоративному середовищі на базі Windows Server 2012 (містить зміни до Кроку 2, якщо вам недоступні зовнішні майданчики з валідними SSL-сертифікатами):

  • Установка і настройка DNS-сервера;
  • Встановлення та налаштування IIS;
  • Створення та встановлення SSL-сертифікатів;
  • Настройка і складання сайтів для розповсюдження;


Примітка
Я зумисне наводжу докладний опис всіх етапів і проміжних дій, щоб у людей, навіть з поверхневими знаннями в даній області, не виникло труднощів у налагодженні описуваного рішення. Тому, прошу бути поблажливими. Стаття позначена як «навчальний матеріал». Спасибі.

Крок 1: Отримання UDID в iOS-пристрої користувача



Для отримання UDID в iOS-пристрої ми будемо використовувати ASP.NET WebAPI 2. Це зручне рішення, яке відразу забезпечить нам:

  • Діалог з користувачем через MVC-контролери;
  • Отримання і обробку XML-файлу від iOS-пристрої через API-контролер;
  • Зберігання файлів профілю і бази даних зареєстрованих UDID;
Створення проекту WebAPI


В якості майданчика Кроці 1 і 2 я буду використовувати Microsoft Azure. За замовчуванням, для сайтів *.azurewebsites.net надається валідний SSL-сертифікат, який знадобиться нам на Кроці 2. Звичайно, для корпоративного використання, вам також треба передбачити, як мінімум, найпростішу авторизацію. Однак, це сильно виходить за рамки даної статті.

Сформуємо файл *.mobileconfig і покладемо його в директорію WebAPI-проекту «Downloads/corp-apps.mobileconfig»
Вміст файлу *.mobileconfig
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<dict>
<key>URL</key>
<string>http://iphone-udid.azurewebsites.net/api/xml</string>
<key>DeviceAttributes</key>
<array>
<string>UDID</string>
<string>IMEI</string>
<string>ICCID</string>
<string>VERSION</string>
<string>PRODUCT</string>
</array>
</dict>
<key>PayloadOrganization</key>
<string>Corp Apps</string>
<key>PayloadDisplayName</key>
<string>CorpApps</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadUUID</key>
<string>B43A078F-E0E2-4F52-B1E6-C03AD7032EDF</string>
<key>PayloadIdentifier</key>
<string>com.CorpApps.profile-service</string>
<key>PayloadDescription</key>
<string>This temporary profile will be used to find and display your current device's UDID.</string>
<key>PayloadType</key>
<string>Profile Service</string>
</dict>
</plist>



В даному файлі заслуговують на увагу два поля:

URL — це адреса нашого API-контролера, який буде обробляти XML-файл, відправлений від iOS-пристрої;
У моєму випадку, я вкажу посилання на сайт, розміщений у Azure, де /api/xml — POST-метод WebAPI контролера:
iphone-udid.azurewebsites.net/api/xml
PayloadUUID — найпростіше описати це поле, як унікальний GUID, який не повинен повторюватися в рамках одного iOS-пристрої.
Унікальний UUID (PayloadUUID) можна згенерувати на OS X за допомогою утиліти «uuidgen»:

Використання утиліти uuidgen
os-x-server:~ zanael$ uuidgen --
generate a universally unique identifier
usage: uuidgen [-hdr]
-hdr emit result in form suitable for coping into a header
os-x-server:~ zanael$ uuidgen
B43A078F-E0E2-4F52-B1E6-C03AD7032EDF
os-x-server:~ zanael$


Результат виконання утиліти uuidgen


Створимо XML-файл, в якому будемо зберігати зареєстровані UDID. Назвемо його udids.xml і покладемо його в директорію WebAPI-проекту «App_Data/udids.xml».
Стуктура XML-файлу для зберігання зареєстрованих UDID
<?xml version="1.0" encoding="utf-8"?>
<udids>
<iPhone>
<TimeAdded></TimeAdded>
<UDID></UDID>
</iPhone>
</udids>



Додамо в Web.config дозвіл для скачування файлів-профілів.
Необхідні зміни в Web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<staticContent>
<mimeMap fileExtension=".mobileconfig" mimeType="application/x-apple-aspen-config" />
</staticContent>
</system.webServer>
</configuration>



Додамо модель для зберігання інформації про зареєстрованих UDID в папку Models.
Файл iPhoneUDID.cs
namespace iPhoneUDID.Models
{
public class iPhoneUDID
{
public string TimeAdded { get; set; }
public string UDID { get; set; }
}
}



Створимо HomeController (MVC-контролер) в папці Controllers і додамо в нього метод для відображення списку зареєстрованих UDID з XML.
Файл HomeController.cs
using System;
using System.Collections.Generic;
using System.Web.Mvc;
using System.Xml.Linq;

namespace iPhoneUDID.Controllers
{
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
ViewBag.Title = "Home Page";

XDocument databaseXML;
try
{
databaseXML = XDocument.Load(System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/udids.xml"));
}
catch (Exception exp)
{
databaseXML = new XDocument(new XElement("udids"));
}

List<Models.iPhoneUDID> UDIDs = new List<Models.iPhoneUDID>();
XElement iPhones = databaseXML.Element("udids");
foreach (XElement e in iPhones.Elements("iPhone"))
{
UDIDs.Add(new Models.iPhoneUDID { TimeAdded = e.Element("TimeAdded").Value, UDID = e.Element("UDID").Value });
}
ViewBag.UDIDs = UDIDs;

return View();
}
}
}



Додамо View (Index.cshtml) для HomeController, який буде вітати користувача і просити зареєструвати свій UDID.
При натисканні на кнопку Take UDID користувач завантажить профіль, iOS-пристрій зрозуміє параметри, які нам потрібні і відправить їх по URL, який ми вказали в *.mobileconfig файлі у форматі XML.
Файл /Views/Home/Index.cshtml
<div class="jumbotron">
<h1>Get your UDID</h1>
<p class="lead">Please, reach this page in Mobile Safari from your iPhone.</p>
<p><a href="/downloads/corp-apps.mobileconfig" class="btn btn-primary btn-lg">Take UDID</a></p>
</div>
<div class="row">
<p>
@{
foreach (iPhoneUDID.Models.iPhoneUDID item in ViewBag.UDIDs)
{
<h5>TimeAdded: @item.TimeAdded, UDID: @item.UDID</h5>
}
}
</p>
</div>
<div class="row">
@Html.ActionLink("Clear UDIDs list", "ClearHistory", "Home", null, new { @class = "btn btn-primary btn-large" })
</div>



Створимо XmlController (WebApi2-контролер) в папці Controllers, який буде ловити XML-файл від iOS-пристрої, і зберігати отриманий з нього UDID в локальний XML.
Так як ми використовуємо Windows-машину, то друга частина файлу в інший кодуванні. Це можна виправити, використовуючи бібліотеки конвертування *.plist. Їх можна знайти на GitHub, але, так як нам потрібен лише UDID, ми можемо взяти його елементарно із заданої позиції в рядку. Це дозволить нам не тягнути зайві залежності.
Файл XmlController.cs
using System;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Xml.Linq;

namespace iPhoneUDID.Controllers
{
public class XmlController : ApiController
{
[HttpPost]
public HttpResponseMessage PostRawXMLMessage(HttpRequestMessage request)
{
string plist = request.Content.ReadAsStringAsync().Result;
int begin = plist.IndexOf("UDID") + 20;
int end = plist.IndexOf("<", begin);
string UDID = plist.Substring(begin, end begin);

XDocument databaseXML;
try
{
databaseXML = XDocument.Load(System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/udids.xml"));
}
catch (Exception exp)
{
databaseXML = new XDocument(new XElement("udids"));
}

databaseXML.Element("udids").Add(
new XElement("iPhone",
new XElement("TimeAdded", DateTime.Now.ToLongTimeString() + " - " + DateTime.Now.ToShortDateString()),
new XElement("UDID", UDID)));
databaseXML.Save(System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/udids.xml"));

HttpResponseMessage response = request.CreateResponse(HttpStatusCode.MovedPermanently);
response.Headers.Add("Location", "/Thanks");
return response;
}
}
}



Створимо ThanksController (MVC-контролер), на який буде перенаправлятися користувач після отримання його UDID.
Файл ThanksController.cs
using System.Web.Mvc;

namespace iPhoneUDID.Controllers
{
public class ThanksController : Controller
{
[HttpGet]
public ActionResult Index()
{
ViewBag.Title = "Thanks Page";

return View();
}
}
}



Додамо View (Index.cshtml) для ThanksController.
Файл /Views/Thanks/Index.cshtml
<div class="jumbotron">
<h1>Thanks for Відвідують!</h1>
</div>



Для локального очищення XML з отриманими UDID, додамо в HomeController (MVC-контролер) метод ClearHistory.
Файл HomeController.cs
[HttpGet]
public ActionResult ClearHistory()
{
ViewBag.Title = "Home Page";

XDocument databaseXML = new XDocument(new XElement("udids"));
databaseXML.Save(Server.MapPath("/App_Data/udids.xml"));

ViewBag.UDIDs = new List<Models.iPhoneUDID>();

return View("Index");
}



Так виглядає загальний Layout (_Layout.cshtml) — стандартний для шаблону.
Файл _Layout.cshtml
<!DOCTYPE html>
<html>
<head>
< meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
< meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("Ім'я програми", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>@Html.ActionLink("Домашня сторінка", "Index", "Home", new { area = "" }, null)</li>
<li>@Html.ActionLink("API", "Index", "Help", new { area = "" }, null)</li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© @DateTime.Now.Year – додаток ASP.NET</p>
</footer>
</div>

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
</html>



Тепер, все що потрібно користувачеві, це зайти на сайт і натиснути пару кнопок.
Дії



Якщо натиснути Більш докладно








Після цього побачимо на сайті його UDID.
Список зареєстрованих UDID


Нарешті, у нас в руках є UDID в iOS-пристрої, що нам потрібно зареєструвати в нашій облікового запису розробника.
Перейдемо на сайт Apple для розробників в розділ Member Center.
Докладніше







Додамо UDID в iOS пристрою.
Докладніше



Якщо ви ще не створили App ID, зробіть це.
Докладніше



Створіть профіль розповсюдження (Provisioning Profile) для вашої програми.
Докладніше













Тепер в будь-який момент ви можете додати пристрою до цього профілю поширення.






Крок 2: Установка програми через посилання



Після того, як ми отримали UDID в iOS-пристрої, додали його до облікового запису розробника і внесли зміни до Provisioning Profile, нам необхідно надати користувачу веб-ресурс, на якому будуть розміщені файли, необхідні для встановлення програми. В якості такого ресурсу я буду використовувати Microsoft Azure, який надає для сайтів *.azurewebsites.net валідний SSL-сертифікат. В якості імені сайту я виберу: corp-apps.azurewebsites.net
Примітка
Установка програми з посиланням буде працювати тільки в разі, якщо ви будете використовувати HTTPS з валідним SSL сертифікатом.

В якості проекту для створення веб-сайту можна вибрати найпростіший шаблон, без будь-яких контролерів. Все що нам потрібно — це HTML-сторінка і можливість скачування декількох додаткових файлів.
Докладніше


Тепер можемо розпочати підготовку необхідних файлів. Для цього експортуємо пакет програми через XCode.
Докладніше














Заповнимо інформацію, необхідну для розповсюдження програми. Зверніть увагу на розширення файлів.

Докладніше


Після завершення експорту в цільовій папці ви побачите маніфест manifest.plist, в якому прописані шляху до необхідних ресурсів, а також картинок необхідного формату і розміру.
Вміст файлу manifest.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>items</key>
<array>
<dict>
<key>assets</key>
<array>
<dict>
<key>kind</key>
<string>software-package</string>
<key>url</key>
<string>https://corp-apps.azurewebsites.net/app-files/myApp.ipa</string>
</dict>
<dict>
<key>kind</key>
<string>display-image</string>
<key>url</key>
<string>https://corp-apps.azurewebsites.net/app-files/image.57x57.png</string>
</dict>
<dict>
<key>kind</key>
<string>full-size-image</string>
<key>url</key>
<string>https://corp-apps.azurewebsites.net/app-files/image.512x512.jpg</string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>com.habr.hellohabr001</string>
<key>bundle-version</key>
<string>0.0.1</string>
<key>kind</key>
<string>software</string>
<key>title</key>
<string>myApp</string>
</dict>
</dict>
</array>
</dict>
</plist>



Тепер, нам необхідно дозволити завантаження файлів зазначених типів з сервера. Це можна зробити, внісши зміни в файл Web.config.
Необхідні зміни у файлі Web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<staticContent>
<mimeMap fileExtension=".jpg" mimeType="image/jpg" />
<mimeMap fileExtension=".png" mimeType="image/png" />
<mimeMap fileExtension=".plist" mimeType="text/plain" />
<mimeMap fileExtension=".ipa" mimeType="application/octet-stream" />
</staticContent>
</system.webServer>
</configuration>



І, нарешті, додамо для користувачів html-сторінку зі спец-посиланням на скачування програми.
Файл index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
< meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Встановлення програми</title>
<link rel="stylesheet" href="dist/bootstrap.min.css">
</head>
<body>
<div class="container">
<br><br>
<h1 class="text-center">Hello Apache Cordova</h1>
<p class="text-center">
<a href="itms-services://?action=download-manifest&url=https://corp-apps.azurewebsites.net/app-files/manifest.plist" class="btn btn-info" type="button">Install App</a>
</p>
<br><br>
</div>
</body>
</html>



Відмінно, все, що необхідно зробити користувачеві натиснути кілька кнопок.
Щоб підкреслити універсальність методу по відношенню до інструментів розробки, у прикладі було використано додаток, написаний на Apache Cordova. Теж саме справедливо і для інших інструментів, таких як Xamarin.
Дії










Крок 3: Розгортання в корпоративному середовищі на базі Windows Server 2012



Отже, ми підійшли до найскладнішого сценарієм, коли вам недоступні зовнішні майданчики. У цьому випадку, ми будемо використовувати Windows Server 2012 і IIS 8.

Для наочності розгорнемо два окремих сайту:
Примітка
Установка для сайту HTTPS iphone-udid-zzzz.com не обов'язкова, просто візьмемо цей випадок для демонстрації конфігурування IIS.

Для доступу до сайтів по заданим доменним іменам необхідний налаштований DNS-сервер (у прикладі контроллер домена Active Directory, DNS-сервер, і самі сайти — розгорнуті на одній машині).

Почнемо створювати зони прямого перегляду для наших сайтів. Для цього скористаємося диспетчером серверів.
Докладніше










Створимо зону прямого перегляду сайту отримання UDID в iOS пристрою: iphone-udid-zzzz.com.
Докладніше






В академічних цілях наведу налаштування мережі, які важливо враховувати.
ДокладнішеНалаштування мережевого адаптера сервера (де 192.168.0.1 — IP-адреса WiFi-маршрутизатора)



Налаштування DNS для Wi-fi-маршрутизатора. У випадку з D-Link порядок DNS-серверів важливий.



Налаштування мережевого адаптера віртуальної машини з Windows Server 2012.




Створимо сайт (А або АААА).
Докладніше

Пропишемо IP-адресу нашого сервера



Переконаємося, що сайт доступний через FQDN-ім'я. Виконаємо очищення кеша DNS.





Відмінно, ми бачимо, що все працює.


Повторимо цю ж ланцюжок дій для сайту стрибки додатків: corp-apps-zzzz.com.
Докладніше






Тепер можемо приступити до встановлення та налаштування IIS.
Докладніше







Вибираємо Веб-сервер IIS).



Тут все залишаємо без змін.



В рамках даного керівництва використовувалася наступна конфігурація:









Будьте обережні, вибираючи «Автоматична перезавантаження» на бойовому сервері.





Установка завершена.


Створимо заглушки для наших сайтів.
Докладніше








Так як, для установки додатків на iOS-пристрої за посиланням, необхідна підтримка HTTPS — приступимо до створення SSL-сертифікатів. На жаль, SSL-сертифікати, що генеруються IIS, нам не підходять, тому скористаємося утилітою OpenSSL.
В даному посібнику використовується утиліта командного рядка Win32 OpenSSL, яку можна скачати за посилання.
Подробиці по встановленню OpenSSLВиберіть розрядність вашої операційної системи. Для даного Windows Server 2012 був обраний Win64 OpenSSL v1.0.2 e (16MB Installer)



Моменти, на які слід звернути увагу при установці.






Після установки OpenSSL, створимо на диску C папку OpenSSL-Certificates.

Запустимо командний рядок. Створимо сертифікат для iphone-udid-zzzz.com.
Використання утиліти openssl для створення сертифіката
C:\Users\devin> cd c:\OpenSSL-Certificates

c:\OpenSSL-Certificates> set RANDFILE=c:\OpenSSL-Certificates\.rnd

c:\OpenSSL-Certificates> set OPENSSL_CONF=C:\OpenSSL-Win64\bin\openssl.cfg

c:\OpenSSL-Certificates> c:\OpenSSL-Win64\bin\openssl.exe

OpenSSL> genrsa -out iphone-udid-zzzz.key 2048

OpenSSL> req -new -x509 -sha256 -key iphone-udid-zzzz.key -out iphone-udid-zzzz.cer -days 365 -subj /CN=iphone-udid-zzz.com

OpenSSL> pkcs12 -export -out iphone-udid-zzzz.pfx -inkey iphone-udid-zzzz.key -in iphone-udid-zzzz.cer
Enter Export Password:
Verifying - Enter Export Password:

OpenSSL> exit

c:\OpenSSL-Certificates> 


Результат виконання




Аналогічно створимо сертифікат для corp-apps-zzzz.com:
Використання утиліти openssl для створення сертифіката
C:\Users\devin> cd c:\OpenSSL-Certificates

c:\OpenSSL-Certificates> set RANDFILE=c:\OpenSSL-Certificates\.rnd

c:\OpenSSL-Certificates> set OPENSSL_CONF=C:\OpenSSL-Win64\bin\openssl.cfg

c:\OpenSSL-Certificates> c:\OpenSSL-Win64\bin\openssl.exe

OpenSSL> genrsa -out corp-apps-zzzz.key 2048

OpenSSL> req -new -x509 -sha256 -key corp-apps-zzzz.key -out corp-apps-zzzz.cer -days 365 -subj /CN=corp-apps-zzzz.com

OpenSSL> pkcs12 -export -out corp-apps-zzzz.pfx -inkey corp-apps-zzzz.key -in corp-apps-zzzz.cer
Enter Export Password:
Verifying - Enter Export Password:

OpenSSL> exit

c:\OpenSSL-Certificates> 


Результат виконання




Наступним кроком імпортуємо створені *.pfx сертифікати в IIS.
Докладніше








Тепер ми можемо змінити прив'язки, щоб забезпечити HTTPS-з'єднання.

Для сайту: iphone-udid-zzzz.com







Для сайту: corp-apps-zzzz.com








Відмінно, наступним етапом нам потрібно внести зміни в проект WebAPI для сайту iphone-udid-zzzz.com.

Файл Веб.config, для уникнення проблем з WebDAV і помилки 405, секція system.webServer.
Необхідні зміни у файлі Web.config
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/>
</modules>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrl-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<remove name="WebDAV" />
</handlers>
<staticContent>
<mimeMap fileExtension=".mobileconfig" mimeType="application/x-apple-aspen-config" />
</staticContent>
</system.webServer>


Для сертифікатів також потрібно додати зміни в Веб.config.
Докладніше
<system.webServer>
<staticContent>
<remove fileExtension=".mobileconfig" />
<mimeMap fileExtension=".mobileconfig" mimeType="application/x-apple-aspen-config" />
<remove fileExtension=".crt" />
<mimeMap fileExtension=".crt" mimeType="application/x-x509-ca-cert" /> 
</staticContent>
</system.webServer>


Файл /Downloads/iphone-udid-zzzz.mobileconfig — змінено URL.
Докладніше
<key>URL</key>
<string>https://iphone-udid-zzzz.com:9001/api/xml</string>


В теку /Downloads/ додано згенерований сертифікат iphone-udid-zzzz.cer, у якого необхідно змінити розширення на *.crt. В іншому випадку, на iOS-пристрої він буде відкриватися в браузері просто як текстовий файл.
Докладніше

Файл /Views/Home/Index.cshtml — змінені URL (href), додана посилання на скачування SSL-сертифіката.
Необхідні зміни у файлі Index.cshtml
<div class="jumbotron">
<h1>Get your UDID</h1>
<p><a href="/downloads/iphone-udid-zzzz.mobileconfig" class="btn btn-primary btn-lg">Take UDID</a></p>
</div>
<div class="row">
<a href="/downloads/iphone-udid-zzzz.crt" download class="btn btn-info">Install SSL Certificate</a>
<p>
@{
foreach (iPhoneUDID.Models.iPhoneUDID item in ViewBag.UDIDs)
{
<h5>TimeAdded: @item.TimeAdded, UDID: @item.UDID</h5>
}
}
</p>
</div>
<div class="row">
@Html.ActionLink("Clear UDIDs list", "ClearHistory", "Home", null, new { @class = "btn btn-primary btn-large" })
</div>


Файл /Controllers/XmlController.cs — додано конструкція try/catch — обгортка при розборі plist (UDID).
Докладніше
using System;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Xml.Linq;

namespace iPhoneUDID.Controllers
{
public class XmlController : ApiController
{
[HttpPost]
public HttpResponseMessage PostRawXMLMessage(HttpRequestMessage request)
{
string plist = request.Content.ReadAsStringAsync().Result;

string UDID = "Error";
try
{
int begin = plist.IndexOf("UDID") + 20;
int end = plist.IndexOf("<", begin);
UDID = plist.Substring(begin, end begin);
}
catch (Exception exc)
{
//
}


XDocument databaseXML;
try
{
databaseXML = XDocument.Load(System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/udids.xml"));
}
catch (Exception exp)
{
databaseXML = new XDocument(new XElement("udids"));
}

databaseXML.Element("udids").Add(
new XElement("iPhone",
new XElement("TimeAdded", DateTime.Now.ToLongTimeString() + " - " + DateTime.Now.ToShortDateString()),
new XElement("UDID", UDID)));
databaseXML.Save(System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/udids.xml"));

HttpResponseMessage response = request.CreateResponse(HttpStatusCode.MovedPermanently);
response.Headers.Add("Location", "/Thanks");
return response;
}
}
}



Можемо почати складання проекту для сайту iphone-udid-zzzz.com.
Докладніше









Копіюємо отримані файли у відповідну папку на сервері.
Докладніше



Рекомендую перезавантажити сайт.



Також, необхідно дозволити зміни файлу udids.xml всередині каталогу на сервері.
Докладніше






З цього моменту, користувачі можуть реєструвати UDID своїх iOS-пристроїв на сайті: iphone-udid-zzzz.com:9001
ДіїУстановка SSL-сертифіката. Це опціонально.






Якщо натиснути Більш докладно







Реєстрація UDID в iOS пристрою.




Якщо натиснути Більш докладно







Відображення UDID в iOS пристрою.




В цілях тестування POST-запиту реєстрації UDID, рекомендую використовувати безкоштовне розширення для Google Chrome Postman.

Докладніше






Почнемо складання проекту для сайту corp-apps-zzzz.com.

Файл Веб.config.
Зміст файлу Web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<staticContent>
<remove fileExtension=".jpg" />
<mimeMap fileExtension=".jpg" mimeType="image/jpg" />
<remove fileExtension=".png" />
<mimeMap fileExtension=".png" mimeType="image/png" />
<remove fileExtension=".plist" />
<mimeMap fileExtension=".plist" mimeType="text/plain" />
<remove fileExtension=".ipa" />
<mimeMap fileExtension=".ipa" mimeType="application/octet-stream" />
<remove fileExtension=".crt" />
<mimeMap fileExtension=".crt" mimeType="application/x-x509-ca-cert" />
</staticContent>
</system.webServer>
</configuration>


Файл index.html — змінені URL (href), додана посилання на скачування SSL-сертифіката.
Користувачеві необхідно встановити цей сертифікат до початку установки програми. В іншому випадку, він отримає помилку перевірки достовірності сертифіката.
Необхідні зміни у файлі index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
< meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Поширення iOS додатків</title>
<link rel="stylesheet" href="dist/bootstrap.min.css">
<script src="dist/jquery-1.11.3.min.js"></script>
<style>
h4 {line-height: 25px;}
</style>
</head>
<body>
<div class="container">
<br><br>
<h1 class="text-center">Hello Apache Cordova</h1>
<p class="text-center">
<a href="itms-services://?action=download-manifest&url=https://corp-apps-zzzz.com:9002/app-files/manifest.plist" class="btn btn-info" type="button">Install App</a>
<a href="/app-files/corp-apps-zzzz.crt" download class="btn btn-info">Install SSL Certificate</a>
</p>
<br><br>
</div>
</body>
</html>


Файл manifest.plist — змінені URL (додані порти).
Необхідні зміни у файлі manifest.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>items</key>
<array>
<dict>
<key>assets</key>
<array>
<dict>
<key>kind</key>
<string>software-package</string>
<key>url</key>
<string>https://corp-apps-zzzz.com:9002/app-files/myApp.ipa</string>
</dict>
<dict>
<key>kind</key>
<string>display-image</string>
<key>url</key>
<string>https://corp-apps-zzzz.com:9002/app-files/image.57x57.png</string>
</dict>
<dict>
<key>kind</key>
<string>full-size-image</string>
<key>url</key>
<string>https://corp-apps-zzzz.com:9002/app-files/image.512x512.jpg</string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>com.habr.hellohabr001</string>
<key>bundle-version</key>
<string>0.0.1</string>
<key>kind</key>
<string>software</string>
<key>title</key>
<string>myApp</string>
</dict>
</dict>
</array>
</dict>
</plist>


В теку /app-files/ додано згенерований сертифікат corp-apps-zzzz.cer, у якого необхідно змінити розширення на *.crt. В іншому випадку, на iOS-пристрої він буде відкриватися в браузері просто як текстовий файл.
Докладніше


Тепер, для установки програми, користувачеві необхідно натиснути всього кілька кнопок, перейшовши на сайт: corp-apps-zzzz.com:9002
ДіїУстановка SSL-сертифіката.







Якщо натиснути Більш докладно







Установка програми.








Висновок



В рамках даної статті ми розглянули спосіб поширення iOS додатків за посиланням, використовуючи стек технологій компанії Microsoft.

В цілях ознайомлення я виклав демо-проекти на GitHub.

  • Исходники проектів, що використовують зовнішні майданчики для розміщення, можна подивитися тут;
  • Исходники проектів, що використовують в якості майданчика windows server всередині компанії, можна подивитися тут.


Сподіваюся, стаття здасться корисною людям, початківцям розбиратися а даній темі.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.