(Notes) Notes (2009 год)

CreateUserProfile - создание профиля Win-пользователя.

При написании ASP.NET Hosting panel создание профиля пользователя оказалось для меня наиболее сложным фрагментом. Никакого подобного описания в интернете я не нашел - поэтом следуя своей традиции, я решил опубликовать логику этого фрагмента.

Задача любого Shared-хостинга заключается в том, чтобы создать множество автономных пользователей, которые не могут повлиять на работу друг друга. В UNIX это совершенно тривиальная задача - просто создается пользователь и для него новый покаталог в каталоге USER.

В Windows это было бы тоже несложно, если бы дать разрешение на интерактивный логин пользователю Shared-хостинга. Для этого его еще бы пришлось включить в специальную группу (по умолчанию администраторы), которая имеет прав интерактивного логина. В технологии Shared-хостинга такие решения совершенно неприемлимы.

Понятно, что в Windows создание профиля пользователя не является просто копированием папки User Profile из Default User - как это происходит в UNIX. Ведь в Windows вместо текстовых .INI файлов для ускорения работы (и сохранения авторских прав на Windows за Microsoft'ом) введена иерархическая база данных - реестр. Что в точности и когда записывает WinLogon туда - является коммерческой тайной империи Била Гейтса и не документировано. Это приносит миллиарды империи Била Гейтса, но является фантастическим сдерживающим мотивом развития IT-индустрии, делая в Windows чрезвычано сложными решения самых обыкновенных для открытых систем задач.

Итак, для хостинг-панели мне нужно было бы своей прогой сделать в точности то, что делает Interactive Logon, но без вызова микрософтовских API. Манипуляции с реестром, выполняемые WinLogon являются собственность Билла Гейста и не документированы. Эти действия можно воспроизвести лишь предположительно. В любой момент Билл Гейтс может изменить по своему усмотрению эти правила и любой Hotfix превратит ваш труд и вашу программу в кучу мусора.

К сожалению, никаких средств для работы с профилями пользователей в Windows не существует вообще. Как-бы есть WMI-класс SELECT * FROM Win32_UserProfile, однако его можно добавить, похоже, только в Win2008 и Vista, да и то специальным отдельным хотфиксом. Единственное, что можно достаточно надежно делать с профилями в Windows - это удалять их утилитой Delprof.exe из пакета Windows Resource Kit. В остальном эти писаки удовлетворились полученным баблом и дописывать свои АПИ не стали (как и раскрывать написанное).

1.

Для начала нужно собственно создать пользователя. Сделать это можно множеством способов, например с помощью ADSI/WMI. Можно и так:

net user %1 %2 /add /scriptpath:users.bat

Здесь первый параметр - имя создаваемого пользователя, второй - пароль.

2.

Следующим этапом надо узнать SID созданного пользователя. Сделать это тоже можно множеством способов, например запросом SELECT * FROM Win32_UserAccount к WMI. Интерактивно в процессе тестов можно узнать вот таким ADSI-скриптом:

   1:  On Error Resume Next
   2:  strComputer = "."
   3:  Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
   4:  Set colItems = objWMIService.ExecQuery _
   5:      ("Select * from Win32_UserAccount Where LocalAccount = True")
   6:  For Each objItem in colItems
   7:      Wscript.Echo  objItem.Name & vbcrlf & "SID: " & objItem.SID
   8:  Next

Этот скрипт можно прогнать сразу если пользователей мало, а если много то нажимать OK все время утомительно. Тогда надо прогнать

cscript.exe /h:cscript
GetSid >1.txt

И получить все SID в текстовом файлике 1.txt.

3.

Следующий этап - скопировать дефолтный профиль в папку вновь созданного пользователя, например для пользователя "1" команда копирования будет выглядеть так:

xcopy "%systemdrive%\Documents and Settings\Default User\*.*" "%systemdrive%\Documents and Settings\1" /e /c /I /H /R /K /Y

произойдет копирование 40-50 файлов (для Win2003) профиля. Скопированный профиль будет иметь унаследованные разрешения от папки C:\Documents and Settings\

4.

Поэтому следущий этап - назначить правильно NTFS-права на профиль, чтобы Win-механизмы разграничения доступа отделяли данные одного пользователя от данных другого. Прописывать NTFS-права можно тоже многими способами. В составе Windows Support tools есть утилита Xcacls.exe, которой можно прописать access control lists (ACLs). Но она разная для разных Windows. Поэтому ее же можно сгрузить в виде WSH отсюда. Мне это решение нравится по трем причинам - это исходный скрипт, который идет под любым Windows, это хороший пример программирования на WSH и там в тексте есть чему поучиться. Кроме того, там есть русская документация.

Итак, снимем наследование и добавим разрешения на профиль нашего условного пользователя 1:

XCACLS "%systemdrive%\Documents and Settings\1" /I REMOVE /G System:F 1:F Администратор:F

5.

Насколько я понял логику микрософта - есть два отдельных места для хранения информации о профиле. Хотя, кажется, это не очень умно. Видимо эти фрагменты писались разными программистами в разное время. Я бы хранил информацию о профиле в одном месте. Но тем не менее посмотрим что там наковыряли горе-писаки из микрософта.

Первое место - HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList. Это важное место - именно здесь хранится соответствие имени папки профиля на диске с именем пользователя. В моем реальном хостинге, конечно, пользователь 1 не пишет в папку 1. Это соотношение произвольно и оно устанавливается в этом ключе реестра.

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

rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl

Поэтому этот ключ нам придется просто загрузить своей программой. Ручками это можно сдедать так - экспортировать любой имещийся ключ regedit->Export->as Reg или командой

reg export HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\S-1-5-21-991293091-3234348621-441160891-500 1.reg

В данном случае я экспортирировал ключ администратора (он завершается на 500). Затем нотепадом надо модифицировать этот ключ в трех местах - собственно имя (заменить в имени SID нашего вновь созданного пользователя), затем второе место - параметр SID это тот же SID, только в в бинарном виде и параметр ProfileImagePath - это путь с созданному нами ранее профилю на диске.

И загрузить модифицированный ключ командой

Reg import 1.reg

После этой манипуляции оснастке sysdm.cpl уже кажется, что это вполне нормальный профиль существующего пользователя.

6.

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

reg load "Win1\S-1-5-21-620741613-1291834151-3859767443-1016" "%USERPROFILE%\..\1\NTUSER.DAT"

Здесь в команде вы видите SID пользователя и путь к его личному ключу реестра NTUSER.DAT, расположенному в его личном профиле.



В приниципе на этом этапе пользователя (с личным профилем) уже можно считать созданным. C этого места можно начинать основное программирование хостинг-панели - создание Web-узлов, настройку их на работу в папках внутри профиля пользователя, создание FTP-узлов для удаленной загрузки сайта, создание SQL-пользователей и так далее. Теперь все операции хостинга, например раззиповывание бекапа перед загрузкой базы в SQL уже будут происходить в контексте пользователя с размещением Temp-файлов в созданном профиле пользователя.




Замечу, что выбранный мною путь - использование папки C:\Document ans Setting в качестве общего корня для всех пользователей - не единственный путь. Он дает многие преимущества (например можно использовать Win-аутентификацию при доступе к SQL), но можно начинать делать панель хостинга и из другого начального вектора. Можно начать от механизма работы FTP, которые предполагают совсем другой корень, общий для всех пользователей Shared-хостинга. Два альтернативных способа получить общий корень я описал тут - Настройка FTP-сервера (Isolated Ftp Site).



Комментарии к этой страничке ( )
ссылка на эту страничку: http://www.vb-net.ru/CreateUserProfile/index.htm
<Назад>  <На главную>  <В раздел ASP>  <В раздел NET>  <В раздел SQL>  <В раздел Разное>  <Написать автору>  < Поблагодарить>