Google Calendar API и проблема с общим хостингом

Я пытаюсь использовать общедоступный календарь Google на веб-странице, для которой потребуются функции редактирования. Для этого я создал календарь и сделал его общедоступным. Затем я создал учетную запись службы Google и соответствующий идентификатор клиента. Я также включил API календаря и добавил в проект DLL версии 3. Я скачал сертификат p12 и тут начались проблемы.

Звонок в Google идет с сертификатом X509, но структура .NET построена так, что она использует временную папку пользователя. Поскольку это общий хост для веб-сервера (GoDaddy), я не могу изменить идентификатор пула приложений. В результате я получаю эту ошибку:

System.Security.Cryptography.CryptographicException: система не может найти указанный файл.

при вызове:

X509Certificate2 certificate = new X509Certificate2(GoogleOAuth2CertificatePath,
                "notasecret", X509KeyStorageFlags.Exportable);

этот сертификат var затем будет использоваться в вызове Google:

ServiceAccountCredential credential = new ServiceAccountCredential(
                new ServiceAccountCredential.Initializer(GoogleOAuth2EmailAddress)
                {
                    User = GoogleAccount,
                    Scopes = new[] { CalendarService.Scope.Calendar }
                }.FromCertificate(certificate));

... но я никогда не захожу так далеко.

Вопрос: есть ли способ сделать вызов по-другому, т.е. использовать не сертификат X509, а JSON? Или я могу заставить функцию x509 использовать общее временное местоположение, а не местоположение пользователя, к которому у меня нет доступа, поскольку я не могу изменить личность в пуле приложений?

Поскольку я полностью застрял, любая помощь будет оценена по достоинству.


comment
Конечно, при использовании JSON у вас будет та же проблема - проблема в том, что я не могу загрузить файл, а не для Google или X509. Вы потенциально можете встроить сертификат в сборку и использовать Assembly.GetManifestResourceStream для загрузки данных...   -  person Jon Skeet    schedule 23.09.2016
comment
Согласен, куда вы положили GoogleOAuth2CertificatePath?   -  person DaImTo    schedule 23.09.2016
comment
файл .p12 находится в папке App_Data/MyGoogleStorage.   -  person Nick    schedule 23.09.2016
comment
Файл .p12 находится в папке App_Data/MyGoogleStorage. Я могу загрузить файл при вводе адреса напрямую, так что это не проблема пути или учетных данных. Я также согласен с тем, что проблема не в самом Google, поскольку я застреваю перед вызовом, когда сертификат x509 фактически создается. @Jon Skeet: мне нравится твоя идея ... не мог бы ты привести пример кода?   -  person Nick    schedule 23.09.2016
comment
Что именно вы имеете в виду, говоря, что я могу загрузить файл при прямом вводе адреса? Ваше веб-приложение не должно показывать его...   -  person Jon Skeet    schedule 23.09.2016
comment
извините за путаницу. Я переместил папку MyGoogleStorage в корень, а затем скачал файл, и все заработало. Таким образом, абсолютный путь правильный. Затем я сделал тесты из этой папки, и это не удалось. Поскольку это было очищено, я переместил папку Google обратно в App_Data, где она должна быть, насколько я понимаю.   -  person Nick    schedule 23.09.2016
comment
Извини, я все еще не с тобой. Это звучит как совершенно другой путь кода ... и вам действительно нужно убедиться, что ваш сертификат не является общедоступным.   -  person Jon Skeet    schedule 23.09.2016


Ответы (1)


Один простой вариант, позволяющий не беспокоиться о расположении файлов, — встроить сертификат в вашу сборку. В Visual Studio щелкните файл правой кнопкой мыши и отобразите его свойства. В разделе «Действие сборки» выберите «Встроенный ресурс».

Затем вы сможете загрузить данные примерно так:

// In a helper class somewhere...
private static byte[] LoadResourceContent(Type type, string resourceName)
{
    string fullName = type.Namespace + "." + resourceName;
    using (var stream = type.Assembly.GetManifestResourceStream(fullName)
    {
        var output = new MemoryStream();
        stream.CopyTo(output);
        return output.ToArray();
    }
}

Затем:

byte[] data = ResourceHelper.LoadResourceContent(typeof(MyType), "Certificate.p12");
var certificate = new X509Certificate2(data, "notasecret", X509KeyStorageFlags.Exportable);

Здесь MyType — это какой-то тип, который находится в той же папке, что и ваш ресурс.

Обратите внимание, что в .NET существует множество различных типов "веб-проектов"... в зависимости от точного типа проекта, который вы используете, вам может потребоваться настроить это.

person Jon Skeet    schedule 23.09.2016
comment
это проект веб-страницы, поэтому у меня нет возможности встроить файл, или нет? Единственное свойство, которое у меня есть в VS2012, - это имя файла и локальный путь. - person Nick; 23.09.2016
comment
@Nick: Из твоего описания было неясно, какой проект ты использовал. Вы могли бы поместить его в отдельную библиотеку классов... или обновить, чтобы использовать более полнофункциональный вид веб-проекта... - person Jon Skeet; 23.09.2016
comment
сайт представляет собой веб-приложение .net 4.5 - person Nick; 23.09.2016
comment
@Nick: Правильно, если это веб-приложение, вы сможете без проблем добавить ресурс. (А если вы используете VS2012, то это C# 5, а не C# 4, верно?) - person Jon Skeet; 23.09.2016
comment
@Nick: Я только что попробовал - по общему признанию, в VS2015 - создать новое приложение WebForms и добавить файл ... Я смог настроить действие сборки в порядке. - person Jon Skeet; 23.09.2016
comment
Это может показаться глупым, но я создал папку App_GlobalResources и поместил туда копию файла .p12. Я могу создать класс с первой частью кода, верно? И mytype будет чем-то вроде System.Web.HttpContext.Current.Server.MapPath(/App_GlobalResources)? - person Nick; 23.09.2016
comment
@Nick: Нет, с моим предложением вы не получите отдельный файл на диске вообще при развертывании приложения. Никаких MapPath или чего-то подобного. Боюсь, я мало знаю о веб-приложениях и о том, где подходящее место для размещения некодового, необслуживаемого контента - вполне может быть, что есть лучшее решение, чем использование встроенного ресурса, но я подумал решение было бы лучше, чем ничего. Вы бы поместили ресурс в ту же папку, что и ваш код, и установили бы его как встроенный ресурс, и использовали бы любой тип в том же самом пространстве имен, чтобы добраться до него. - person Jon Skeet; 23.09.2016
comment
для добавления рабочего стола я привык к встроенным ресурсам, например, для запуска внешних приложений в моем коде. Я никогда раньше не использовал встроенные ресурсы в веб-приложениях, поэтому я могу показаться немного потерянным. Я ценю усилия и буду смотреть в потоке - person Nick; 23.09.2016