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:cscriptGetSid >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 Администратор:F5.
Насколько я понял логику микрософта - есть два отдельных места для хранения информации о профиле. Хотя, кажется, это не очень умно. Видимо эти фрагменты писались разными программистами в разное время. Я бы хранил информацию о профиле в одном месте. Но тем не менее посмотрим что там наковыряли горе-писаки из микрософта.
Первое место - 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).
|