Pull to refresh
13
0
Send message
Приведу вам выдержки из кода, использующего API OpenSSL.

1. Собственно таблица «русских» полей:

OpensslObject ruOpensslObjects[] =
{
	{"INN", "INN", "1.2.643.3.131.1.1", V_ASN1_NUMERICSTRING},
	{"OGRN", "OGRN", "1.2.643.100.1", V_ASN1_NUMERICSTRING},
	{"OGRNIP", "OGRNIP", "1.2.643.100.5", V_ASN1_NUMERICSTRING},
	{"SNILS", "SNILS", "1.2.643.100.3", V_ASN1_NUMERICSTRING},
	{"kpFSS", "KP FSS", "1.2.643.3.141.1.2", V_ASN1_UTF8STRING},
	{"rnsFSS", "RNS FSS", "1.2.643.3.141.1.1", V_ASN1_UTF8STRING},
	{"KC1", "KC1", "1.2.643.100.113.1", -1},
	{"KC2", "KC2", "1.2.643.100.113.2", -1}, // TODO: check  sn and ln names for russian policy
	{"KC3", "KC3", "1.2.643.100.113.3", -1},
	{"KB1", "KB1", "1.2.643.100.113.4", -1},
	{"KB2", "KB2", "1.2.643.100.113.5", -1},
	{"KA1", "KA1", "1.2.643.100.113.6", -1},
	{"subjectSignTool", "Subject Sign Tool", "1.2.643.100.111", -1},
}; 


2. Регистрируем «объекты», связанные с «русскими» полями

try {
		for (int i = 0; i != boost::size(ruOpensslObjects); i++)
		{
			int nid = m_openssl->OBJ_create(ruOpensslObjects[i].oid, ruOpensslObjects[i].sn,
			                                ruOpensslObjects[i].ln);
			m_objectsMap[nid] = &(ruOpensslObjects[i]);
		}
	} catch (std::exception& exc) {
		e = exc;
		exceptionThrown = true;
		goto opensslEngineFinish;
	}


3. Собственно функция формирования subject в PKCS#10. «Русские» поля обрабатываются в default.

void Pkcs10Request::addSubjectEntry(const string& name, const string& value)
{
	if (name.empty() || value.empty())
		BOOST_THROW_EXCEPTION(BadParamsException());

	const OpensslWrapper* openssl = m_crypto->openssl();
	int nid = openssl->OBJ_txt2nid(name.c_str());
	int encodingType = 0;
	switch (nid)
	{
		case NID_commonName:
		case NID_organizationName:
		case NID_organizationalUnitName:
		case NID_title:
		case NID_localityName:
		case NID_stateOrProvinceName:
		case NID_surname:
		case NID_givenName:
		case NID_streetAddress:
		case NID_postalAddress:
		case NID_pseudonym:
			encodingType = MBSTRING_UTF8;
			break;
		case NID_pkcs9_emailAddress:
			encodingType = V_ASN1_IA5STRING;
			break;
		case NID_countryName:
			encodingType = V_ASN1_PRINTABLESTRING;
			break;
		default:
			const OpensslObject* obj = m_crypto->object(nid);
			encodingType = obj->asn1enc;
	}

	if (!openssl->X509_NAME_add_entry_by_NID(m_subject, nid, encodingType,
	                                         reinterpret_cast<unsigned char*>(const_cast<char*>(value.c_str())),
	                                         -1, -1, 0))
		BOOST_THROW_EXCEPTION(OpensslException(openssl));
}


Через тулзу openssl сделать то же самое с ходу не удалось, как-то там мутно конфигурируются типы новых OID-ов.
OpenSSL по-мимо своей дурной славы своим неполноценным API. Например, вы не можете с помощью него сделать сертификат на ГОСТовский ключ, который удовлетворяет приказу ФСБ из-за того, что ему нельзя указать тип у полей у тэгов ИНН, СНИЛС и ОГРН.

Почему же. Можно.
А другой путь — в качестве криптоядра chromium использовать openssl вы не рассматривали? В этом случае патч будет существенно меньше.
Если абстрагироваться от баталии, то проект atoken предлагает работающее решение. Правда для устаревшей версии NSS.
А в Яндекс.Браузере поддержку ГОСТ не планируете сделать?
А зачем отключать pkicore? Вы же поменяли исходники и сами себе багу создали.
Без отключения будет
warning call_user_func_array() expects parameter 1 to be a valid callback, class '_CryptoCore' does not have a method 'exec' in 

