УДК 519.6:004.4
Разработка модуля авторизации пользователей и разграничения прав доступа к данным
Д.Е. Белов, к. б. н.,
А.Ф. Шалин, гл. специалист по информационной безопасности
Активное развитие информационных технологий и их повсеместное внедрение во все отрасли экономики оказывает существенное влияние на коммуникационные процессы, протекающие в обществе. В результате эти процессы становятся более эффективными, увеличивается количество информации и скорость обработки информации, улучшается её качество. То есть увеличение информационных потоков привело к необходимости стандартизации их обработки и хранения данных.
Вместе с положительными аспектами развития информационных технологий открывается ряд проблем, связанных с контролем данных. А именно, их целостности и непротиворечивости, особенно в случаях распределенных систем обработки данных, когда пользователи, осуществляющие ввод информации в базу данных, не являются сотрудниками организации, осуществляющей свод отчетности и принимающей в соответствии с консолидированными данными определенные решения. В частности, такая структура характерна и для нашего случая. В том числе остается открытым вопрос о юридической ответственности за неверный ввод данных или намеренный ввод данных, не соответствующих действительности. Равно как и ответственность за действия, направленные на изменения информации с целью ввода в заблуждение органов, контролирующих свод и обработку данных, либо в целях дискредитации руководства нижестоящих организаций путем незаконного завладения идентификационными данными пользователя в системе. Долгое время, а именно с 2002 г., с принятием закона - Федеральный закон от 10 января 2002 г. N 1-ФЗ "Об электронной цифровой подписи" - в вопросах, описанных выше, не наблюдалось сколько-либо значимых изменений. Основной причиной подобного застоя в этом направлении считается фактическая монополизация процесса выдачи электронной цифровой подписи компанией ООО «КРИПТО-ПРО». Однако ситуация в этом направлении развития информационных технологий может существенно измениться уже с 1 июля 2013 года, что обусловлено принятием Федерального закона от 06.04.2011 №63-Ф3 "Об электронной подписи", которым вводится ряд новых возможностей, позволяющих разработчикам информационно-вычислительных систем
совершенствовать процессы, связанные с использованием ЭЦП, в том числе путем ее создания.
Таким образом, опираясь на вышеизложенные задачи и пути их
решения, можно определить следующие принципы разработки модуля авторизации пользователей и разграничения прав доступа к данным:
1. Должна быть осуществлена возможность использования электронной подписи в будущем;
2. Должен быть реализован механизм логирования пользователей в системе в соответствии с их идентификационными данными, к которым относятся:
а) логин;
б) пароль;
в) ip-адрес электронного средства, с которого осуществляется ввод или изменение информации;
б) электронная подпись (в случае необходимости предъявления данного требования потребителем в рамках Федерального закона от 06.04.2011 №63-Ф3 "Об электронной подписи");
3. Механизм логирования должен позволять идентифицировать пользователя в случаях создания записи, её изменения или удаления;
4. Удаляемая пользователем информация не должна физически удаляться из базы данных, но должна быть скрыта и не участвовать в процессе обработки данных;
5. Необходимо при ведении лога фиксировать транзакционное время осуществления действий пользователей в системе;
6. Идентификационные данные пользователей должны храниться в базе данных в зашифрованном виде.
Опираясь далее на сформулированные принципы разработки модуля авторизации пользователей и разграничения прав доступа к данным, был осуществлен анализ разрабатываемого проекта на предмет практической реализации заявленной функциональности. Оказалось, что используемые нами подходы в части достижения кросс-платформенности, реализованные на основе Java Persistence API (JPA), не позволяют использовать типовые реализации журнализации транзакций, встроенные в современные СУБД. То есть для системы управления базами данных, все действия осуществляются одним пользователем, которому назначены соответствующие права доступа. При предложенной архитектуре информационной системы, представленной на рисунке 1, права доступа к данным и принципы логирования действий пользователей должны закладываться не на уровне базы данных, а на уровне DAO (data access object) слоя приложения.
С точки зрения практической реализации, это означало, что необходимо воспользоваться следующим алгоритмом:
1. Создание в СУБД записей, хранящихся в зашифрованном виде и однозначно идентифицирующих пользователей системы.
2. Разработка классов, осуществляющих шифрование и дешифрование данных, обеспечивающих их сохранение, извлечение и изменение.
3. Организация доступа пользователей к данным в рамках сессий с возможностью идентификации пользователя, его 1р-адреса, принадлежности к определённой организации и назначение ему в соответствии с этими параметрами определенных прав доступа к данным в рамках групповой политики.
4. Осуществление записи информации в базу данных при выполнении действий, модифицирующих ее состояние.
Для решения обозначенных задач и оптимизации затрат на написание исходного кода было принято решение вынести операции, осуществляющие изменение базы данных, в отдельный класс, в котором должны инкапсулироваться сформулированные принципы разработки модуля авторизации пользователей и разграничения прав доступа к данным.
Рисунок 1 - Упрощенное представление архитектуры информационно-вычислительной системы.
Эти классом стал SuperAbstractBean, собственно говоря, его название вытекает из объявления, так как при использовании JPA спецификатор Abstract задает компилятору информацию о том, что данный класс не имеет объектов, то есть нет необходимости сохранять данный класс в базе - он не является самостоятельной сущностью (entity). А аннотация Entity с параметром «mappedSuperclass = true» позволяет хранить информацию наследников данного класса в различных таблицах базы данных.
Ниже приведен исходный код данного класса (для сокращения были приведены только методы, имеющие непосредственное отношение к реализации ядра проекта. Переопределенный метод toString, а также методы get и set для каждого из полей были опущены.): @RooEntity (mappedSuperclass = true)
public abstract class SuperAbstractBean implements Serializable{ private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType. AUTO)
@Column(name = "id") protected Long id;
@Version
@Column(name = "version") private Integer version; private Long userCreateID; private String userCreateIP; private String userCreateESign;
@Temporal(T em poralT ype. TIMES TAMP)
@DateTimeFormat(style = "M-") private Date userCreateTime; private Long userModifyID; private String userModifyIP; private String userModifyESign;
@Temporal(T em poralT ype. TIMES TAMP)
@DateTimeFormat(style = "M-") private Date userModifyTime; private Long userDeleteID; private String userDeleteIP; private String userDeleteESign;
@Temporal(T em poralT ype. TIMES TAMP)
@DateTimeFormat(style = "M-") private Date userDeleteTime;
@Value("false")
private Boolean falseDelete;
@Transactional public void persist() {
if (this.entityManager == null) this.entityManager = entityManager(); if (WebApplication.gef()!= null){
WebApplicationContext wc = ((WebApplicationContext) WebApplication.gef().getContext());
setUserCreateID(WebApplication.gef().getUser().getId());
setUserCreateIP(wc.getBrowser().getAddress()); setUserCreateESign(WebApplication.get().getUser().getESign()); setUserCreateTime(new Date());
}
this.entityManager.persist(this);
}
@Transactional public void remove() {
if (WebApplication.get()!= null) {
WebApplicationContext wc = ((WebApplicationContext) WebApplication.get().getContext());
if (this.entityManager == null) this.entityManager = entityManager(); if (this.entityManager.contains(this)) { this.setUserDeleteID(WebApplication.gef().getUser().getId()); this.setUserDeleteIP(wc.getBrowser().getAddress()); this.setUserDeleteESign(WebApplication.gef().getUser().getESign());
this.setUserDeleteTime(new Date()); this.falseDelete = true;
} else {
SuperAbstractBean attached = findSuperAbstractBean(this.id); this.setUserDeleteID(WebApplication.gef().getUser().getId()); this.setUserDeleteIP(wc.getBrowser().getAddress()); this.setUserDeleteTime(new Date()); this.falseDelete = true;
}
}
else {
if (this.entityManager == null) this.entityManager =
entityManager();
if (this.entityManager.contains(this)) { this.entityManager.remove(this);
} else {
SuperAbstractBean attached = SuperAbstractBean.findSuperAbstractBean(this.id);
this.entityManager.remove(attached);
}
}
}
@Transactional
public SuperAbstractBean merge() { if (WebApplication.get()!= null) {
WebApplicationContext wc = ((WebApplicationContext) WebApplication.get().getContext());
if (this.entityManager == null) this.entityManager = entityManager(); this.setUserModifyID(WebApplication.gef().getUser().getId()); this.setUserModifyIP(wc.getBrowser().getAddress()); this.setUserDeleteESign(WebApplication.gef().getUser().getESign()); this.setUserModifyTime(new Date());
SuperAbstractBean merged = this.entityManager.merge(this);
this.entityManager.flush(); return merged;
}
else {
if (this.entityManager == null) this.entityManager = entityManager();
SuperAbstractBean merged = this.entityManager.merge(this); this.entityManager.flush(); return merged;
}
}
}
Почему для нас так важен именно этот класс? Да потому что он и составляет основную часть ядра модуля авторизации пользователей и разграничения прав доступа к данным. В нем инкапсулируются все методы, отвечающие сформулированным принципам для данного модуля. Наложением условий ограничения на разработку таким образом, что все классы, имеющие методы, осуществляющие любые вызовы DML (data manipulation language) операторов, должны наследоваться от SuperAbstractBean, мы гарантируем реализацию следующих сформулированных принципов:
1. Должен быть реализован механизм логирования пользователей по правилу «последней порчи» (то есть мы с уверенностью можем говорить о том, кто и когда создал или удалил запись, но информация о модификации записи сохраняется только о последнем пользователе. Ниже будет приведен материал, позволяющий обойти данное ограничение).
2. Возможность использования электронной подписи.
3. Удаляемая пользователем информация физически не удаляется из базы данных, но может быть легко скрыта и не участвовать в процессе обработки данных (за это отвечает поле falseDelete, по умолчанию «false», что достигается использованием аннотации @Value("false").
4. При ведении лога фиксируется транзакционное время осуществления действий пользователей в системе.
Как видно из приведённого материала, была достигнута основная часть декларируемых показателей разрабатываемого модуля.
Однако с определённой проблемой наша команда столкнулась в связи с необходимостью соблюдения принципов переносимости программного обеспечения между базами данных, что обусловливается существенно различающимися механизмами генерации первичных ключей. Проблема решается незначительными модификациями в коде, например, для перехода на Oracle необходимо будет добавить в исходный код следующий метод:
@PrePersist public void setNextId() { if (this. id == null) {
Identifier i = new Identifier();
if (this.getClass().getSimpleName().equals("Region") || this.getClass().getSimpleName().equals("Rayon")
|| this.getClass().getSimpleName().equals("Company")) { i.sqlCallfromDual("Unit");
} else {
i.sqlCallfromDual(this.getClass().getSimpleName());
}
setId(i.getNextID());
}
System.oa/.println(" private void prePers() = " + this.getClass().getSimpleName());
}
В дальнейшем предполагается полностью автоматизировать этот процесс путем внесения изменений в настроечном файле.
Что касается разработки механизма шифрования паролей, нашей командой было принято решение использовать библиотеку security из пакета org.springframework. Одним из основных классов данной библиотеки, отвечающих за шифрование и дешифрование данных, является MessageDigestPasswordEncoder. Для увеличения стойкости пароля к дешифрованию было использовано так называемое «подсаливание» ( salt). Для получения соли проводилась генерация UUID (Universally Unique identifier), затем выбиралась строка из 10 первых символов, после чего эти данные вместе с паролем передавались в качестве параметров методу encodePassword класса
SimplePasswordEncoder.
public void setPassword(String password) { if (!password.equals(this.password)) {
String salt = UUID.randomUUID().toString().substring(0, 10); this.salt = salt;
SimplePasswordEncoder pass = new SimplePasswordEncoder("MD5");
this.password = pass.encodePassword(password, salt);
}
}
public class SimplePasswordEncoder extends MessageDigestPasswordEncoder {
public SimplePasswordEncoder(String algorithm) { super(algorithm);
}
@Override
public String encodePassword(String originalPassword, Object salt) {
String encryptedPassword = super.encodePassword(originalPassword, salt); return encryptedPassword;
}
}
Как видно из исходного кода класса SuperAbstractBean, в проекте были использованы Spring - аннотации, а именно, для контроля механизма транзакций была использована аннотация Transactional, что позволило сократить количество исходного кода, увеличить его надежность и удобочитаемость. Для интеграции возможности
использования аннотаций в проекте был использован конфигурационный файл applicationContext.xml
Интеграция происходила путем внедрения зависимостей (Injection) в проект, ниже приводится пример конфигурационного файла:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www. springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context= "http://www. springframework.org/schema/context" xmlns:jee="http://www.springframe work.org/schema/je e"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3. O.xsd http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schemaftx/spring-tx-3.0.xsd'">
<context:property-placeholder location="classpath*:META-INF/spring/*.properties"/> <context:spring-configured/>
<context:component-scan base-package="ru.sniizhk.f24a">
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/> </context:component-scan>
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource"> <property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
<property name="testWhileIdle" value="true"/>
<property name="timeBetweenEvictionRunsMillis" value="1800000"/>
<property name="numTestsPerEvictionRun" value="3"/>
<property name="minEvictableIdleTimeMillis" value="1800000"/>
<property name="validationQuery" value= "SELECT 1"/>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref= "entityManagerFactory"/>
</bean>
<tx:annotation-driven mode= "aspectj" transaction-manager= "transactionManager"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="persistenceUnitName" value= "persistenceUnit"/>
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
Именно посредством этого файла происходит инициализация всего приложения. Spring указывает, с какого пакета начинать сканирование и компиляцию классов, далее подключается возможность использования аннотаций, устанавливаются настройки базы данных и параметры ее тестирования, определяется JPA-провайдер, включается поддержка аспектов.
С помощью применения предложенной конфигурации стало возможным разделить настроечный файл на два отдельных. А именно, persistence.xml, отвечающий за инициализацию JPA, и database.properties, позволяющий изменять параметры доступа к базе
данных. Данные манипуляции позволили производить быструю смену иРА-провайдера, а также смену СУБД.
Для организации процесса разграничений прав доступа к данным в разрезе районов была осуществлена выборка данных по Ю авторизированно пользователя. На рисунках 2-4 показаны примеры входа в систему под авторизированными аккаунтами пользователей, осуществляющими ввод данных в рамках различных районов Ставропольского края. Для улучшения пользовательского интерфейса
при входе показывается герб района.
Рисунок 2 - Вход в систему под идентификационными данными пользователя, имеющего доступ к информации в пределах
Александровского района Ставропольского края.
Рисунок 3 - Вход в систему под идентификационными данными пользователя, имеющего доступ к информации в пределах Шпаковского района Ставропольского края.
1 СЗ \@ ^-1
«- С 1 D Iocalhost:8090/f24a/ * =
SF MySQL Stored Funct... Новости науки И| Red Hat Linux 12 f\ MySQL database on ... ¡с] 15 Practical Usages... Д Tomcat - ArchWiki Q '/ Статья: "MySQL. Ие... Birt Щ Creating and using r... »
Поголовье Воспроизводство Продуктивность Осеменение животных Забой Падеж Производство продукции (реализация) Производство продукции (выращивание)
Благодарненский район
Рисунок 4 - Вход в систему под идентификационными данными пользователя, имеющего доступ к информации в пределах Благодарненского района Ставропольского края.
При общении с потенциальным заказчиком была установлена необходимость ведения классификатора предприятий, осуществляющих свою деятельность на определенном отрезке времени. На рисунке 5 представлена форма редактирования классификатора предприятий в рамках роли «Аналитик». _________
f М Входящие (121) - suppor * J Iocalhost:8090/f24a/ Ж sql delete - Поиск в ( Зоо * Т g? S0L DELETE Statement х Т W Delete fSOLl —Википед! x [ ,=, | @ |^-£W|
4r C D Iocalhost:8090/f24a/ * s
SP MySQL Stored Funct... Q- Новости науки Red Hat Linux7.2 ^ MySQL database on .. . Q0 15 Practical Usages... Tomcat-ArchWiki Q V Статья: "MySQL Ие... Ä Birt Д Creating and using r„. »
Поголовье | Воспроизводство | Продуктивность Осеменение Забой Падеж Производство продукции (выращивание) Производство продукции (реализация) Компании
Добавить |“5 Изменить
НАИМЕНОВАНИЕ ИНН ОГРН ДАТА ОТКРЫТИЯ ДАТА ЗАКРЫТИЯ
▼ Ставропольский край
тАлександровский район Я
'Колледж"
ЗАО МТС "Апексан-ское"
ОАО "Пятигоре. хУк"
ООО “Колос"
ООО "Надежда'
ООО 'Русь'
ООО "Садовое"
ООО "Северное"
ПНИ
СПК к-з "Копос"
СП К к-з им."Войтика"
СП К к-з* С еверное"
СПКА ПКЗ "Ставр-ский"
Крестьянские (фермерские) хозяйства
Личные подсобные хозяйства
тАндроповский район
ООО'АПККуршава
ООО "Каскад"
ООО "Прогресс"
ООО СХП' Дружба'
СПК (с-з)'Курсавский"
Крестьянские (фермерские) хозяйства
Личные подсобные хозяйства -
Рисунок 5 - Вход в систему под идентификационными данными пользователя, имеющего доступ к системе в рамках роли «Аналитик».
На рисунке 6 представлена форма управления пользователями, соответствующая правам «Администратора пользователей».
Рисунок 6 - Вход в систему под идентификационными данными пользователя, имеющего доступ к системе в рамках роли «Администратор пользователей».
Что касается расширения возможностей механизма логирования, предложенного ранее, было принято решение организации триггеров на основных редактируемых таблицах после событий insert и update. Однако использование триггера после события delete в нашем случае не потребовалось в связи с тем, что в соответствии с хорошим тоном программирования баз данных физическое удаление информации не происходит, она лишь скрывается и модифицируется.
Для хранения полного лога событий была создана отдельная таблица “log_dml”, скрипт которой представлен ниже:
CREATE TABLE 'log_dml' (
'id' BIGINT(20) NOT NULL,
'id_record' BIGINT(20) NOT NULL,
'id_table' VARCHAR(255) COLLATE utf8_general_ci NOT NULL,
'false_delete' BIT(1) DEFAULT NULL,
'user_createid' BIGINT(20) NOT NULL,
'user_createip' VARCHAR(255) COLLATE utf8_general_ci NOT NULL, 'user_create_time' DATETIME NOT NULL,
'user_create_esign' VARCHAR(7000) COLLATE utf8_general_ci DEFAULT NULL, 'user_deleteid' BIGINT(20) DEFAULT NULL,
'user_deleteip' VARCHAR(7000) COLLATE utf8_general_ci DEFAULT NULL, 'user_delete_time' DATETIME DEFAULT NULL,
'user_delete_esign' VARCHAR(3)COLLATE utf8_general_ci DEFAULT NULL, 'user_modifyid' BIGINT(20) DEFAULT NULL,
'user_modifyip' VARCHAR(255) COLLATE utf8_general_ci DEFAULT NULL, 'user_modify_time' DATETIME DEFAULT NULL,
user_ modify_esign' VARCHAR(7000) COLLATE utf8_general_ci DEFAULT NULL, 'version' INTEGER(11) DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=1 CHARACTER SET 'utf8' COLLATE
'utf8_general_ci';
ALTER TABLE 'log_dml' ADD PRIMARY KEY ('id');
ALTER TABLE 'log_dml' MODIFY COLUMN 'id' BIGINT(20) NOT NULL AUTO_INCREMENT.
Конечно, необходимо отметить, что поиск по такой таблице будет занимать достаточно много времени, так как она будет наиболее массивной, однако такие запросы будут осуществляться чрезвычайно редко в случаях обнаружения некорректного ввода данных, намеренного введения заблуждение и т.п., и то только в случае повторной модификации записи, что можно легко установить по полю “Version”.
Литература:
1. Абонеев, В.В. Методика оценки мясной продуктивности овец /В.В. Абонеев, Ю.Д. Квитко, И.И. Селькин и др. //Ставрополь, 2009. -34 с.
2. Абонеев, В.В. Стратегия развития овцеводства в Российской Федерации /В.В. Абонеев //Достижения науки и техники АПК. -2008.-№10. -С. 37-39.
3. Абонеев, В.В. Приемы и методы повышения конкурентоспособности товарного овцеводства /В.В. Абонеев, Л.Н. Скорых, Д.В. Абонеев //ГНУ СНИИЖК, Ставрополь. -2011. -337 с.
4. Абонеев, В.В. Перспективные направления селекции овец в условиях рыночной экономики /В.В.Абонеев, А.Н. Соколов //Овцы, козы, шерстяное дело. -2007. -№ 1. -С. 7-11.
5. Абонеев, В.В. Развитие тонкорунного овцеводства в России /В.В. Абонеев, В.В. Марченко, А.И. Суров, А.А. Пикалов, А.И. Ерохин, С.А. Карасев //Овцы. Козы. Шерстяное дело. - 2012. - № 2. - С. 6-13.
6. Василенко, В.Н. Племенная база овцеводства Ростовской области /В.Н.Василенко, Ю.А. Колосов //Зоотехния, 2002. -№8. -С.9-12.
7. Завгородняя, Г.В. Мясная продуктивность баранчиков разных генотипов и уровней кормления /Г.В. Завгородняя, Ю.Д. Квитко, И.И. Дмитрик, И.П. Будякова, И.Н. Шарко //Овцы. Козы. Шерстяное дело, 2012. -№2. -С.42-44.
8. Квитко, Ю.Д. Проблемы и новые подходы в организации производства баранины /Ю.Д. Квитко //Сборник научных трудов Ставропольского научно-исследовательского института животноводства и кормопроизводства. -2005. -Т.1.№2. -С. 3-7.
9. Квитко, Ю.Д. Мясная продуктивность и качество мяса молодняка овец разного происхождения /Ю.Д. Квитко, А.В. Скокова, С.Ф. Силкина //Овцы. Козы. Шерстяное дело. - 2012. -№ 2. -С. 39-41.
10. Ковалюк, Н. В. Молекулярно-биологические методы для оздоровления стад крупного рогатого скота от лейкоза //Ветеринария. -2008. -№2. -С. 22-26.
11. Ковалюк, Н.В. Методические рекомендации по использованию маркера BoLA DRB3 в селекционно-племенной работе с крупным рогатым скотом: Рекомендации СКНИИЖ. /Н.В.Ковалюк, В.Ф. Сацук //Краснодар, 2010. -24 с.
12. Ковалюк, Н.В. Использование генетического маркера BOLA-DRB3 для оптимизации селекционного процесса при скрещивании /Н.В.Ковалюк, В.Ф. Сацук //Молочное скотоводство.-2010.-№2.-С.10-12.
13. Ковалюк, Н.В. Современные методы диагностики лейкоза крупного рогатого скота /Н.В. Ковалюк, В.Ф. Сацук, Е.В. Мачульская //Вестник Кубани. -2007. -№ 1.
14. Колосов, Ю.А., Информационное сопровождение селекционного процесса в овцеводстве: учебное пособие /Ю.А.Колосов, А.И.Бараников,
В.Н.Василенко, Н.В. Михайлов //Изд-во Донского ГАУ, пос. Персиановский, 2012. -55 с.
15. Колосов, Ю.А. Продуктивность молодняка породы советский меринос и её помесей с эдильбаевскими баранами/Ю.А. Колосов, С.В. Шихов //Овцы, козы, шерстяное дело. -2006. -№ 3. -С.7-10.
16. Колосов, Ю.А. Модель организации селекционно-племенной работы в овцеводстве с применением метода зависимых уровней отбора /Ю.А. Колосов, И.В. Засемчук //Новочеркасск, 2008.-С.76.
17. Новопашина, С.И. Переваримость питательных веществ рациона молочными козами при разном уровне протеина /С.И. Новопашина, Ю.Д. Квитко, М.Ю. Санников, Е.И. Кизилова //Овцы. Козы. Шерстяное дело. -2012. - № 2. - С. 64-67.
18. Ольховская, Л. В. Иммуногенетический анализ в селекции коз /Л.В. Ольховская, Л.Н. Чижова и др. //Ставрополь. ВНИИОК. -2000. -С.3-11.
19. Тимошенко, Н.К. Состояние и перспективы развития первичной обработки шерсти /Н.К. Тимошенко //Овцы, козы, шерстяное дело. -2007. -№ 4. -С. 46-50.
20. Тимошенко Н.К. Рынок шерсти: состояние и тенденции развития. /Н.К. Тимошенко, В.В. Абонеев //Овцы, козы, шерстяное дело. -2012. -№
2. -С. 50.
21. Чижова, Л.Н. Биохимические тест-системы, генетические маркеры продуктивности, их использование в селекции овец /Л.Н. Чижова //Автореф. дисс.... д-ра с.-х. наук. -Ставрополь, 2004. -58 с.
22. Чижова, Л.Н. Методические рекомендации комплексной оценки крупного рогатого скота мясных пород по фенотипу и генотипу /Л.Н. Чижова и др. //Ставрополь, 2008. -52с.