<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://pontonetpt.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Israel Aéce</title><link>http://pontonetpt.com/blogs/israelaece/default.aspx</link><description>Microsoft MVP, MCP, MCAD, MCTS, MCPD e MCT</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Projetando.NET não existe mais</title><link>http://pontonetpt.com/blogs/israelaece/archive/2009/04/22/P28989.aspx</link><pubDate>Wed, 22 Apr 2009 06:28:00 GMT</pubDate><guid isPermaLink="false">9d4b03f4-ce39-4703-ab9d-5b341a2c824e:946</guid><dc:creator>Israel Aéce</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://pontonetpt.com/blogs/israelaece/rsscomments.aspx?PostID=946</wfw:commentRss><comments>http://pontonetpt.com/blogs/israelaece/archive/2009/04/22/P28989.aspx#comments</comments><description>&lt;p align="justify"&gt;Há alguns anos eu mantenho um site chamado &lt;strong&gt;Projetando.NET&lt;/strong&gt;: &lt;a href="http://www.projetando.net"&gt;http://www.projetando.net&lt;/a&gt;. Além deste site, eu também mantenho um &lt;em&gt;blog&lt;/em&gt; na comunidade portuguesa &lt;a href="http://www.pontonetpt.com/tabid/36/default.aspx"&gt;PontoNetPt&lt;/a&gt;, que criei logo no ínicio da mesma. De acordo com as minhas regras, &lt;em&gt;posts&lt;/em&gt; que não rendem artigos eram publicados neste &lt;em&gt;blog&lt;/em&gt; e matérias maiores e mais detalhadas eu optava por publicá-los no Projetando.NET.&lt;br /&gt;&lt;br /&gt;Como eu não investi muito tempo no desenvolvimento do site do Projetando.NET, eu decidi então optar por uma solução pronta para a publicação e gerenciar os meus &lt;em&gt;posts&lt;/em&gt; e artigos, ao invés de evoluir o projeto atual. Com isso, eu resolvi criar um novo domínio que é &lt;a href="http://www.israelaece.com"&gt;http://www.israelaece.com&lt;/a&gt; e migrar todos os meus &lt;em&gt;posts&lt;/em&gt; deste &lt;em&gt;blog&lt;/em&gt; e também os artigos do site Projetando.NET para lá. Se tentar acessar o Projetando.NET, apenas terá uma página estática, informando que o site foi mudado para &lt;a href="http://www.israelaece.com"&gt;http://www.israelaece.com&lt;/a&gt;. Se estiver a procura de um artigo, consulte a opção de busca deste novo site e, se mesmo assim não encontrá-lo, &lt;a href="http://www.israelaece.com/contact.aspx"&gt;entre em contato comigo&lt;/a&gt; que poderia ajudá-lo. As minhas contas de e-mail &lt;a href="mailto:israel@projetando.net"&gt;israel@projetando.net&lt;/a&gt; e &lt;a href="mailto:contact@projetando.net"&gt;contact@projetando.net&lt;/a&gt; também deixam de existir. O meu novo e-mail agora passa a ser &lt;a href="mailto:ia@israelaece.com"&gt;ia@israelaece.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Peço também que atualizem o endereço de RSS, que agora passará a conter os &lt;em&gt;posts&lt;/em&gt; e artigos. O novo endereço é &lt;/strong&gt;&lt;a href="http://www.israelaece.com/syndication.axd"&gt;&lt;strong&gt;http://www.israelaece.com/syndication.axd&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;. &lt;/strong&gt;Para que fique claro, este novo site destina-se exclusivamente a publicação de conteúdo técnico e &lt;u&gt;não pessoal&lt;/u&gt;, como já acontecia antes.&lt;br /&gt;&lt;br /&gt;É importante ficar claro que estou deixando a PontoNetPt apenas por uma questão de comodidade. Em nenhum momento os integrantes deste time me deixaram sem suporte. A PontoNetPt continuará evoluindo, assim como o &lt;a href="http://weblogs.pontonetpt.com/nunogomes/"&gt;Nuno Gomes&lt;/a&gt; publicou &lt;a href="http://weblogs.pontonetpt.com/nunogomes/posts/28972.aspx"&gt;neste post&lt;/a&gt;. Quero publicamente agradecer ao time da PontoNetPt, mais precisamente ao &lt;a href="http://weblogs.pontonetpt.com/jpc/"&gt;João Paulo Carreiro&lt;/a&gt;, &lt;a href="http://weblogs.pontonetpt.com/rbfigueira/"&gt;Ricardo Figueira&lt;/a&gt;, &lt;a href="http://weblogs.pontonetpt.com/joaocardoso/"&gt;João Cardoso&lt;/a&gt;, &lt;a href="http://msmvps.com/blogs/luisabreu/"&gt;Luis Abreu&lt;/a&gt; e &lt;a href="http://weblogs.pontonetpt.com/pjmorgado/"&gt;Paulo Morgado&lt;/a&gt;, que sempre me ajudaram em tudo que precisei, tanto em relação ao meu &lt;em&gt;blog&lt;/em&gt; quanto em conselhos para a minha vida profissional.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://pontonetpt.com/aggbug.aspx?PostID=946" width="1" height="1"&gt;</description><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/Diversos/default.aspx">Diversos</category></item><item><title>Otimizando a compilação</title><link>http://pontonetpt.com/blogs/israelaece/archive/2009/04/16/P28981.aspx</link><pubDate>Thu, 16 Apr 2009 16:33:00 GMT</pubDate><guid isPermaLink="false">9d4b03f4-ce39-4703-ab9d-5b341a2c824e:945</guid><dc:creator>Israel Aéce</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://pontonetpt.com/blogs/israelaece/rsscomments.aspx?PostID=945</wfw:commentRss><comments>http://pontonetpt.com/blogs/israelaece/archive/2009/04/16/P28981.aspx#comments</comments><description>&lt;p align="justify"&gt;Quando fazemos alguma mudança no diretório bin, App_Code ou no arquivo Global.asax, toda a aplicação ASP.NET será recompilada. Para sites pequenos, isso não tem muitos problemas, já que não há muitos arquivos/recursos a serem compilados. Já quando temos um site com várias páginas, esse processo pode se tornar muito lento, principalmente na primeira requisição, que é o onde a compilação irá ocorrer.&lt;br /&gt;&lt;br /&gt;O SP1 do .NET Framework 3.5 inclui um novo atributo chamado &lt;em&gt;optimizeCompilations&lt;/em&gt;, dentro do elemento &lt;a href="http://msdn.microsoft.com/en-us/library/s10awwz0.aspx"&gt;compilation&lt;/a&gt;. Quando esse atributo estiver definido como &lt;em&gt;False &lt;/em&gt;(configuração padrão), qualquer mudança provocará a recompilação total do site; já quando voce, explicitamente, definí-lo como &lt;em&gt;True&lt;/em&gt;, somente os arquivos afetados pela mudança serão recompilados. Abaixo temos o exemplo da utilização deste novo atributo:&lt;br /&gt;&lt;br /&gt;&amp;lt;compilation optimizeCompilations=&amp;quot;true&amp;quot;&amp;gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://pontonetpt.com/aggbug.aspx?PostID=945" width="1" height="1"&gt;</description><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>WSDL com nome da máquina</title><link>http://pontonetpt.com/blogs/israelaece/archive/2009/04/15/P28974.aspx</link><pubDate>Wed, 15 Apr 2009 05:31:00 GMT</pubDate><guid isPermaLink="false">9d4b03f4-ce39-4703-ab9d-5b341a2c824e:944</guid><dc:creator>Israel Aéce</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://pontonetpt.com/blogs/israelaece/rsscomments.aspx?PostID=944</wfw:commentRss><comments>http://pontonetpt.com/blogs/israelaece/archive/2009/04/15/P28974.aspx#comments</comments><description>&lt;p align="justify"&gt;Quando publicamos um serviço WCF em um servidor, mais precisamente, dentro do IIS, é comum aparecer o nome da máquina no endereço de acesso ao documento que descreve o serviço (WSDL). Como se isso não bastasse, dentro do WSDL ainda existem diversos outros links, que também utilizam o nome da máquina para compor o endereço. Mas o correto seria aparecer o nome do domínio ou, até mesmo, o IP do servidor onde o serviço está hospedado.&lt;br /&gt;&lt;br /&gt;Isso ocorre porque o WCF utiliza as configurações do IIS (&lt;a href="http://weblogs.pontonetpt.com/israelaece/posts/28340.aspx"&gt;binding information&lt;/a&gt;) para determinar o &lt;em&gt;base address&lt;/em&gt; do serviço. Para resolver isso, podemos atualizar as configurações do IIS. Caso esteja utilizando o IIS 6.0, então pode adicionar um &lt;em&gt;host header&lt;/em&gt; customizado nas configurações do &lt;em&gt;Web Site&lt;/em&gt;, ou ainda, através do seguinte comando:&lt;br /&gt;&lt;br /&gt;C:\WINDOWS\system32\&amp;gt;cscript.exe %systemdrive%\inetpub\adminscripts\adsutil.vbs set w3svc/&amp;lt;&lt;em&gt;ID do Web Site&lt;/em&gt;&amp;gt;/ServerBindings &amp;quot;:80:www.dominio.com.br&amp;quot;&lt;br /&gt;&lt;br /&gt;Se estiver utilizando o IIS 7.0, pode recorrer a configuração do arquivo &lt;em&gt;applicationHost.config&lt;/em&gt;, assim como é mostrado abaixo:&lt;br /&gt;&lt;br /&gt;&amp;lt;bindings&amp;gt;&lt;br /&gt;  &amp;lt;binding protocol=&amp;quot;http&amp;quot; bindingInformation=&amp;quot;*:80:www.dominio.com.br&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/bindings&amp;gt;&lt;br /&gt;&lt;br /&gt;E, finalmente, se já estiver utilizando o .NET Framework 3.5 SP 1, então pode utilizar o elemento &lt;em&gt;baseAddressPrefixFilters&lt;/em&gt;, assim como é mostrado &lt;a href="http://weblogs.pontonetpt.com/israelaece/posts/28340.aspx"&gt;neste post&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://pontonetpt.com/aggbug.aspx?PostID=944" width="1" height="1"&gt;</description><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/WCF/default.aspx">WCF</category></item><item><title>Strong Name Bypass</title><link>http://pontonetpt.com/blogs/israelaece/archive/2009/03/31/P28954.aspx</link><pubDate>Tue, 31 Mar 2009 17:03:00 GMT</pubDate><guid isPermaLink="false">9d4b03f4-ce39-4703-ab9d-5b341a2c824e:943</guid><dc:creator>Israel Aéce</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://pontonetpt.com/blogs/israelaece/rsscomments.aspx?PostID=943</wfw:commentRss><comments>http://pontonetpt.com/blogs/israelaece/archive/2009/03/31/P28954.aspx#comments</comments><description>&lt;p align="justify"&gt;Um dos passos necessários durante a carga do &lt;em&gt;Assembly&lt;/em&gt; é análise da assinatura do &lt;em&gt;Strong Name&lt;/em&gt;. Independentemente do &lt;a href="http://www.projetando.net/Sections/Articles/77/Chapters/Chapter09.xps"&gt;Code Access Security&lt;/a&gt;, essa análise sempre é realizada e muitas aplicações pagam esse preço sem ao menos utilizá-lo. A partir do SP1 do .NET Framework 3.5, a Microsoft incluiu uma funcionalidade chamada de &lt;em&gt;Strong Name Bypass&lt;/em&gt;, não mais fazendo essa verificação e, consequentemente, tendo um ganho de performance durante a sua inicialização.&lt;br /&gt;&lt;br /&gt;Essa análise não será mais realizada para &lt;em&gt;Assemblies&lt;/em&gt; que são carregados em um ambiente &lt;em&gt;full-trusted&lt;/em&gt;. Obviamente que essa análise acontecerá quando, para computar a segurança, voce levar em consideração o &lt;em&gt;Strong Name&lt;/em&gt;. Se, por algum motivo, voce quiser reabilitar a verificação, então pode recorrer ao elemento &lt;em&gt;bypassTrustedAppStrongNames&lt;/em&gt;, definindo o atributo &lt;em&gt;enabled&lt;/em&gt; para &lt;em&gt;false&lt;/em&gt;, assim como é mostrado abaixo, utilizando o arquivo de configuração:&lt;br /&gt;&lt;br /&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;    &amp;lt;runtime&amp;gt;&lt;br /&gt;        &amp;lt;bypassTrustedAppStrongNames enabled=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;/runtime&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://pontonetpt.com/aggbug.aspx?PostID=943" width="1" height="1"&gt;</description><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/.NET+Framework/default.aspx">.NET Framework</category><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/Security/default.aspx">Security</category></item><item><title>Core Services no ASP.NET 4.0</title><link>http://pontonetpt.com/blogs/israelaece/archive/2009/03/24/P28931.aspx</link><pubDate>Tue, 24 Mar 2009 17:28:00 GMT</pubDate><guid isPermaLink="false">9d4b03f4-ce39-4703-ab9d-5b341a2c824e:942</guid><dc:creator>Israel Aéce</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://pontonetpt.com/blogs/israelaece/rsscomments.aspx?PostID=942</wfw:commentRss><comments>http://pontonetpt.com/blogs/israelaece/archive/2009/03/24/P28931.aspx#comments</comments><description>&lt;p align="justify"&gt;Além de algumas novidades que já foram reportadas &lt;a href="http://weblogs.pontonetpt.com/israelaece/posts/28353.aspx"&gt;neste post&lt;/a&gt;, o ASP.NET 4.0 trará ainda uma série de funcionalidades muito interessantes e, entre elas, teremos:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;OutputCaching Extensível&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Quando utilizamos o &lt;a href="http://msdn.microsoft.com/en-us/library/hdxfb6cy.aspx"&gt;OutputCaching&lt;/a&gt; em uma página, a primeira requisição a executará, e antes de devolver o conteúdo para o cliente, o resultado é armazenado na memória do servidor Web, e com isso, futuras requisições utilizarão esse conteúdo ao invés de reprocessar a página completamente. O ASP.NET 4.0 fornece uma forma altamente flexível para conseguirmos customizar o repositório de &lt;em&gt;caching&lt;/em&gt; trabalhando com &lt;em&gt;providers&lt;/em&gt;, assim como já acontece nas principais funcionalidades do ASP.NET atual.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Auto-Start de Aplicações&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Todos sabemos que as aplicações ASP.NET tem um &lt;em&gt;delay&lt;/em&gt; na primeira requisição, que se deve ao fato de efetuar a compilação da mesma. A partir do ASP.NET 4.0, em conjunto com o IIS 7.5, teremos uma funcionalidade chamada de &lt;em&gt;auto-start&lt;/em&gt;. Ao configurar esta funcionalidade em uma aplicação, o IIS enviará uma mensagem ao ASP.NET para que a sua aplicação faça o processo necessário para deixá-la pronta para ser consumida. Tudo isso ocorre no momento em que o IIS/AppPool ainda não aceita requisições.&lt;br /&gt;&lt;br /&gt;O mais interessante é que ainda podemos interceptar este evento, implementando o método &lt;em&gt;Preload&lt;/em&gt; da &lt;em&gt;Interface&lt;/em&gt; &lt;em&gt;IProcessHostPreloadClient&lt;/em&gt;. Nele podemos fazer outras &amp;quot;pré-inicializações&amp;quot; que antes eram feitas sob demanda.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Redirecionamento Permanente&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Como já &lt;a href="http://weblogs.pontonetpt.com/israelaece/posts/28556.aspx"&gt;comentado aqui&lt;/a&gt;, agora teremos um método chamado &lt;em&gt;RedirectPermanent&lt;/em&gt; que efetuará esse tipo de redirecionamento.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Compressão das variáveis de Sessão&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Quando utilizamos variáveis de sessão, elas são armazenadas na memória do servidor onde a aplicação está sendo executada (&lt;em&gt;In-Process&lt;/em&gt;). Além disso, temos duas outras possibilidades que é o armazenamento diretamente no SQL Server ou um servidor exclusivo para o armazenamento das variáveis sessão (&lt;em&gt;Out-of-Process&lt;/em&gt;). Nestas duas últimas opções, há um &lt;em&gt;overhead&lt;/em&gt; extra, que ocorre justamente porque o objeto responsável que armazena as informações, deverá ser serializado antes de enviado para o destino remoto.&lt;br /&gt;&lt;br /&gt;Dependendo do que é armazenado dentro das variáveis de sessão, esse processo pode custar muito caro, tanto em termos de comunicação quanto em termos de memória ou espaço físico. A partir do ASP.NET 4.0, o elemento &lt;a href="http://msdn.microsoft.com/en-us/library/h6bb9cz9(VS.71).aspx"&gt;sessionState&lt;/a&gt; irá possuir um novo atributo chamado &lt;em&gt;compressionEnabled&lt;/em&gt;. Ao definí-lo como &lt;em&gt;True&lt;/em&gt;, o ASP.NET fará o processo necessário para comprimir e descomprimir os dados, utilizando a classe &lt;a href="http://msdn.microsoft.com/en-us/library/system.io.compression.gzipstream.aspx"&gt;GZipStream&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Para aqueles que quiserem mais informações sobre as novas funcionalidades, consulte &lt;a href="http://www.asp.net/learn/whitepapers/aspnet40/"&gt;este documento&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://pontonetpt.com/aggbug.aspx?PostID=942" width="1" height="1"&gt;</description><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>Configurando o limite de conexões pendentes</title><link>http://pontonetpt.com/blogs/israelaece/archive/2009/03/24/P28930.aspx</link><pubDate>Tue, 24 Mar 2009 07:31:00 GMT</pubDate><guid isPermaLink="false">9d4b03f4-ce39-4703-ab9d-5b341a2c824e:941</guid><dc:creator>Israel Aéce</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://pontonetpt.com/blogs/israelaece/rsscomments.aspx?PostID=941</wfw:commentRss><comments>http://pontonetpt.com/blogs/israelaece/archive/2009/03/24/P28930.aspx#comments</comments><description>&lt;p align="justify"&gt;Quando expomos um serviço através do &lt;em&gt;binding&lt;/em&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.nettcpbinding.aspx"&gt;NetTcpBinding&lt;/a&gt;, as requisições que chegam até ele, são processadas e, finalmente o retorno é enviado para o respectivo cliente. As mensagens que chegam são processadas no formato FIFO (&lt;em&gt;first-in, first out&lt;/em&gt;), ou seja, elas aguardam o processamento em uma fila e, sob demanda, são encaminhadas para o processamento.&lt;br /&gt;&lt;br /&gt;Se a velocidade do processamento da mensagem é mais lenta que a velocidade de envio das mensagens, essa fila pode aumentar. Por padrão o &lt;em&gt;binding NetTcpBinding&lt;/em&gt; limita, através da propriedade &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.nettcpbinding.listenbacklog.aspx"&gt;ListenBacklog&lt;/a&gt;, o número de requisições pendentes que podem ser enfileiradas. O valor padrão é 10 e, dependendo da quantidade de requisições que chegam para o serviço, esse limite pode exceder e, a seguinte exceção será disparada:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;font color="#ff0000"&gt;System.ServiceModel.EndpointNotFoundException: Could not connect to net.tcp://localhost:8879/srv. The connection attempt lasted for a time span of 00:00:02.1404880. TCP error code 10061: No connection could be made because the target machine actively refused it 127.0.0.1:8879.  ---&amp;gt; System.Net.Sockets.SocketException:No connection could be made because the target machine actively refused it 127.0.0.1:8879&lt;/font&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;A alternativa aqui é aumentar esse número, definindo um valor próximo a quantidade das conexões simultaneas que eventualmente podem chegar para o serviço. O exemplo abaixo ilustra a configuração desta propriedade no &lt;em&gt;binding NetTcpBinding&lt;/em&gt;:&lt;br /&gt;&lt;br /&gt;host.AddServiceEndpoint(&lt;font color="#0000ff"&gt;typeof&lt;/font&gt;(IContrato), &lt;font color="#0000ff"&gt;new&lt;/font&gt; NetTcpBinding() { ListenBacklog = 70 }, &amp;quot;srv&amp;quot;);&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://pontonetpt.com/aggbug.aspx?PostID=941" width="1" height="1"&gt;</description><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/CSD/default.aspx">CSD</category><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/WCF/default.aspx">WCF</category></item><item><title>Serialização de Propriedades Automáticas</title><link>http://pontonetpt.com/blogs/israelaece/archive/2009/03/17/P28905.aspx</link><pubDate>Tue, 17 Mar 2009 20:39:00 GMT</pubDate><guid isPermaLink="false">9d4b03f4-ce39-4703-ab9d-5b341a2c824e:940</guid><dc:creator>Israel Aéce</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://pontonetpt.com/blogs/israelaece/rsscomments.aspx?PostID=940</wfw:commentRss><comments>http://pontonetpt.com/blogs/israelaece/archive/2009/03/17/P28905.aspx#comments</comments><description>&lt;p align="justify"&gt;Quando queremos expor uma propriedade, na maioria das vezes existe um campo privado que serve como &amp;quot;repositório&amp;quot; para a informação que é definida ou lida. A propriedade tem o papel de interceptar a leitura e escrita à este campo privado através de blocos &lt;em&gt;get/set&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Para reduzir o trabalho, a partir da versão 3.0 do C#, é disponibilizado uma funcionalidade chamada de &lt;a href="http://msdn.microsoft.com/en-us/library/bb384054.aspx"&gt;Automatic Properties&lt;/a&gt; que, por sua vez, nos permite omitir a criação deste campo privado. Na realidade, essa funcionalidade nada mais é do que &lt;a href="http://en.wikipedia.org/wiki/Syntactic_sugar"&gt;&amp;quot;açúcar sintático&amp;quot;&lt;/a&gt;, já que no momento da compilação, o C# irá injetar o campo privado para armazenar a informação que a propriedade expõe. Como exemplo, imagine que voce cria uma classe com a seguinte definição:&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;public class&lt;/font&gt; Usuario&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#0000ff"&gt;public string&lt;/font&gt; Nome { &lt;font color="#0000ff"&gt;get&lt;/font&gt;; &lt;font color="#0000ff"&gt;set&lt;/font&gt;; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;No momento da compilação, ela será definida como:&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;public class&lt;/font&gt; Usuario&lt;br /&gt;{&lt;br /&gt;    [CompilerGenerated]&lt;br /&gt;    &lt;font color="#0000ff"&gt;private string&lt;/font&gt; &amp;lt;Nome&amp;gt;k__BackingField;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#0000ff"&gt;public string&lt;/font&gt; Nome&lt;br /&gt;    {&lt;br /&gt;        [CompilerGenerated]&lt;br /&gt;        &lt;font color="#0000ff"&gt;get&lt;/font&gt;&lt;br /&gt;        {&lt;br /&gt;            &lt;font color="#0000ff"&gt;return this&lt;/font&gt;.&amp;lt;Nome&amp;gt;k__BackingField;&lt;br /&gt;        }&lt;br /&gt;        [CompilerGenerated]&lt;br /&gt;        &lt;font color="#0000ff"&gt;set&lt;/font&gt;&lt;br /&gt;        {&lt;br /&gt;            &lt;font color="#0000ff"&gt;this&lt;/font&gt;.&amp;lt;Nome&amp;gt;k__BackingField = &lt;font color="#0000ff"&gt;value&lt;/font&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Já vi alguns casos em que esses objetos que fazem uso desta técnica, são marcados com o atributo &lt;a href="http://msdn.microsoft.com/en-us/library/system.serializableattribute.aspx"&gt;SerializableAttribute&lt;/a&gt; e, como o próprio atributo indica, permitir a serialização do mesmo. Quando um objeto com essas características são expostos através de serviços WCF (talvez quando voce já possuir uma API com essas classes definidas), precisamos de alguns cuidados especiais.&lt;br /&gt;&lt;br /&gt;O serializador padrão do WCF é o &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx"&gt;DataContractSerializer&lt;/a&gt;. Esse serializador trabalha em conjunto com os atributos &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx"&gt;DataContractAttribute&lt;/a&gt; e &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute.aspx"&gt;DataMemberAttribute&lt;/a&gt;, serializando as propriedades ou campos públicos que são decorados com um desses dois atributos. Esse serializador também suporta classes decoradas com o atributo &lt;em&gt;SerializableAttribute&lt;/em&gt; mas, como esse atributo foi desenhado para persistir e reconstituir na íntegra a representação do objeto, todos os campos (privados ou públicos) são serializados. As propriedades aqui são ignoradas.&lt;br /&gt;&lt;br /&gt;Ao submeter um objeto com as características que vimos acima para o serializador padrão do WCF, ele persistirá os campos privados, que no nosso caso é o &lt;em&gt;&amp;lt;Nome&amp;gt;k__BackingField&lt;/em&gt;, e que na maioria dos casos, não é isso que desejamos. Como exemplo, podemos utilizar o seguinte código para analisar o resultado deste processo:&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt; DataContractSerializer(&lt;font color="#0000ff"&gt;typeof&lt;/font&gt;(Usuario))&lt;br /&gt;    .WriteObject(&lt;br /&gt;        File.Create(&amp;quot;Usuario.xml&amp;quot;),&lt;br /&gt;        &lt;font color="#0000ff"&gt;new&lt;/font&gt; Usuario() { Nome = &amp;quot;Israel&amp;quot; });&lt;br /&gt;&lt;br /&gt;Abaixo temos conteúdo Xml correspondente:&lt;br /&gt;&lt;br /&gt;&amp;lt;Usuario xmlns=&amp;quot;...&amp;quot; xmlns:i=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;_x003C_Nome_x003E_k__BackingField&amp;gt;Israel&amp;lt;/_x003C_Nome_x003E_k__BackingField&amp;gt;&lt;br /&gt;&amp;lt;/Usuario&amp;gt;&lt;br /&gt;&lt;br /&gt;Caso voce não possa alterar os atributos que já foram definidos para a classe, uma possibilidade que temos é utilizar o serializador &lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx"&gt;XmlSerializer&lt;/a&gt;. Ao contrário do &lt;em&gt;DataContractSerializer&lt;/em&gt;, esta classe irá serializar somente as propriedades ou campos públicos. Assim como o exemplo acima, para efetuarmos este teste, podemos utilizar o seguinte código:&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt; XmlSerializer(&lt;font color="#0000ff"&gt;typeof&lt;/font&gt;(Usuario))&lt;br /&gt;    .Serialize(&lt;br /&gt;        File.Create(&amp;quot;Usuario.xml&amp;quot;),&lt;br /&gt;        &lt;font color="#0000ff"&gt;new&lt;/font&gt; Usuario() { Nome = &amp;quot;Israel&amp;quot; });&lt;br /&gt;&lt;br /&gt;E, finalmente, o resultado em Xml:&lt;br /&gt;&lt;br /&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;Usuario xmlns:xsi=&amp;quot;...&amp;quot; xmlns:xsd=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;Nome&amp;gt;Israel&amp;lt;/Nome&amp;gt;&lt;br /&gt;&amp;lt;/Usuario&amp;gt;&lt;br /&gt;&lt;br /&gt;O XmlSerializer é utilizado também pelo ASP.NET Web Services (ASMX). Por mais que esta técnica funcione, antes de alterar o serializador padrão do WCF, é importante que voce analise as vantagens e desvantagens da sua utilização e, para isso, poderá recorrer à &lt;a href="http://msdn.microsoft.com/en-us/library/ms733901.aspx"&gt;própria documentação&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://pontonetpt.com/aggbug.aspx?PostID=940" width="1" height="1"&gt;</description><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/CSD/default.aspx">CSD</category><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/WCF/default.aspx">WCF</category></item><item><title>ASP.NET Development Server parou de funcionar</title><link>http://pontonetpt.com/blogs/israelaece/archive/2009/03/14/P28890.aspx</link><pubDate>Sat, 14 Mar 2009 02:45:00 GMT</pubDate><guid isPermaLink="false">9d4b03f4-ce39-4703-ab9d-5b341a2c824e:939</guid><dc:creator>Israel Aéce</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://pontonetpt.com/blogs/israelaece/rsscomments.aspx?PostID=939</wfw:commentRss><comments>http://pontonetpt.com/blogs/israelaece/archive/2009/03/14/P28890.aspx#comments</comments><description>&lt;p align="justify"&gt;Com a instalação &lt;a href="http://www.microsoft.com/security/portal/Entry.aspx?name=SettingsModifier:Win32/PossibleHostsFileHijack&amp;amp;threatid=1758608427027806866"&gt;de uma atualização&lt;/a&gt; que a Microsoft lliberou, o arquivo &lt;em&gt;hosts&lt;/em&gt; (&lt;em&gt;C:\Windows\System32\drivers\etc&lt;/em&gt;) pode ter sido alterado, removendo a entrada que tem o apontamento do IP 127.0.0.1 para &lt;em&gt;localhost&lt;/em&gt;, fazendo com que os projetos ASP.NET que usam o servidor interno do Visual Studio .NET para hospedar as aplicações deixem de funcionar. Com isso, ao rodar essas aplicações, voce receberá a seguinte mensagem: &lt;em&gt;&amp;quot;Internet Explorer cannot display the webpage&amp;quot;&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Como já era de se esperar, basta readicionar esta linha no arquivo para que tudo volte ao normal, assim como é mostrado abaixo:&lt;br /&gt;&lt;br /&gt;127.0.0.1       localhost&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://pontonetpt.com/aggbug.aspx?PostID=939" width="1" height="1"&gt;</description><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/Security/default.aspx">Security</category></item><item><title>Compartilhando portas através do protocolo TCP</title><link>http://pontonetpt.com/blogs/israelaece/archive/2009/03/13/P28889.aspx</link><pubDate>Fri, 13 Mar 2009 18:46:00 GMT</pubDate><guid isPermaLink="false">9d4b03f4-ce39-4703-ab9d-5b341a2c824e:938</guid><dc:creator>Israel Aéce</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://pontonetpt.com/blogs/israelaece/rsscomments.aspx?PostID=938</wfw:commentRss><comments>http://pontonetpt.com/blogs/israelaece/archive/2009/03/13/P28889.aspx#comments</comments><description>&lt;p align="justify"&gt;Ao criar um serviço WCF, podemos disponibilizá-lo através do protocolo TCP (&lt;em&gt;net.tcp&lt;/em&gt;), utilizando uma porta específica. Uma vez que voce publica esse serviço, nenhum outro serviço naquela mesma máquina poderá utilizar aquela porta ao mesmo tempo, e se fizer isso, uma exceção do tipo &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.addressalreadyinuseexception.aspx"&gt;AddressAlreadyInUseException&lt;/a&gt; será disparada exibindo a seguinte mensagem: &lt;font color="#ff0000"&gt;&lt;em&gt;There is already a listener on IP endpoint [MachineName]:[Port].  Make sure that you are not trying to use this endpoint multiple times in your application and that there are no other applications listening on this endpoint&lt;/em&gt;&lt;/font&gt;.&lt;br /&gt;&lt;br /&gt;Podemos não perceber mas o Windows permite o compartilhamento de uma mesma porta TCP para expor múltiplas aplicações. Um exemplo disso é o HTTP, que permite múltiplas aplicações estarem acessíveis através da porta 80 do protocolo TCP. Isso é possível graças à um &lt;em&gt;listener&lt;/em&gt; (&lt;em&gt;HTTP.SYS&lt;/em&gt;) que o IIS possue e que, baseando-se no conteúdo da mensagem, encaminha a requisição para a aplicação correspondente processá-la.&lt;br /&gt;&lt;br /&gt;Ao instalar o .NET Framework, um serviço chamado &lt;em&gt;Net.Tcp Port Sharing Service&lt;/em&gt; é instalado no Windows, dando a possibilidade de múltiplos serviços WCF compartilharem a mesma porta TCP, assim como o HTTP. Esse serviço (hospedado através do processo &lt;strong&gt;SMSvcHost.exe&lt;/strong&gt; (&lt;em&gt;C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation&lt;/em&gt;)) tem a finalidade de inspecionar a mensagem, extrair o endereço de destino, e baseando-se nele, encaminhar a requisição para a aplicação que a processará.&lt;br /&gt;&lt;br /&gt;Além deste serviço funcionando, ainda é necessário uma pequena configuração no código que expõe serviço WCF. O &lt;em&gt;binding&lt;/em&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.nettcpbinding.aspx"&gt;NetTcpBinding&lt;/a&gt; possui uma propriedade booleana chamada &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.nettcpbinding.portsharingenabled.aspx"&gt;PortSharingEnabled&lt;/a&gt; que, por padrão, é definida como &lt;em&gt;False&lt;/em&gt;. Voce deverá definí-la como &lt;em&gt;True&lt;/em&gt; para todos os serviços que desejarem compartilhar uma porta TCP específica. Ao fazer isso, o WCF se encarrega de iniciar automaticamente o serviço &lt;em&gt;Net.Tcp Port Sharing Service&lt;/em&gt;, mas voce pode fazer isso manualmente, ou ainda alterar a configuração do serviço para ele ser inciado automaticamente quando o sistema operacional entrar no ar. O trecho de código abaixo ilustra como podemos proceder para configurar o &lt;em&gt;endpoint&lt;/em&gt; com o &lt;em&gt;binding&lt;/em&gt; e habilitando o compartilhamento da porta TCP:&lt;br /&gt;&lt;br /&gt;host.AddServiceEndpoint(&lt;br /&gt;    &lt;font color="#0000ff"&gt;typeof&lt;/font&gt;(IContrato), &lt;br /&gt;    &lt;font color="#0000ff"&gt;new&lt;/font&gt; NetTcpBinding() { PortSharingEnabled = &lt;font color="#0000ff"&gt;true&lt;/font&gt; }, &lt;br /&gt;    &lt;font color="#0000ff"&gt;new&lt;/font&gt; Uri(&amp;quot;net.tcp://localhost:7373/NomeDoServico/Cadastro&amp;quot;));&lt;br /&gt;&lt;br /&gt;Como os serviços irão compartilhar a mesma porta, a distinção da aplicação é determinada pela URI como um todo, ou seja, o que vem depois da porta na URI do serviço precisa ser diferente entre os serviços, caso contrário voce terá o mesmo problema que antes.&lt;br /&gt;&lt;br /&gt;Com esta técnica, vamos permitir múltiplas aplicações coexistirem fisicamente na mesma máquina, mas em processos separados, compartilhando a mesma infraestrutura de rede, melhorando a segurança, já que podemos diminiur a superfície de ataque não exigindo a abertura de portas no &lt;em&gt;firewall&lt;/em&gt; de forma aleatória.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://pontonetpt.com/aggbug.aspx?PostID=938" width="1" height="1"&gt;</description><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/CSD/default.aspx">CSD</category><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/WCF/default.aspx">WCF</category></item><item><title>Melhorando a performance no ThreadPool</title><link>http://pontonetpt.com/blogs/israelaece/archive/2009/03/11/P28880.aspx</link><pubDate>Wed, 11 Mar 2009 06:16:00 GMT</pubDate><guid isPermaLink="false">9d4b03f4-ce39-4703-ab9d-5b341a2c824e:937</guid><dc:creator>Israel Aéce</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://pontonetpt.com/blogs/israelaece/rsscomments.aspx?PostID=937</wfw:commentRss><comments>http://pontonetpt.com/blogs/israelaece/archive/2009/03/11/P28880.aspx#comments</comments><description>&lt;p align="justify"&gt;Como já sabemos, a classe &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx"&gt;ThreadPool&lt;/a&gt; disponibiliza um repositório de &lt;em&gt;threads&lt;/em&gt; que podemos utilizar em nossas aplicações, delegando a ela uma tarefa para ser executada através de um &lt;em&gt;delegate&lt;/em&gt;. Para isso, é muito comum utilizarmos o método &lt;a href="http://msdn.microsoft.com/en-us/library/kbf0f1ct.aspx"&gt;QueueUserWorkItem&lt;/a&gt; para enfileirar uma nova tarefa. O exemplo abaixo ilustra a sua utilização em uma aplicação qualquer:&lt;br /&gt;&lt;br /&gt;ThreadPool.QueueUserWorkItem(state =&amp;gt;&lt;br /&gt;{&lt;br /&gt;    Console.WriteLine(&lt;font color="#0000ff"&gt;new&lt;/font&gt; StreamReader(@&amp;quot;C:\Temp\Arquivo.txt&amp;quot;).ReadToEnd());&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;Quando utilizamos o método &lt;em&gt;QueueUserWorkItem&lt;/em&gt;, antes de enfileirar a tarefa a ser executada, ele captura todas as permissões que foram concedidas e, antes de executá-la, essas permissões são aplicadas a &lt;em&gt;thread&lt;/em&gt; que está associada à tarefa. Com isso, se a tarefa que voce está tentando executar de forma assíncrona exigir alguma permissão e ela não foi concedida, uma exceção do tipo &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.securityexception.aspx"&gt;SecurityException&lt;/a&gt; será disparada. Podemos notar esse comportamento com o seguinte código:&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt; FileIOPermission(FileIOPermissionAccess.Read, @&amp;quot;C:\Temp\Arquivo.txt&amp;quot;).Deny();&lt;br /&gt;&lt;br /&gt;ThreadPool.QueueUserWorkItem(state =&amp;gt;&lt;br /&gt;{&lt;br /&gt;    Console.WriteLine(&lt;font color="#0000ff"&gt;new&lt;/font&gt; StreamReader(@&amp;quot;C:\Temp\Arquivo.txt&amp;quot;).ReadToEnd());&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;No código acima, a aplicação não possui permissão de acesso ao arquivo, e ao executar o método &lt;em&gt;QueueUserWorkItem&lt;/em&gt;, a tarefa vinculada também não conseguirá executar a leitura do arquivo, disparando uma exceção. Por menor que seja, utilizar este método sempre tem o &lt;em&gt;overhead&lt;/em&gt; para a cópia das permissões atuais e associá-las a &lt;em&gt;thread&lt;/em&gt; responsável pela tarefa, para que ela execute no mesmo contexto de segurança.&lt;br /&gt;&lt;br /&gt;É justamente neste ponto que entra em cena o método &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.threadpool.unsafequeueuserworkitem.aspx"&gt;UnsafeQueueUserWorkItem&lt;/a&gt;, também da classe &lt;em&gt;ThreadPool&lt;/em&gt;. Ao contrário do método &lt;em&gt;QueueUserWorkItem&lt;/em&gt;, ele não propaga as permissões para a &lt;em&gt;worker thread&lt;/em&gt;, diminuindo o trabalho a ser realizado quando voce enfileira uma nova tarefa ao &lt;em&gt;ThreadPool&lt;/em&gt;. A utilização em relação ao que vimos acima muda ligeiramente:&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt; FileIOPermission(FileIOPermissionAccess.Read, @&amp;quot;C:\Temp\Arquivo.txt&amp;quot;).Deny();&lt;br /&gt;&lt;br /&gt;ThreadPool.UnsafeQueueUserWorkItem(state =&amp;gt;&lt;br /&gt;{&lt;br /&gt;    Console.WriteLine(&lt;font color="#0000ff"&gt;new&lt;/font&gt; StreamReader(@&amp;quot;C:\Temp\Arquivo.txt&amp;quot;).ReadToEnd());&lt;br /&gt;}, &lt;font color="#0000ff"&gt;null&lt;/font&gt;);&lt;br /&gt;&lt;br /&gt;Como as permissões não são propagadas e avaliadas com o método &lt;em&gt;UnsafeQueueUserWorkItem&lt;/em&gt;, mesmo que a aplicação não tenha as devidas permissões, a execução da tarefa ocorre sem maiores problemas.&lt;br /&gt;&lt;br /&gt;É importante dizer aqui que a performance é melhorada mas, em contrapartida, a segurança fica vulnerável. Utilizar este tipo de código pode abrir portas para algum código malicioso, que pode utilizá-lo para elevar os privilégios de uma aplicação e, consequentemente, executar tarefas que atualmente ela não tem permissão. Opte sempre por utilizar esta técnica em uma tarefa em que voce não dependerá de nenhum recurso do sistema operacional (sistema de arquivos, &lt;em&gt;registry&lt;/em&gt;, SQL Server, etc.), utilizando em conjunto com tarefas que dependam exclusivamente do processador, como é o caso de cálculos complexos, geração de algum conteúdo, etc., melhorando consideravelmente a performance na execução, sem abrir potenciais problemas de segurança.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://pontonetpt.com/aggbug.aspx?PostID=937" width="1" height="1"&gt;</description><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/.NET+Framework/default.aspx">.NET Framework</category><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/Async/default.aspx">Async</category><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/Security/default.aspx">Security</category></item><item><title>IgnoreDataMemberAttribute</title><link>http://pontonetpt.com/blogs/israelaece/archive/2009/03/10/P28877.aspx</link><pubDate>Tue, 10 Mar 2009 21:50:00 GMT</pubDate><guid isPermaLink="false">9d4b03f4-ce39-4703-ab9d-5b341a2c824e:936</guid><dc:creator>Israel Aéce</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://pontonetpt.com/blogs/israelaece/rsscomments.aspx?PostID=936</wfw:commentRss><comments>http://pontonetpt.com/blogs/israelaece/archive/2009/03/10/P28877.aspx#comments</comments><description>&lt;p align="justify"&gt;A partir do .NET Framework 3.5 SP1 temos a possibilidade de suportar a serialização de tipos complexos em serviços WCF, mesmo que eles não estejam decorados com o atributo &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx"&gt;DataContractAttribute&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute.aspx"&gt;DataMemberAttribute&lt;/a&gt; ou &lt;a href="http://msdn.microsoft.com/en-us/library/system.serializableattribute.aspx"&gt;SerializableAttribute&lt;/a&gt;, permitindo o suporte à objetos &lt;a href="http://en.wikipedia.org/wiki/POCO"&gt;POCO&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Quando trabalhamos nesta linha, não precisamos nos preocupar com os atributos já que, por padrão, todas as propriedades públicas serão serializadas. Já que o comportamento padrão faz com que todas as propriedades serão serializadas, como podemos determinar que uma delas não deve ser disponibilizada para os consumidores do serviço? Neste caso, temos que explicitamente dizer ao &lt;em&gt;runtime&lt;/em&gt; do WCF para não serializar tal propriedade e, para isso, recorremos à utilização do atributo &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.ignoredatamemberattribute.aspx"&gt;IgnoreDataMemberAttribute&lt;/a&gt;, contida no &lt;em&gt;namespace&lt;/em&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.aspx"&gt;System.Runtimem.Serialization&lt;/a&gt;, aplicando-o nas propriedades que não queremos que esteja disponível, assim como é mostrado abaixo:&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;public class&lt;/font&gt; Usuario&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#0000ff"&gt;public string&lt;/font&gt; Nome { &lt;font color="#0000ff"&gt;get&lt;/font&gt;; &lt;font color="#0000ff"&gt;set&lt;/font&gt;; }&lt;br /&gt;&lt;br /&gt;    [IgnoreDataMember]&lt;br /&gt;    &lt;font color="#0000ff"&gt;public string&lt;/font&gt; Password { &lt;font color="#0000ff"&gt;get&lt;/font&gt;; &lt;font color="#0000ff"&gt;set&lt;/font&gt;; }&lt;br /&gt;}&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://pontonetpt.com/aggbug.aspx?PostID=936" width="1" height="1"&gt;</description><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/CSD/default.aspx">CSD</category><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/WCF/default.aspx">WCF</category></item><item><title>DBAuthorization – Parte 10 – Conclusão</title><link>http://pontonetpt.com/blogs/israelaece/archive/2009/03/09/P28856.aspx</link><pubDate>Mon, 09 Mar 2009 23:35:00 GMT</pubDate><guid isPermaLink="false">9d4b03f4-ce39-4703-ab9d-5b341a2c824e:935</guid><dc:creator>Israel Aéce</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://pontonetpt.com/blogs/israelaece/rsscomments.aspx?PostID=935</wfw:commentRss><comments>http://pontonetpt.com/blogs/israelaece/archive/2009/03/09/P28856.aspx#comments</comments><description>&lt;p align="justify"&gt;Finalmente chegamos na conclusão desta série. A partir deste momento você tem todas as políticas de acesso as páginas dentro do banco de dados, com uma arquitetura flexível e que pode ser estendida para ser suportada por outros repositórios.&lt;br /&gt;&lt;br /&gt;Uma vez que o &lt;em&gt;provider&lt;/em&gt; foi criado, sempre que nós precisamos das informações, seja para aplicar a autorização durante a execução ou pelas telas de gerenciamento das informações, sempre utilizamos o provider para isso (classe &lt;em&gt;DBAuthorization&lt;/em&gt;), o que torna a aplicação e a API totalmente independente de qual fonte de dados estamos utilizando para armazenar essas informações.&lt;br /&gt;&lt;br /&gt;É importante dizer também que, assim como a &lt;em&gt;UrlAuthorization&lt;/em&gt;, a &lt;em&gt;DBAuthorization&lt;/em&gt; avalia as permissões de forma sequencial, ou seja, a ordem em que elas aparecerem cadastradas no banco de dados será a ordem de avaliação durante a execução. Neste momento não temos nenhuma forma de reordenação dos registros, mas isso pode ser facilmente implementado. Um boa prática aqui é sempre você ir cadastrando em uma ordem coerente, ou seja, negue o acesso anônimo para um diretório como um todo mas, dentro dele, customize o acesso à algumas seções de acordo com os papéis.&lt;br /&gt;&lt;br /&gt;Outra semelhança que o &lt;em&gt;DBAuthorizationModule&lt;/em&gt; possui em relação ao &lt;em&gt;UrlAuthorizationModule&lt;/em&gt; é que faz uso da propriedade &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpcontext.user.aspx"&gt;User&lt;/a&gt; da classe &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpcontext.aspx"&gt;HttpContext&lt;/a&gt;. Essa propriedade retorna a instância de uma classe que implementa a interface &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.principal.iprincipal.aspx"&gt;IPrincipal&lt;/a&gt; e, independentemente do tipo de autenticação que está utilizando (&lt;em&gt;Forms&lt;/em&gt; (&lt;a href="http://msdn.microsoft.com/en-us/library/system.security.principal.genericprincipal.aspx"&gt;GenericPrincipal&lt;/a&gt;) ou &lt;em&gt;Windows&lt;/em&gt; (&lt;a href="http://msdn.microsoft.com/en-us/library/system.security.principal.windowsprincipal.aspx"&gt;WindowsPrincipal&lt;/a&gt;)), ele sempre irá trabalhar de forma genérica. Utilizará a propriedade &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.principal.iidentity.aspx"&gt;IIdentity&lt;/a&gt; para determinar o nome do usuário e o método &lt;em&gt;IsInRole&lt;/em&gt; para avaliar se o usuário faz ou não parte de um determinado papel/grupo.&lt;br /&gt;&lt;br /&gt;Para efeitos de centralização e reusabilidade da API, você pode instalar essa DLL dentro do GAC (&lt;em&gt;Global Assembly Cache&lt;/em&gt;) e registrar a seção &lt;em&gt;“dbAuthorization”&lt;/em&gt; no arquivo &lt;em&gt;machine.config&lt;/em&gt;. Esta técnica evitará com que todas as aplicações que desejam fazer uso deste recurso, não precisem explicitamente fazer o registro.&lt;br /&gt;&lt;br /&gt;Para finalizar, todo esse projeto não foi implementando em um ambiente real. Os testes foram locais e, se desejar colocá-lo em um ambiente de produção, chamo a atenção para que você refaça os testes, analisando todas as possibilidades necessárias para garantir o bom funcionamento dele.&lt;br /&gt;&lt;br /&gt;Quero também agradecer imensamente ao &lt;a href="http://msmvps.com/blogs/luisabreu/default.aspx"&gt;Luis Abreu&lt;/a&gt;, expert em tecnologias Microsoft, que revisou e me deu dicas extremamente importantes para ajudar na elaboração desta série. O código para download está no seguinte endereço: &lt;a href="http://www.projetando.net/Temp/Posts/DBAuthorization.zip"&gt;http://www.projetando.net/Temp/Posts/DBAuthorization.zip&lt;/a&gt; &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://pontonetpt.com/aggbug.aspx?PostID=935" width="1" height="1"&gt;</description><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/Security/default.aspx">Security</category></item><item><title>DBAuthorization – Parte 9 – Interface de Administração</title><link>http://pontonetpt.com/blogs/israelaece/archive/2009/03/06/P28845.aspx</link><pubDate>Fri, 06 Mar 2009 15:42:00 GMT</pubDate><guid isPermaLink="false">9d4b03f4-ce39-4703-ab9d-5b341a2c824e:934</guid><dc:creator>Israel Aéce</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://pontonetpt.com/blogs/israelaece/rsscomments.aspx?PostID=934</wfw:commentRss><comments>http://pontonetpt.com/blogs/israelaece/archive/2009/03/06/P28845.aspx#comments</comments><description>&lt;p align="justify"&gt;Nos &lt;em&gt;posts anteriores&lt;/em&gt; analisamos detalhadamente como devemos proceder para criar a infraestrutura necessária, e para efetuar a autorização com as informações armazenadas em uma base de dados. Sem telas de administração destas informações, teríamos que recorrer diretamente as ferramentas do próprio banco de dados para inserir as informações.&lt;br /&gt;&lt;br /&gt;Para facilitar, criei também duas telas: &lt;em&gt;ViewAllRules.aspx&lt;/em&gt; e &lt;em&gt;AddRule.aspx&lt;/em&gt;. A primeira delas exibe uma lista contendo todas as políticas cadastradas, exibindo o caminho (&lt;em&gt;path&lt;/em&gt;), ação e tipo, dando também a opção de exclusão. A imagem abaixo exibe essa tela, podendo ser customizada para ter uma melhor aparência:&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p align="justify"&gt;&lt;img src="http://pontonetpt.com:1466/images/weblogs_pontonetpt_com/israelaece/119/o_DBAuth4.png" alt="" /&gt;&lt;/p&gt;
&lt;p align="justify"&gt;Basicamente, no evento &lt;em&gt;Load&lt;/em&gt; da página invoco o método &lt;em&gt;GetAllRules&lt;/em&gt; a partir do &lt;em&gt;provider&lt;/em&gt; (classe &lt;em&gt;DBAuthorization&lt;/em&gt;) e, com o retorno deste método (&lt;em&gt;DBAuthorizationRuleCollection&lt;/em&gt;) carrega o controle &lt;em&gt;DataList&lt;/em&gt;. O código para carregar os dados é bem simples:&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;private void &lt;/font&gt;BindRules()&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#0000ff"&gt;this&lt;/font&gt;.DataList1.DataSource = DBAuthorization.GetAllRules();&lt;br /&gt;    &lt;font color="#0000ff"&gt;this&lt;/font&gt;.DataList1.DataBind();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Já a segunda página, &lt;em&gt;AddRule.aspx&lt;/em&gt;, disponibiliza um formulário com os devidos campos para a criação de uma nova política. Esse formulário já está configurado com alguns &lt;em&gt;DropDownList’s&lt;/em&gt; para assegurar que o usuário que está cadastrando a política escolha apenas um dos tipos ou ações suportadas. Essa página é exibida abaixo:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://pontonetpt.com:1466/images/weblogs_pontonetpt_com/israelaece/119/o_DBAuth5.png" alt="" /&gt;&lt;/p&gt;
&lt;p align="justify"&gt;O único código que temos aqui é a inserção da regra no evento &lt;em&gt;Click&lt;/em&gt; do botão &lt;em&gt;“Add Rule”&lt;/em&gt;, código qual é mostrado abaixo:&lt;br /&gt;&lt;br /&gt;DBAuthorization.AddRule(&lt;br /&gt;    &lt;font color="#0000ff"&gt;new&lt;/font&gt; DBAuthorizationRule()&lt;br /&gt;    {&lt;br /&gt;        Action = Helper.ParseEnum&amp;lt;DBAuthorizationRuleAction&amp;gt;(&lt;font color="#0000ff"&gt;this&lt;/font&gt;.Action.SelectedValue),&lt;br /&gt;        Data = Helper.ExtractCollectionFromString(&lt;font color="#0000ff"&gt;this&lt;/font&gt;.Data.Text.Trim()),&lt;br /&gt;        Path = &lt;font color="#0000ff"&gt;this&lt;/font&gt;.Path.Text.Trim(),&lt;br /&gt;        Type = Helper.ParseEnum&amp;lt;DBAuthorizationRuleType&amp;gt;(&lt;font color="#0000ff"&gt;this&lt;/font&gt;.Type.SelectedValue)&lt;br /&gt;    });&lt;br /&gt;&lt;br /&gt;Ao caminho (&lt;em&gt;path&lt;/em&gt;) não necessariamente precisa ser uma página ASPX, mas um diretório. Isso pode ajudar quando você precisa proteger um diretório todo. Utilize a página quando precisar de um refinamento da autorização, concedendo acesso específico à um papel ou usuário. Como a busca pelo &lt;em&gt;path&lt;/em&gt; está baseado na propriedade &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httprequest.path.aspx"&gt;Path&lt;/a&gt; da classe &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httprequest.aspx"&gt;HttpRequest&lt;/a&gt;, a propriedade &lt;em&gt;Path&lt;/em&gt; da classe &lt;em&gt;DBAuthorizationRule&lt;/em&gt; deve seguir o padrão de URL absoluta, como por exemplo: &lt;em&gt;“/App/Diretorio/Pagina.aspx”&lt;/em&gt; ou apenas &lt;em&gt;“/App/Diretorio/”&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Essas telas são simplesmente páginas ASPX que fazem uso do API &lt;em&gt;DBAuthorization&lt;/em&gt; para exibir ou criar novas políticas de acesso. Como elas fazem parte de um projeto específico, essas telas não são reutilizáveis por várias aplicações. Fica sob responsabilidade do desenvolvedor criar ou não as telas nas aplicações que deseja fazer uso desta funcionalidade.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://pontonetpt.com/aggbug.aspx?PostID=934" width="1" height="1"&gt;</description><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/Security/default.aspx">Security</category></item><item><title>DBAuthorization – Parte 8 – Configuração do arquivo Web.config</title><link>http://pontonetpt.com/blogs/israelaece/archive/2009/03/05/P28841.aspx</link><pubDate>Thu, 05 Mar 2009 18:07:00 GMT</pubDate><guid isPermaLink="false">9d4b03f4-ce39-4703-ab9d-5b341a2c824e:933</guid><dc:creator>Israel Aéce</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://pontonetpt.com/blogs/israelaece/rsscomments.aspx?PostID=933</wfw:commentRss><comments>http://pontonetpt.com/blogs/israelaece/archive/2009/03/05/P28841.aspx#comments</comments><description>&lt;p align="justify"&gt;No &lt;a href="http://weblogs.pontonetpt.com/israelaece/posts/28837.aspx"&gt;post anterior&lt;/a&gt; acoplamos o módulo &lt;em&gt;DBAuthorizationModule&lt;/em&gt; e removemos o módulo &lt;em&gt;UrlAuthorizationModule&lt;/em&gt; da execução da aplicação. Isso fará com que a avaliação das políticas seja feita utilizando o &lt;em&gt;provider&lt;/em&gt;, que tem o papel de disponibilizar as informações para o módulo e para a aplicação.&lt;br /&gt;&lt;br /&gt;Mas as configurações no arquivo &lt;em&gt;Web.config&lt;/em&gt; não se resumem a isso. Além das configurações do &lt;em&gt;Membership&lt;/em&gt; e &lt;em&gt;Roles&lt;/em&gt;, ainda precisamos registrar o &lt;em&gt;provider&lt;/em&gt; responsável pela autorização no &lt;em&gt;Web.config&lt;/em&gt;. A criação da classe que representa essa seção já foi discutida no artigo em que demonstro como criar um &lt;em&gt;provider&lt;/em&gt; customizado. Esse artigo pode ser acessado a partir &lt;a href="http://www.projetando.net/Sections/ViewArticle.aspx?ArticleID=75"&gt;deste endereço&lt;/a&gt; e vou assumir que você tenha o devido conhecimento nisso.&lt;br /&gt;&lt;br /&gt;No código abaixo limitei as configurações relevantes do &lt;em&gt;provider&lt;/em&gt;, como o registro da seção, a conexão com o banco de dados e a configuração do &lt;em&gt;provider&lt;/em&gt; em si. Note que o escolhido foi o &lt;em&gt;“SqlAuthorizationProvider”&lt;/em&gt;:&lt;br /&gt;&lt;br /&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;    &amp;lt;configSections&amp;gt;&lt;br /&gt;        &amp;lt;section&lt;br /&gt;            name=&amp;quot;dbAuthorization&amp;quot;&lt;br /&gt;            type=&amp;quot;ProjetandoNET.Web.Configuration.DBAuthorizationSection, ProjetandoNET&amp;quot;&lt;br /&gt;            requirePermission=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;    &amp;lt;/configSections&amp;gt;&lt;br /&gt;    &amp;lt;connectionStrings&amp;gt;&lt;br /&gt;        &amp;lt;clear/&amp;gt;&lt;br /&gt;        &amp;lt;add&lt;br /&gt;            name=&amp;quot;SqlConnectionString&amp;quot;&lt;br /&gt;            connectionString=&amp;quot;Data Source=.;Initial Catalog=DB;Integrated Security=SSPI;&amp;quot;&lt;br /&gt;            providerName=&amp;quot;System.Data.SqlClient&amp;quot; /&amp;gt;&lt;br /&gt;    &amp;lt;/connectionStrings&amp;gt;&lt;br /&gt;    &amp;lt;dbAuthorization defaultProvider=&amp;quot;SqlAuthorizationProvider&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;providers&amp;gt;&lt;br /&gt;            &amp;lt;add&lt;br /&gt;                name=&amp;quot;SqlAuthorizationProvider&amp;quot;&lt;br /&gt;                type=&amp;quot;ProjetandoNET.Web.Security.SqlAuthorizationProvider, ProjetandoNET&amp;quot;&lt;br /&gt;                applicationName=&amp;quot;WebTeste&amp;quot;&lt;br /&gt;                connectionStringName=&amp;quot;SqlConnectionString&amp;quot;&lt;br /&gt;                storeRulesInCache=&amp;quot;true&amp;quot;&lt;br /&gt;                commandTimeout=&amp;quot;40&amp;quot; /&amp;gt;&lt;br /&gt;        &amp;lt;/providers&amp;gt;&lt;br /&gt;    &amp;lt;/dbAuthorization&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;br /&gt;&lt;br /&gt;Assim como na configuração do módulo, o registro da seção que criamos e também os tipos dos &lt;em&gt;providers&lt;/em&gt; referentes à autorização também devem contemplar o nome completo (&lt;em&gt;namespace&lt;/em&gt; + &lt;em&gt;Assembly&lt;/em&gt;). Você pode utilizar cada elemento &lt;em&gt;add&lt;/em&gt; para adicionar quantos &lt;em&gt;providers&lt;/em&gt; forem necessários mas, em &lt;em&gt;runtime&lt;/em&gt;, o ASP.NET utilizará o &lt;em&gt;provider&lt;/em&gt; especificado no atributo &lt;em&gt;defaultProvider&lt;/em&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://pontonetpt.com/aggbug.aspx?PostID=933" width="1" height="1"&gt;</description><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/Security/default.aspx">Security</category></item><item><title>DBAuthorization – Parte 7 – DBAuthorizationModule</title><link>http://pontonetpt.com/blogs/israelaece/archive/2009/03/04/P28837.aspx</link><pubDate>Wed, 04 Mar 2009 08:38:00 GMT</pubDate><guid isPermaLink="false">9d4b03f4-ce39-4703-ab9d-5b341a2c824e:932</guid><dc:creator>Israel Aéce</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://pontonetpt.com/blogs/israelaece/rsscomments.aspx?PostID=932</wfw:commentRss><comments>http://pontonetpt.com/blogs/israelaece/archive/2009/03/04/P28837.aspx#comments</comments><description>&lt;p align="justify"&gt;Com o &lt;a href="http://weblogs.pontonetpt.com/israelaece/posts/28826.aspx"&gt;post anterior&lt;/a&gt; provemos uma boa performance, garantindo que a mesma informação seja compartilhada entre todos os usuários de uma aplicação específica. Além disso, em &lt;em&gt;posts&lt;/em&gt; anteriores analisamos como extrair os dados da fonte de dados mas, tudo o que fizemos até então, é a manipulação de dados, mas a regra para validar se o usuário atual possui ou não direito de acesso não foi definida.&lt;br /&gt;&lt;br /&gt;Todas as funcionalidades que falamos no &lt;a href="http://weblogs.pontonetpt.com/israelaece/posts/28809.aspx"&gt;primeiro post&lt;/a&gt; desta série estão acopladas ao &lt;em&gt;pipeline&lt;/em&gt; do ASP.NET através de módulos (&lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ihttpmodule.aspx"&gt;IHttpModule&lt;/a&gt;). Se analisarmos o arquivo &lt;em&gt;Web.config&lt;/em&gt; do servidor (aquele que está dentro do diretório do .NET Framework), veremos os módulos vinculados à execução da aplicação:&lt;br /&gt;&lt;br /&gt;&amp;lt;httpModules&amp;gt;&lt;br /&gt;    &amp;lt;add&lt;br /&gt;        name=&amp;quot;WindowsAuthentication&amp;quot; &lt;br /&gt;        type=&amp;quot;System.Web.Security.WindowsAuthenticationModule&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;add &lt;br /&gt;        name=&amp;quot;FormsAuthentication&amp;quot; &lt;br /&gt;        type=&amp;quot;System.Web.Security.FormsAuthenticationModule&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;add &lt;br /&gt;        name=&amp;quot;RoleManager&amp;quot; &lt;br /&gt;        type=&amp;quot;System.Web.Security.RoleManagerModule&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;add &lt;br /&gt;        name=&amp;quot;UrlAuthorization&amp;quot; &lt;br /&gt;        type=&amp;quot;System.Web.Security.UrlAuthorizationModule&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;add &lt;br /&gt;        name=&amp;quot;FileAuthorization&amp;quot; &lt;br /&gt;        type=&amp;quot;System.Web.Security.FileAuthorizationModule&amp;quot;/&amp;gt;&lt;br /&gt;&amp;lt;/httpModules&amp;gt;&lt;br /&gt;&lt;br /&gt;Os módulos de autenticação são executados de acordo com a opção escolhida no arquivo &lt;em&gt;Web.config&lt;/em&gt; (&lt;em&gt;Forms&lt;/em&gt; ou &lt;em&gt;Windows&lt;/em&gt;). Para autorização, a classe &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpapplication.aspx"&gt;HttpApplication&lt;/a&gt; fornece um evento chamado &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpapplication.authorizerequest.aspx"&gt;AuthorizeRequest&lt;/a&gt;, que é disparado quando chega o momento de determinar a autorização da página requisitada. Os módulos “assinam” esse evento, e são notificados quando ele ocorre e, com isso, executam as verificações necessárias para determinar se o usuário possui ou não os privilégios necessários para acessar a página solicitada.&lt;br /&gt;&lt;br /&gt;A &lt;em&gt;UrlAuthorization&lt;/em&gt; é a responsável por efetuar essa verificação levando em conta as políticas de acesso que colocamos no arquivo &lt;em&gt;Web.config&lt;/em&gt; e, como sabemos, se alteradas forçam o processo do ASP.NET ser reciclado, o que queremos evitar. Como não vamos mais levar em conta as configurações de políticas de acesso que estão no arquivo de configuração, devemos remover este módulo da execução mas, antes disso, ainda é necessário criarmos o nosso.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;DBAuthorizationModule&lt;/em&gt; é uma classe que implementa a &lt;em&gt;Interface IHttpModule&lt;/em&gt; e também assina o evento &lt;em&gt;AuthorizeRequest&lt;/em&gt;. No nosso caso, temos que avaliar se o usuário possui ou não privilégio de acesso consultando o &lt;em&gt;provider&lt;/em&gt; anteriormente criado. O &lt;em&gt;provider&lt;/em&gt;, por sua vez, irá retornar as políticas do &lt;em&gt;cache&lt;/em&gt; ou efetuar a busca no banco de dados.&lt;br /&gt;&lt;br /&gt;Depois que o &lt;em&gt;provider&lt;/em&gt; devolver as políticas definidas, temos que aplicar a regra necessária para conceder ou negar o acesso para o usuário corrente. Mas antes de efetivamente executar essa tarefa, precisamos analisar a propriedade &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpcontext.skipauthorization.aspx"&gt;SkipAuthorization&lt;/a&gt; da classe &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpcontext.aspx"&gt;HttpContext&lt;/a&gt;. Essa propriedade retorna um valor booleano indicando se a autorização deve ou não ser avaliada. Um exemplo disso é quando você solicita a página de &lt;em&gt;Login&lt;/em&gt;. Essa página não deve sofrer nenhuma espécie de autorização, já que todos devem acessá-la. Caso essa propriedade retorne &lt;em&gt;False&lt;/em&gt;, então devemos avaliar os privilégios do usuário. O código abaixo ilustra o módulo:&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;public class &lt;/font&gt;DBAuthorizationModule : IHttpModule&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#0000ff"&gt;public void&lt;/font&gt; Init(HttpApplication context)&lt;br /&gt;    {&lt;br /&gt;        context.AuthorizeRequest += &lt;font color="#0000ff"&gt;new&lt;/font&gt; EventHandler(OnEnter);&lt;br /&gt;    }&lt;/p&gt;
&lt;p align="justify"&gt;    &lt;font color="#0000ff"&gt;private void&lt;/font&gt; OnEnter(&lt;font color="#0000ff"&gt;object&lt;/font&gt; sender, EventArgs e)&lt;br /&gt;    {&lt;br /&gt;        HttpApplication application = (HttpApplication)sender;&lt;br /&gt;        HttpContext context = application.Context;&lt;/p&gt;
&lt;p align="justify"&gt;        &lt;font color="#0000ff"&gt;if&lt;/font&gt; (!context.SkipAuthorization)&lt;br /&gt;        {&lt;br /&gt;            &lt;font color="#0000ff"&gt;if &lt;/font&gt;(!IsUserAllowed(context.User, context.Request.Path, context.Request.RequestType))&lt;br /&gt;            {&lt;br /&gt;                context.Response.StatusCode = 401;&lt;br /&gt;                context.Response.StatusDescription = &amp;quot;Unauthorized&amp;quot;;&lt;br /&gt;                application.CompleteRequest();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;/p&gt;
&lt;p align="justify"&gt;    &lt;font color="#0000ff"&gt;public static bool&lt;/font&gt; IsUserAllowed(IPrincipal principal, &lt;font color="#0000ff"&gt;string&lt;/font&gt; requestedPath, &lt;font color="#0000ff"&gt;string&lt;/font&gt; verb)&lt;br /&gt;    {&lt;br /&gt;        &lt;font color="#0000ff"&gt;return&lt;/font&gt; DBAuthorization.GetAllRulesByPath(requestedPath).IsUserAllowed(principal, requestedPath, verb);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Para avaliar as políticas, criei um método estático chamado &lt;em&gt;IsUserAllowed&lt;/em&gt; que recebe como parâmetro o usuário corrente, a página (&lt;em&gt;path&lt;/em&gt;) requisitada e o verbo (GET ou POST). Esse método recorre ao provider para recuperar a coleção de regras definidas e, em seguida, invoca o método &lt;em&gt;IsUserAllowed&lt;/em&gt; da classe &lt;em&gt;DBAuthorizationRuleCollection&lt;/em&gt; informando os mesmos parâmetros. É dentro deste método que toda a “mágica” ocorre, e que por questões de espaço, não será exibida aqui.&lt;br /&gt;&lt;br /&gt;Caso os métodos &lt;em&gt;IsUserAllowed&lt;/em&gt; retornem &lt;em&gt;False&lt;/em&gt;, definimos o código de status de HTTP como 401 (&lt;em&gt;Unauthorized&lt;/em&gt;) e invocamos o método &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpapplication.completerequest.aspx"&gt;CompleteRequest&lt;/a&gt; da classe &lt;em&gt;HttpApplication&lt;/em&gt;, que obriga o ASP.NET a dar um &lt;em&gt;“bypass”&lt;/em&gt; em todos os eventos da classe &lt;em&gt;HttpApplication&lt;/em&gt;, direcionando a requisição para o evento &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpapplication.endrequest.aspx"&gt;EndRequest&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Com o módulo criado, então é necessário adicioná-lo à execução. Mas antes disso, como não faremos uso da &lt;em&gt;Url Authorization&lt;/em&gt;, precisamos também removê-la. Dentro do arquivo &lt;em&gt;Web.config&lt;/em&gt; da aplicação temos uma seção chamada &lt;em&gt;httpModules&lt;/em&gt;. Essa seção permite alistarmos todos os módulos que serão utilizados pela aplicação e, a remoção do módulo &lt;em&gt;“UrlAuthorization”&lt;/em&gt; se faz necessária porque em &lt;em&gt;runtime&lt;/em&gt; ele mescla os módulos do &lt;em&gt;Web.config&lt;/em&gt; do servidor com o da aplicação. Abaixo temos a configuração necessária: &lt;br /&gt;&lt;br /&gt;&amp;lt;httpModules&amp;gt;&lt;br /&gt;    &amp;lt;remove &lt;br /&gt;        name=&amp;quot;UrlAuthorization&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;add &lt;br /&gt;        name=&amp;quot;DBAuthorizationModule&amp;quot; &lt;br /&gt;        type=&amp;quot;ProjetandoNET.Web.Security.DBAuthorizationModule, ProjetandoNET&amp;quot;/&amp;gt;&lt;br /&gt;&amp;lt;/httpModules&amp;gt;&lt;br /&gt;&lt;br /&gt;Note que o tipo (atributo &lt;em&gt;type&lt;/em&gt; do elemento &lt;em&gt;add&lt;/em&gt;) deve refletir o nome completo da classe, ou seja, incluindo os possíveis &lt;em&gt;namespaces&lt;/em&gt; e também o nome do &lt;em&gt;Assembly&lt;/em&gt;. As configurações do arquivo &lt;em&gt;Web.config&lt;/em&gt; da aplicação não param por aí. Veremos mais detalhes no próximo post desta série.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://pontonetpt.com/aggbug.aspx?PostID=932" width="1" height="1"&gt;</description><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://pontonetpt.com/blogs/israelaece/archive/tags/Security/default.aspx">Security</category></item></channel></rss>