здесь скорее надо проверить метод на method_exists
в примере у человека mvc все-таки установлен. Но его можно и не ставить, если нужна поддержка чисто WebAPI на формах.
Размер пакетов у меня вышел ~ 800kb
+1
Понравилось. Спасибо. Сменил некоторые самописные велосипеды на WebAPI.
И, кстати, не только для mvc. Можно тут взять — http://aspnetwebstack.codeplex.com/ и к формам прикрутить.
посмотрел как геттер сделан:
public int ContentLength
{
    get
    {
        if ((this._contentLength == -1) && (this._wr != null))
        {
            string knownRequestHeader = this._wr.GetKnownRequestHeader(11);
            if (knownRequestHeader != null)
            {
                try
                {
                    this._contentLength = int.Parse(knownRequestHeader, CultureInfo.InvariantCulture);
                }
                catch
                {
                }
            }
            else if (this._wr.IsEntireEntityBodyIsPreloaded())
            {
                byte[] preloadedEntityBody = this._wr.GetPreloadedEntityBody();
                if (preloadedEntityBody != null)
                {
                    this._contentLength = preloadedEntityBody.Length;
                }
            }
        }
        if (this._contentLength < 0)
        {
            return 0;
        }
        return this._contentLength;
    }
}


Так что данные на сервере не из-за обращения к Request.ContentLength, это да.
Просто загрузку никто не прерывает, вот в чем дело. Даже если сделать сабмит формы с файлом в iframe, мы же должны получить ответ, что размер превышен, причем получим его в тот же iframe.

Чтобы можно было прервать, нельзя к Request обращаться в модуле загрузки, про который писал. У меня все заработало, только когда убрал обращение во всех классах. Иначе запросы статуса ждали окончания загрузки, потом выдавали 100%.

> А какая разница какой контрол? Данные то все равно уже на сервере «в полном объеме».
Разница есть. Если использовать html5, flash или silverlight можно сделать загрузку чанками, причем запрашивать на сервере максимальный размер чанка. Со стандартным контролом input type=«file» так не выйдет.
Данные на сервере в полном объеме только по тому, что вы вызываете Requset, что заставляет его ресолвиться полностью.
Есть способ доступа к размеру загружаемого контента в начале загрузки. При этом клиенту можно сообщить, что размер превышен, и таким образом он сможет прервать загрузку.

Вот код из моего модуля загрузки:
private const string C_MARKER = "multipart/form-data; boundary=";

  private HttpWorkerRequest GetWorkerRequest(HttpContext context)
        {
            IServiceProvider provider = context;

            // если траблы с доступом - используем
        	new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
            return (HttpWorkerRequest) provider.GetService(typeof (HttpWorkerRequest));
        }

 private void Context_AuthenticateRequest(object sender, EventArgs e)
        {
            var app = sender as HttpApplication;
            HttpWorkerRequest worker = GetWorkerRequest(app.Context);
            int bufferSize;
            string boundary;
            string ct;
            bool statusPersisted = false;        

       

           // заголовок запроса (multipart form data)
            ct = worker.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentType);


            // application/x-www-form-urlencoded
            // проверка что это именно форма с файлом. еще и параметр запроса проверяем
            if (worker.GetQueryString() == "upload" && ct != null &&
                string.Compare(ct, 0, C_MARKER, 0, C_MARKER.Length, true, CultureInfo.InvariantCulture) == 0)
            {
                long length = long.Parse(worker.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength));


                if (length > 0)
                {
                    if (length/1024 > GetMaxRequestLength(app.Context))
                    {

                       // здесь ставим статус "Запрос превышен". Клиент сможет его забрать и отменить загрузку


                    }
.....


Дальше делаем httpHandler с отдачей процента загрузки
         /// <summary>
        /// отдаем процент загрузки
        /// </summary>
        public void GetProgress()
        {
            UploadStatus status = UploadManager.Instance.Status;
            m_message = new CMessageXml(status ?? UploadStatus.EMPTY_STATUS);
            // дальше в классе делаем Response.Write(m_message.ToString());
            // Response.End();
        }

Статус ставится объекту класса UploadStatus. Он у нас [DataContract].

Вобщем принцип думаю понятен.

Главное что такой подход позволяет делать запросы на сервер в процессе загрузки. Если пытаться опрашивать сервак, используя Request, ничего не выйдет, ответ получите после полной загрузки вашего файла.

Ну и отменить загрузку конечно можно.
Есть одна проблема с данным подходом: исключение будет брошено после полной загрузки. Если файл большой, не красиво выйдет, клиенту придется дождаться пока все отправится.

Для решения можно сделать HttpModule, в котором смотреть на httpWebRequest и его KnownHeaders для определения длина запроса. Так например neatUpload делает
Можно и процесс загрузки получать…

На клиенте же используется стандартный html fileupload контрол, в iframe
Отменять можно например как здесь — www.obout.com/fup/example_11.aspx
исправлено за время написания камента )
Ссылку на пример с overflow:auto пофиксите, смотрит на второй, с clear:both

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Registered
Activity