Прямая запись в справочник 1C: Предприятие через Linq на примере работы с пользователями Asp.Net
Статья описывает как зарегистрировать пользователя веб-сайта в справочнике 1С: Предприятие 8, расположенном в MSSQL базе данных. Далее пользователь может авторизоваться на сайте, используя логин и пароль, указанный при регистрации. Работа ведется только со справочником с названием Пользователи и не затрагивает систему работы с пользователями через конфигуратор 1С.
Описаны только простейшие операции по регистрации и авторизации. Вспомогательные операции по восстановлению пароля, информированию через E-mail не освещаются. Работа ведется прямым доступом к базе MSSQL через Linq. Подход позволяет использовать одновременно функционал Asp.Net и 1С, а также обойтись без посредников в виде разных CMS.
Создание справочника Пользователи в 1С: Предприятие
Предполагается, что информационная база 1С создана и расположена на MSSQL-сервере в локальной сети или удаленно у хостинг-провайдера.
Необходимо через конфигуратор создать справочник Пользователи с кодом в виде строки 9 символов и наименованием 25 символов.
Структура полей следующая (перечень полей взят с избытком для дальнейшего расширения функциональности):
- Активный: Булево
- ДатаРегистрации: Дата
- Email: Строка 255, переменная
- Пароль: Строка 32 переменная
- ПарольПрефикс: Строка 16 переменная
- Язык: Строка 255 переменная
- ФорматДаты: Строка 20 переменная
- КодАктивации: Строка 36 переменная
- КодВосстановленияПароля: Строка 36 переменная
- ДатаАктивности: Дата
Интерфейс созданного справочника сразу доступен из 1С, что позволяет сэкономить время на создании интерфейса администрирования. Это одно из достоинств способа, когда доступен весь арсенал средств 1С: Предприятие. К другим достоинствам можно отнести: пометка на удаление без физического удаления, фильтры и поиск, возможность построения запросов СКД, обмен с другими базами 1С через конвертацию данных и т.д.
Например, доступен список зарегистрированных пользователей сразу после определения справочника в конфигураторе:
А также форма редактирования пользователя:
Настройка прямого доступа к базе данных MSSQL
Для доступа к данным нужно сгенерировать файл cs с определениями LINQ. Для генерации нужно воспользоваться утилитой LinqTo1C, указав какие справочники нужно выгружать, а также строку подключения к MSSQL базе данных. Для нашего случая достаточно выгрузить только Справочник.Пользователи.
Начиная с версии 1.2, LinqTo1C позволяет создавать конфигурационный файл с возможностью изменения данных. Не смотря на достоинства прямой записи в базу данных, у способа есть недостатки. Например, записанная таким способом информация не будет автоматически зарегистрирована в планах обмена. Вам самостоятельно нужно заботиться о поддержании правильности данных: генерировать уникальный код, поддерживать целостность с другими объектами, проверять вновь вносимые данные.
В результате работы утилиты появятся 2 файла: dbml – для визуального представления и cs-для добавления в проект C#. Выглядит в редакторе Visual Studio это так:
Asp.Net код для регистрации и авторизации
Код приведен для Asp.Net MVC, где за работу пользователя отвечает AccountController.
AccountController:
public ActionResult LogOn() { ViewBag.Title = Resources.Account.LogonTitle; return View("~/Views/Dotnet/Logon.cshtml"); } [HttpPost] public ActionResult LogOn(LogOnModel model, string returnUrl) { if (ModelState.IsValid) { if (MembershipService.ValidateUser(model.UserName, model.Password)) { FormsService.SignIn(model.UserName, model.RememberMe); if (Url.IsLocalUrl(returnUrl)) { return Redirect(returnUrl); } else { return RedirectToAction("Index", "Dotnet"); } } else { ModelState.AddModelError("", ""); } } // If we got this far, something failed, redisplay form return View("~/Views/Dotnet/Logon.cshtml", model); } public ActionResult LogOff() { FormsService.SignOut(); return RedirectToAction("Index", "Dotnet"); } public ActionResult Register() { ViewBag.Title = Resources.Account.RegisterTitle; ViewBag.PasswordLength = MembershipService.MinPasswordLength; return View("~/Views/Dotnet/Register.cshtml"); } [HttpPost] public ActionResult Register(RegisterModel model) { if (ModelState.IsValid) { // Attempt to register the user MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Email, model.Password, model.ConfirmPassword); if (createStatus == MembershipCreateStatus.Success) { FormsService.SignIn(model.UserName, false /* createPersistentCookie */); return RedirectToAction("Index", "Dotnet"); } else { ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus)); } } // If we got this far, something failed, redisplay form ViewBag.PasswordLength = MembershipService.MinPasswordLength; return View("~/Views/Dotnet/Register.cshtml", model); }
Вызовы вида FormsService.SignOut и FormsService.SignIn не такие интересные, так как они перенаправляются к стандартным методам: FormsAuthentication.SignOut и FormsAuthentication.SetAuthCookie.
Класс AccountMembershipService осуществляет обращение к базе MSSQL.
Для регистрации пользователя предназначен метод CreateUser. Сначала проверяются возможные ошибки: пустой логин, пароль, e-mail, дублирующийся логин/e-mail, совпадение пароля и подтверждение пароля. Далее заполняются поля пользователя. Ссылке присваивается новый Guid, номер ищется как максимальный номер + 1. Пароль хранится в виде контрольной суммы в закрытом, контрольная сумма вычисляется от пароля пользователя и уникального префикса, который хранится здесь же в записи.
public MembershipCreateStatus CreateUser(string userName, string email, string password, string confirmPassword) { if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName"); if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password"); if (String.IsNullOrEmpty(email)) throw new ArgumentException("Value cannot be null or empty.", "email"); MembershipCreateStatus status = MembershipCreateStatus.ProviderError; using (var dataContext = new ElisyCMS(ConfigurationManager.ConnectionStrings["ElisyCMS"].ConnectionString)) { if (dataContext.СправочникПользователи.Where(m => m.Наименование == userName && m.ПометкаУдаления == new Binary(new byte[]{0})).Count() != 0) return MembershipCreateStatus.DuplicateUserName; if (dataContext.СправочникПользователи.Where(m => m.Email == email && m.ПометкаУдаления == new Binary(new byte[] { 0 })).Count() != 0) return MembershipCreateStatus.DuplicateEmail; if (password != confirmPassword) return MembershipCreateStatus.InvalidPassword; try { СправочникПользователи user = new СправочникПользователи(); user.Ссылка = Guid.NewGuid().ToByteArray(); user.ПометкаУдаления = new byte[] { 0 }; user.Предопределенный = new byte[] { 0 }; var codeRequest = from a in dataContext.СправочникПользователи where Convert.ToInt32(a.Код) > 0 orderby Convert.ToInt32(a.Код) descending select Convert.ToInt32(a.Код); var lastCode = codeRequest.Take(1).FirstOrDefault(); user.Код = (lastCode + 1).ToString().PadLeft(9, '0'); user.Наименование = userName; byte[] saltBytes = new byte[8]; new RNGCryptoServiceProvider().GetBytes(saltBytes); user.ПарольПрефикс = Convert.ToBase64String(saltBytes); byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes(user.ПарольПрефикс + password); byte[] hash = new SHA1CryptoServiceProvider().ComputeHash(passwordBytes); user.Пароль = Convert.ToBase64String(hash); user.ДатаРегистрации = DateTime.Now; user.ДатаАктивности = DateTime.Now; user.Активный = new Binary(new byte[] { 1 }); user.Язык = System.Threading.Thread.CurrentThread.CurrentUICulture.Name; //user.КодАктивации = Guid.NewGuid().ToString(); user.Email = email; dataContext.СправочникПользователи.InsertOnSubmit(user); dataContext.SubmitChanges(); return MembershipCreateStatus.Success; } catch (Exception ex) { return MembershipCreateStatus.ProviderError; } } return status; }
Для авторизации предназначен метод ValidateUser, который после проверки параметров проверяет наличие пользователя в базе, флаг активности и пытается сравнить контрольную сумму пароля с вычисленной контрольной суммой переданного пароля и уникального префикса.
public bool ValidateUser(string userName, string password) { if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName"); if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password"); using (var dataContext = new ElisyCMS(ConfigurationManager.ConnectionStrings["ElisyCMS"].ConnectionString)) { var пользователь = dataContext.СправочникПользователи.Where(m => m.Наименование.ToUpper() == userName.ToUpper()).FirstOrDefault(); if (пользователь == null) return false; if (пользователь.Активный.ToArray()[0] == 0) return false; if (String.IsNullOrWhiteSpace(пользователь.Пароль)) return true; byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes(пользователь.ПарольПрефикс + password); byte[] hash = new SHA1CryptoServiceProvider().ComputeHash(passwordBytes); return Convert.ToBase64String(hash).Equals(пользователь.Пароль); } }
ссылка на оригинал статьи http://habrahabr.ru/post/210654/
Добавить комментарий