protected void Page_Load(object sender, EventArgs e) { using (VendingModelContainer dc = new VendingModelContainer()) { using (var dbContextTransaction = dc.Database.BeginTransaction()) { try { long wvdid = Convert.ToInt64(Request.QueryString["wvdid"]); string prg = Request["prg"]; if (prg != null && wvdid != 0) { DateTime dt = DateTime.Now; //убиваем неподтвержденные заявки на регистрацию, которым больше 3 часов. кто не успел - тот опоздал, блять) long regrequestoldestdatetime = Convert.ToInt64(dt.AddHours(-3).ToString("yyyyMMddHHmmss")); dc.WaterDevices.RemoveRange(dc.WaterDevices.Where(x => x.RegistrationRequestDateTime < regrequestoldestdatetime)); long cdt = Convert.ToInt64(dt.ToString("yyyyMMddHHmmss")); string cdtstr = dt.ToString("dd.MM.yyyy HH:mm:ss"); WaterDevices tmpwd = dc.WaterDevices.Where(x => x.PendingRegistration && x.PendingRegistrationGUID == prg && x.ID == wvdid && !x.PendingRegConfirmed).First(); CryptoHelper ch = new CryptoHelper(); SHA512 sha512 = new SHA512Managed(); //вычисляем хеш открытого ключа устройства byte[] hash = sha512.ComputeHash(tmpwd.PublicKey); //подписываем хеш открытого ключа устройства и формируем ответ. В ответе указываем текущее распределение лицензий с учетом текущей Uri url = new Uri(Request.Url.Authority); string output = url.GetLeftPart(UriPartial.Authority); WaterDeviceRegistrationResponse authresp = new WaterDeviceRegistrationResponse { RegID = tmpwd.ID, ServerEndPoint = output }; authresp.Signature = Convert.ToBase64String(ch.SignHashedData(hash)); int activedevicescount = dc.WaterDevices.Where(x => x.AccountID == tmpwd.AccountID && x.Valid && !x.Suspended && !x.PendingRegistration).Count(); int pendingdevicescount = dc.WaterDevices.Where(x => x.AccountID == tmpwd.AccountID && x.Valid && !x.Suspended && x.PendingRegistration).Count(); Accounts tmpacc = dc.Accounts.Where(x => x.ID == tmpwd.AccountID && x.Valid && !x.Suspended).First(); authresp.AuthResponse = "SUCCESS " + (activedevicescount + 1).ToString() + "/" + (pendingdevicescount - 1).ToString() + "/" + tmpacc.DeviceCountLimit.ToString(); //Сериализуем объект авторизации в XML документ var xs = new XmlSerializer(authresp.GetType()); var xml = new Utf8StringWriter(); xs.Serialize(xml, authresp); tmpwd.RegistrationResponse = xml.ToString(); tmpwd.PendingRegistration = false; tmpwd.PendingRegConfirmationIP = Request.UserHostAddress; tmpwd.PendingRegConfirmed = true; tmpwd.PendingRegConfirmationDateTime = cdt; tmpwd.PendingRegConfirmationDateTimeStr = cdtstr; tmpwd.RegistrationDateTime = cdt; tmpwd.RegistrationDateTimeStr = cdtstr; dc.SaveChanges(); dbContextTransaction.Commit(); Logger.AccountLog(Request.UserHostAddress, "Подтверждение регистрации устройства №" + tmpwd.ID + " получено", tmpwd.HardwareID, tmpacc.ID); Logger.SystemLog(Request.UserHostAddress, "Пользователь подтвердил регистрацию устройства №" + tmpwd.ID, tmpacc.UserID, "Server"); confirmresult.ForeColor = System.Drawing.Color.Lime; confirmresult.Text = "Подтверждение получено"; MailMessage mail = new MailMessage(); mail.To.Add(tmpacc.UserID); mail.From = new MailAddress(WWWVars.MailFromAddress, WWWVars.EMailDisplayName, Encoding.UTF8); mail.Subject = "Регистрация устройства завершена"; mail.SubjectEncoding = Encoding.UTF8; mail.Body = "Добрый день, уважаемый\\ая сэр\\мадам.<br>" + "<p>В системе успешно зарегистрировано новое устройство: <br>" + "Номер: " + tmpwd.ID.ToString() + "<br>" + "Идентификатор: " + tmpwd.PendingRegistrationGUID + "<br>" + "Для завершения регистрации устройство должно быть включено и подключено в Интернету.<br><p>" + "=======================================<br>" + "письмо сгенерировано автоматически, отвечать на него не нужно. Контакты для обратной связи см. на сайте: <br>" + output; mail.BodyEncoding = Encoding.UTF8; mail.IsBodyHtml = true; mail.Priority = MailPriority.High; SmtpClient client = new SmtpClient { UseDefaultCredentials = !WWWVars.MailUseSMTPAuth, Port = WWWVars.SMTPPort, Host = WWWVars.SMTPHost, EnableSsl = WWWVars.SMTPUseSSL, }; if (!client.UseDefaultCredentials) { client.Credentials = new System.Net.NetworkCredential(WWWVars.MailLogin, WWWVars.MailPassword); } client.Send(mail); Logger.AccountLog("Server", "Отправлено письмо с подтверждением регистрации устройства", tmpacc.UserID, tmpacc.ID); Logger.SystemLog("Server", "Отправлено письмо с подтверждением регистрации устройства", tmpacc.UserID, "Server"); } } catch (Exception ex) { confirmresult.ForeColor = System.Drawing.Color.Red; confirmresult.Text = "Ошибка: " + ex.HResult.ToString(); Logger.SystemLog(Request.UserHostAddress, "Ошибка при отправке письма с подтверждением регистрации устройства", ex.Message, "Server"); } } } }
protected void Page_Load(object sender, EventArgs e) { using (VendingModelContainer dc = new VendingModelContainer()) { using (var dbContextTransaction = dc.Database.BeginTransaction()) { Uri url = new Uri(Request.Url.Authority); string output = url.GetLeftPart(UriPartial.Authority); WaterDeviceRegistrationResponse authresp = new WaterDeviceRegistrationResponse { RegID = -1, ServerEndPoint = output }; try { DateTime dt = DateTime.Now; long cdt = Convert.ToInt64(dt.ToString("yyyyMMddHHmmss")); string cdtstr = dt.ToString("dd.MM.yyyy HH:mm:ss"); var waterdevices = dc.WaterDevices; //считываем запрос string rawrequest = Request.Form["RegistrationRequest"]; byte[] bytes = Convert.FromBase64String(rawrequest); string requestxml = Encoding.UTF8.GetString(bytes); //создаем объект запроса регистрации WaterDeviceRegistrationRequest tmpreq = Deserialize <WaterDeviceRegistrationRequest>(requestxml); RSACryptoServiceProvider rsaProvider = null; CryptoHelper ch = new CryptoHelper(); //расшифровываем запрос byte[] plaintextbytes = ch.DecryptData(tmpreq.AuthorizationString); byte[] tmphwidbytes = new byte[] { }; byte[] tmpuidbytes = new byte[] { }; //делим массив данных на две части, разделитель byte[3] { 254, 11, 254 } for (int i = 0; i < plaintextbytes.Length; i++) { if (plaintextbytes[i] == 254 && plaintextbytes[i + 1] == 11 && plaintextbytes[i + 2] == 254) { Array.Resize(ref tmphwidbytes, i); Array.Copy(plaintextbytes, 0, tmphwidbytes, 0, tmphwidbytes.Length); Array.Resize(ref tmpuidbytes, plaintextbytes.Length - i - 3); Array.Copy(plaintextbytes, i + 3, tmpuidbytes, 0, tmpuidbytes.Length); break; } } //поля запроса: учетная запись и аппаратный идентификатор устройства string userid = Encoding.UTF8.GetString(tmpuidbytes); string hwid = Encoding.UTF8.GetString(tmphwidbytes); //инициализируем криптодвижок для проверки подписи присланных данных rsaProvider = new RSACryptoServiceProvider(); rsaProvider.ImportCspBlob(tmpreq.PublicKey); SHA512 sha512 = new SHA512Managed(); //вычисляем хеш присланных данных byte[] hash = sha512.ComputeHash(plaintextbytes); int activedevicescount; int pendingdevicescount; Accounts tmpacc; //проверяем подпись bool signcorrect = rsaProvider.VerifyData(plaintextbytes, CryptoConfig.MapNameToOID("SHA512"), tmpreq.AuthSignature); if (signcorrect) { //подпись корректна, ищем акаунт tmpacc = dc.Accounts.First(x => x.UserID == userid && x.Valid && !x.Suspended); activedevicescount = waterdevices.Where(x => x.AccountID == tmpacc.ID && x.Valid && !x.Suspended && !x.PendingRegistration).Count(); pendingdevicescount = waterdevices.Where(x => x.AccountID == tmpacc.ID && x.Valid && !x.Suspended && x.PendingRegistration).Count(); WaterDevices tmpdev = null; //пробуем найти акаунт с таким же аппаратным идентификатором, чтобы исключить дубликаты try { tmpdev = waterdevices.Where(x => x.HardwareID == hwid /* && x.AccountID == tmpacc.ID && x.Valid && !x.Suspended*/).First(); //если устройство нашлось и зарегистрировано, отсылаем содержимое лицензии if (!tmpdev.PendingRegistration) { authresp = Deserialize <WaterDeviceRegistrationResponse>(tmpdev.RegistrationResponse); } else //если устройство нашлось и ожидает регистрации { authresp.Signature = ""; authresp.AuthResponse = "OK_PENDING"; } } catch { } //если в базе нет устройства if (tmpdev == null) { //есть неиспользованные лицензии, формируем запись нового устройства if (activedevicescount < tmpacc.DeviceCountLimit) { WaterDevices newwaterdevice = new WaterDevices() { CustomerServiceContactPhone = tmpacc.DefaultContactPhone, HardwareID = hwid, AccountID = tmpacc.ID, LocationAddress = "", LocationLatitude = 0, LocationLongtitude = 0, ProductName = "Вода питьевая", PendingRegistration = true, PRICE_PER_ITEM_MDE = 500, PublicKey = tmpreq.PublicKey, RegistrationRequest = requestxml, Suspended = false, Valid = true, RegistrationDateTime = 0, RegistrationRequestDateTime = cdt, RegistrationDateTimeStr = "", RegistrationRequestDateTimeStr = cdtstr, RegistrationResponse = "", PendingRegistrationGUID = Guid.NewGuid().ToString(), PendingRegConfirmed = false, PendingRegConfirmationIP = "", PendingRegConfirmationDateTime = 0, PendingRegConfirmationDateTimeStr = "" }; //добавляем запись в БД waterdevices.Add(newwaterdevice); dc.SaveChanges(); Logger.AccountLog(Request.UserHostAddress, "Принята заявка на регистрацию нового устройства", newwaterdevice.HardwareID, tmpacc.ID); Logger.SystemLog(Request.UserHostAddress, "Регистрация нового устройства", tmpacc.UserID, "Server"); MailMessage mail = new MailMessage(); mail.To.Add(tmpacc.UserID); mail.From = new MailAddress(WWWVars.MailFromAddress, WWWVars.EMailDisplayName, Encoding.UTF8); mail.Subject = WWWVars.RegDeviceMailSubject; mail.SubjectEncoding = Encoding.UTF8; string confirmurl = output + "/User/ConfirmRegistration.aspx?wvdid=" + newwaterdevice.ID.ToString() + "&prg=" + newwaterdevice.PendingRegistrationGUID; mail.Body = "Добрый день, уважаемый\\ая сэр\\мадам.<br>" + "<p>В систему добавлена заявка на регистрацию нового устройства. Для подтверждения пройдите по ссылке ниже:<br>" + "<a href=\"" + confirmurl + "\">" + confirmurl + "</a><br>" + "<b><font color=\"red\">Внимание: Ссылка будет активной в течение 3 часов!<br> Если вы не завершите регистрацию до " + DateTime.Now.AddHours(3).ToString("dd.MM.yyyy HH:mm:ss") + ", процедуру регистрации необходимо будет повторить на устройстве с использованием файла лицензии.</font></b><br></p>" + "=======================================<br>" + "письмо сгенерировано автоматически, отвечать на него не нужно. Контакты для обратной связи см. на сайте: <br>" + output; mail.BodyEncoding = Encoding.UTF8; mail.IsBodyHtml = true; mail.Priority = MailPriority.High; SmtpClient client = new SmtpClient { UseDefaultCredentials = !WWWVars.MailUseSMTPAuth, Port = WWWVars.SMTPPort, Host = WWWVars.SMTPHost, EnableSsl = WWWVars.SMTPUseSSL, }; if (!client.UseDefaultCredentials) { client.Credentials = new System.Net.NetworkCredential(WWWVars.MailLogin, WWWVars.MailPassword); } client.Send(mail); authresp.AuthResponse = "OK_PENDING"; Logger.AccountLog("Server", "Отправлено электронное письмо о регистрации нового устройства", tmpacc.UserID, tmpacc.ID); Logger.SystemLog("Server", "Отправлено письмо о регистрации нового устройства", tmpacc.UserID, "Server"); } //превышен лимит лицензий, отказ регистрации else { authresp.Signature = ""; authresp.AuthResponse = "DENY_OVERQUOTA"; } } else //устройство уже есть в БД, ничего не делаем { } } else //подпись некорректна, отказ регистрации { authresp.Signature = ""; authresp.AuthResponse = "DENY_SIGNATURE_MISMATCH"; } //сохраняем изменения в БД dbContextTransaction.Commit(); } catch (Exception ex) { //что-то пошло не так, ошибка на любом этапе, прерываем регистрацию, откатываем изменения в БД if (ex.HResult != -2146233040) { dbContextTransaction.Rollback(); authresp.Signature = ""; authresp.AuthResponse = "ABORT CODE: " + ex.HResult.ToString(); Logger.SystemLog(Request.UserHostAddress, "Ошибка при регистрации устройства: " + ex.Message, "", "Server"); } } finally { //Сериализуем объект авторизации в XML документ var xs = new XmlSerializer(authresp.GetType()); var xml = new Utf8StringWriter(); xs.Serialize(xml, authresp); //переводим в массив байт, кодируем в Base64 для передачи по http byte[] xmlbytes = Encoding.UTF8.GetBytes(xml.ToString()); string xmlbytesbase64 = Convert.ToBase64String(xmlbytes); //отсылаем ответ устройству Response.Clear(); Response.Write(xmlbytesbase64); } } } }