Так мне и не удалось добраться до блога чтоб закончить предыдущий пост... Грустно, но что делать, такова жизнь=) Думаю все еще получится.
Вчера у начальства возникла необходимость чтобы при обращении к любым сайтам установленным на IIS осуществлялся редирект с http на https. Ну ладно, идея в конце-концов благая, правильная, а то до этого у нас месяц примерно клиенты попадали не на сайт, а в черную дыру, т.к. запросы по http просто никто не обрабатывал, не до того было. А вчера значит понадобилось, у меня сервак стоит, срочно запускать надо, а им нет жизни без редиректа. Ладно, проехали...
Вообще-то я уже пытался это сделать раньше, но мне не хватило терпенья, а когда начальство берет за... и требует сделать за час, в общем все как-то само получается.
В общем есть несколько способов.
Первый - запретить обращение к сайту не по https и вместо страницы 404.3 IIS'a повесить свою собственную страничку, которая будет редиректить клиента (описано например тут, там вообще-то для exchange, но схема приемлима для многих вариантов). Но тут я столкнулся с такой фигней, что моя 404.3 страница никак не хотела появляться вместо "родной". К тому же тут используется asp + vbs, а это скучно.
На основе этого решения я попытался сделать следующее. Вешаем на 80 порт сайт с default.asp примерно с таким кодом
<%
If Request.ServerVariables("SERVER_PORT")=80 Then
Dim strSecureURL
strSecureURL = "https://"
strSecureURL = strSecureURL & Request.ServerVariables("SERVER_NAME")
strSecureURL = strSecureURL & "/{NameOfSecureDirectory}"
Response.Redirect strSecureURL
End If
%>
Нов моем случае пришлось бы допиливать код, т.к. редиректило меня на https://hostname/default.asp а это неприемлемо.
В общем все это хорошо, но выглядит, честно говоря не очень.
Во время блужданий по интернету я набрел на такую статью на iis.net.
Вкратце - самописный модуль для IIS. Я раньше пытался использовать этот сценарий, но у меня не получилось т.к. я пытался поместить модуль непосредственно в приложение (в моем случае это SharePoint и CRM) и там запросы обрабатывались не так как надо. Например CRM отказывался проводить аутентификацию пользователей и т.п. Но впрочем это и не удивительно, лишнее доказательство что в случае с MS лучше не добавлять ничего самописного в их продукты.
Тогда я сделал отдельный каталог со следующим наполнением:
каталог App_Code c redir.cs
index.html просто пустой файл, дань традиции=)
web.config в котором указано использовать данный модуль.
На 80 порту висит сайт с этим каталогом, а на 443 - собственно продакшн сайт. Для того чтобы модуль нормально работал сайт с модулем должен быть запущен в Application Pool'е в Integrated Mode. Собственно код есть по ссылкам, приводить его тут не вижу смысла, так же как и выкладывать исходники. Если не прав - напишите.
31 января 2009
02 января 2009
asp.net + powershell
Нашел любопытный пост на Dev-Infra. Вкратце - запуск всеми любимого PowerShell с веб-страницы. Это может быть достаточно удобным в любой организации где администратор достаточно квалифицирован чтобы написать скрипт, а так же в любой организации где используется Exchange 2007 (правда я пока не нашел как прикрутить EMS, но думаю это дело времени=) ).
В общем-то дело достаточно простое. Что нам потребуется:
Windows SDK for Windows Server 2008 and .NET Framework 3.5
Visual Web Developer 2008 Express Edition
PowerShell на хостовой машине (где и как скачивать найдете и сами =) )
Механизм работы достаточно подробно описан на Dev-Infra. Что же касается конкретики... Например у меня ни на одной из машин (ни на домашней ни на рабочей) SDK не захотел интегрироваться в VWD Express Edition, так что пришлось добавлять Referenc'ы вручную (Add Reference на проекте и дальше добавляем все dll из C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0 ).
Вторые грабли с которыми я столкнулся - правильный вывод команд PowerShell. Т.к. мы получаем не стандартный вывод, а набор объектов, но после добавления следующей строчки:
pipe.Commands.Add("Out-String");
проблема решилась.
Последние грабли случились с IIS 7. Если запускать рабочий процесс в Integrated, а не в Classical mode AJAX работать у меня отказался. С IIS 5 (стоит на домашней машине), не было вообще никаких проблем.
И еще одно - PowerShell выполняется от имени того пользователя, под которым запущен процесс. Так что надо внимательно относиться к выбору пользователя от имени которого должны запускаться скрипты. И назначать ему соответствующие права.
Естественно код предоставляется без всяких гарантий и т.п. Разумеется доступ к этой странице (если вы решитесь ее использовать) следует строго ограничить.
Полный код aspx страницы выложен тут и я не вижу смысла на нем останавливаться.
А вот codebehind файл представляет больший интерес, поэтому его я выкладываю почти полностью. Во-первых потому что на Дев-Инфре он раскидан по всему посту, а во-вторых потому что он чуть-чуть отличается от оригинала.
Добавляем к стандартным пространствам имен следующие:
=====================================================
=====================================================
=====================================================
=====================================================
=====================================================
=====================================================
В общем в результате получаем работающий PS в браузере на нужной машине.
В общем осталось прикрутить Exchange и сделать обработчик ошибок, если сделаю (а я думаю что сделаю) и доберусь до блога (а вот с этим уже сложнее), то вывешу обновленный вариант и даже кину куда-нить полные исходники.
В общем-то дело достаточно простое. Что нам потребуется:
Windows SDK for Windows Server 2008 and .NET Framework 3.5
Visual Web Developer 2008 Express Edition
PowerShell на хостовой машине (где и как скачивать найдете и сами =) )
Механизм работы достаточно подробно описан на Dev-Infra. Что же касается конкретики... Например у меня ни на одной из машин (ни на домашней ни на рабочей) SDK не захотел интегрироваться в VWD Express Edition, так что пришлось добавлять Referenc'ы вручную (Add Reference на проекте и дальше добавляем все dll из C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0 ).
Вторые грабли с которыми я столкнулся - правильный вывод команд PowerShell. Т.к. мы получаем не стандартный вывод, а набор объектов, но после добавления следующей строчки:
pipe.Commands.Add("Out-String");
проблема решилась.
Последние грабли случились с IIS 7. Если запускать рабочий процесс в Integrated, а не в Classical mode AJAX работать у меня отказался. С IIS 5 (стоит на домашней машине), не было вообще никаких проблем.
И еще одно - PowerShell выполняется от имени того пользователя, под которым запущен процесс. Так что надо внимательно относиться к выбору пользователя от имени которого должны запускаться скрипты. И назначать ему соответствующие права.
Естественно код предоставляется без всяких гарантий и т.п. Разумеется доступ к этой странице (если вы решитесь ее использовать) следует строго ограничить.
Полный код aspx страницы выложен тут и я не вижу смысла на нем останавливаться.
А вот codebehind файл представляет больший интерес, поэтому его я выкладываю почти полностью. Во-первых потому что на Дев-Инфре он раскидан по всему посту, а во-вторых потому что он чуть-чуть отличается от оригинала.
Добавляем к стандартным пространствам имен следующие:
=====================================================
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.IO;
=====================================================
=====================================================
protected void BtnExecuteScript_Click(object sender, EventArgs e)
{
string strCurrentId = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
// Включаем таймер, блокируем кнопку, очищаем текстовое поле с прошлым результатом и сообщаем от кого выполняется скрипт
this.Timer1.Enabled = true;
this.BtnExecuteScript.Enabled = false;
this.TxtResult.Text = "";
Session["PowerTrace"] = "Выполняется от имени : " + strCurrentId + "\r\n";
// Получаем текст скрипта
string strContent = TxtPowerShellScript.Text;
// Преобразуем HTML в string и говорим выполниться скрипту с указанным текстом
StringWriter writer = new StringWriter();
Server.HtmlDecode(strContent, writer);
this.executePowerShellCode(strContent);
}
=====================================================
=====================================================
private void executePowerShellCode(string code)
{
// Открываем рабочее пространство, задаем строчку с кодом который необходимо выполнить и добавляем командлет который отдает не объекты, а строки, в общем приводим к привычному виду
runspace.Open();
pipe = runspace.CreatePipeline(code);
pipe.Commands.Add("Out-String");
// Закрываем ввод, добавляем обработчики событий и запускаем выполнение тела скрипта
pipe.Input.Close();
pipe.Output.DataReady += new EventHandler(Output_DataReady);
pipe.StateChanged += new EventHandler(pipe_StateChanged);
pipe.InvokeAsync();
}
void Output_DataReady(object sender, EventArgs e)
{
// Забираем объекты из вывода
PipelineReader reader = (PipelineReader)sender;
String strPowershellTrace = reader.Read().ToString();
Session["PowerTrace"] += strPowershellTrace + "\r\n";
}
void pipe_StateChanged(object sender, PipelineStateEventArgs e)
{
// Заканчиваем выполнение скрипта
if (pipe.PipelineStateInfo.State == PipelineState.Completed)
{
runspace.Close();
while ((Session["PowerTrace"] != null) && (Session["PowerTrace"].ToString().Length > 0))
{
}
Session.Remove("PowerTrace");
}
}
protected void Timer1_Tick(object sender, EventArgs e)
{
// Ну и наконец включаем КНОПКУ и сообщаем о конце выполнения скрипта
if (Session["PowerTrace"] == null)
{
this.BtnExecuteScript.Enabled = true;
Timer1.Enabled = false;
this.TxtResult.Text += "Конец скрипта";
}
else
{
String strPoshTrace = Session["PowerTrace"].ToString();
this.TxtResult.Text += strPoshTrace;
Session["PowerTrace"] = "";
}
}
=====================================================
В общем в результате получаем работающий PS в браузере на нужной машине.
В общем осталось прикрутить Exchange и сделать обработчик ошибок, если сделаю (а я думаю что сделаю) и доберусь до блога (а вот с этим уже сложнее), то вывешу обновленный вариант и даже кину куда-нить полные исходники.
Подписаться на:
Сообщения (Atom)