{"id":1540,"date":"2012-02-15T14:56:14","date_gmt":"2012-02-15T20:56:14","guid":{"rendered":"http:\/\/www.uv.mx\/personal\/gvera\/?p=1540"},"modified":"2012-02-15T15:00:09","modified_gmt":"2012-02-15T21:00:09","slug":"asp-net-autenticacion-hacia-active-directory-lenta-la-primera-vez","status":"publish","type":"post","link":"https:\/\/www.uv.mx\/personal\/gvera\/2012\/02\/15\/asp-net-autenticacion-hacia-active-directory-lenta-la-primera-vez\/","title":{"rendered":"ASP.NET: Autenticaci\u00f3n hacia Active Directory lenta la primera vez"},"content":{"rendered":"<p><a href=\"http:\/\/www.uv.mx\/personal\/gvera\/files\/2012\/02\/auth1.gif\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1541\" src=\"http:\/\/www.uv.mx\/personal\/gvera\/files\/2012\/02\/auth1.gif\" alt=\"\" width=\"484\" height=\"258\" srcset=\"https:\/\/www.uv.mx\/personal\/gvera\/files\/2012\/02\/auth1.gif 484w, https:\/\/www.uv.mx\/personal\/gvera\/files\/2012\/02\/auth1-300x159.gif 300w\" sizes=\"auto, (max-width: 484px) 100vw, 484px\" \/><\/a>Una pregunta que he escuchado regularmente al utilizar ASP.NET como framework de programaci\u00f3n en sitios Web est\u00e1 relacionada con retraso en la autenticaci\u00f3n hacia un controlador de dominio Windows utilizando el namespace System.DirectoryServices. En concreto me preguntan si he experimentado un peque\u00f1o retraso al momento del <strong>primer intento de autenticaci\u00f3n<\/strong>, a\u00f1adiendo que para los subsecuentes intentos en un cierto periodo de tiempo, esto deja de suceder y la verificaci\u00f3n ya se efectua r\u00e1pidamente.<!--more--><\/p>\n<h3>Problema<\/h3>\n<p>En la mayor\u00eda de los casos el culplable es la clase DirectorySearcher que utilizamos erroneamente para realizar la busqueda del usuario que se quiere autenticar. Digo erroneamente, porque realmente no queremos buscar un usuario, sino unicamente antenticarlo. Aqui un c\u00f3digo de autenticaci\u00f3n muy com\u00fan en la red con este problema del delay al primer intento.<\/p>\n<p>[csharp]<br \/>\npublic bool UsuarioAD(string usuario, string password, string strDominio, string DominioIp)<br \/>\n    {<br \/>\n        bool res = false;<br \/>\n        try<br \/>\n        {<br \/>\n            string DirectoryEnt = &quot;LDAP:\/\/&quot; + DominioIp;<br \/>\n            string dominiousuario = strDominio + @&quot;\\&quot; + usuario;<br \/>\n            DirectoryEntry Entry = new DirectoryEntry(DirectoryEnt, dominiousuario, password, AuthenticationTypes.None);<br \/>\n            DirectorySearcher Search = new DirectorySearcher(Entry);<br \/>\n            Search.Filter = &quot;(SAMAccountName=&quot; + usuario + &quot;)&quot;;<br \/>\n            Search.PropertiesToLoad.Add(&quot;cn&quot;);<br \/>\n            SearchResult result = Search.FindOne();<br \/>\n            res = true;<br \/>\n        }<br \/>\n        catch<br \/>\n        {<br \/>\n            \/\/ No hubo \u00e9xito<br \/>\n        }<br \/>\n        return res;<br \/>\n    }<br \/>\n[\/csharp]<\/p>\n<h3>SOLUCI\u00d3N<\/h3>\n<p>La soluci\u00f3n radica en entender que lo que deseamos es autenticar al usuario y no buscarlo por todo el directorio. Un c\u00f3digo que s\u00f3lo auntentifica y en caso de \u00e9xito devuelve el objeto nativo de interfaces de servicios de Active Directory (ADSI) es una buena forma de hacerlo.<\/p>\n<p>[csharp]<br \/>\nprivate bool UsuarioAD(string usuario, string password, string strDominio, string DominioIp)<br \/>\n    {<br \/>\n        bool res = false;<br \/>\n        try<br \/>\n        {<br \/>\n            string DirectoryEnt = &quot;LDAP:\/\/&quot; + DominioIp;<br \/>\n            string dominiousuario = ddlDominio.SelectedValue + @&quot;\\&quot; + usuario;<br \/>\n            DirectoryEntry Entry = new DirectoryEntry(DirectoryEnt, dominiousuario, password, AuthenticationTypes.None);<br \/>\n            object nativeObject = Entry.NativeObject;<br \/>\n            res = true;<br \/>\n        }<br \/>\n        catch<br \/>\n        {<br \/>\n            \/\/No hubo \u00e9xito<br \/>\n        }<br \/>\n        return res;<br \/>\n    }<br \/>\n[\/csharp]<\/p>\n<p>En el caso de que desearamos realmente buscar por el \u00e1rbol de AD, la recomendaci\u00f3n est\u00e1 en definir adecuadamente la propiedad filter pues es la que puede alentar mucho este proceso. El tip est\u00e1 en NUNCA utilizar el asterisco (comod\u00edn) a la izquierda en la cadena de filtro del objeto DirectorySearcher. Aqu\u00ed un ejemplo:<\/p>\n<p>[csharp]<br \/>\nprivate bool Busca_Usuario_AD(string dominio, string usuario, string DominioIp)<br \/>\n        {<br \/>\n            string DirectoryEnt;<br \/>\n            bool res = false;<br \/>\n            try<br \/>\n            {<br \/>\n                DirectoryEnt = &quot;LDAP:\/\/&quot; + DominioIp + &quot;:389&quot;;<br \/>\n                SearchResultCollection results;<br \/>\n                System.DirectoryServices.DirectoryEntry Entry = new System.DirectoryServices.DirectoryEntry(DirectoryEnt, &quot;DOMINIO\\\\cuenta_para_buscar&quot;, &quot;password&quot;, AuthenticationTypes.None);<br \/>\n                DirectorySearcher Search = new DirectorySearcher(Entry);<br \/>\n                \/\/ Observa que no debes de poner el asterisco a la izquierda de lo que buscas. Esto lo alenta.<br \/>\n                Search.Filter = &quot;(&amp;(objectCategory=person)(|(cn=&quot; + usuario + &quot;*)(SAMAccountName=&quot; + usuario + &quot;*)))&quot;;<br \/>\n                Search.PropertiesToLoad.Add(&quot;cn&quot;);<br \/>\n                Search.PropertiesToLoad.Add(&quot;mail&quot;);<br \/>\n                Search.SizeLimit = 20;<br \/>\n                Search.ServerTimeLimit = DateTime.Now.AddSeconds(1) &#8211; DateTime.Now;<br \/>\n                results = Search.FindAll();<br \/>\n                if (results != null)<br \/>\n                {<br \/>\n                    foreach (SearchResult result in results)<br \/>\n                    {<br \/>\n                        if (result.Properties[&quot;cn&quot;].Count &gt; 0)<br \/>\n                        {<br \/>\n                            res = true;<br \/>\n                            \/\/ Haces cosas con (string)result.Properties[&quot;cn&quot;][0];<br \/>\n                        }<br \/>\n                    }<br \/>\n                }<br \/>\n            }<br \/>\n            catch<br \/>\n            {<br \/>\n                \/\/No hubo \u00e9xito<br \/>\n            }<br \/>\n            return res;<br \/>\n        }<br \/>\n[\/csharp]<\/p>\n<p>Espero estos peque\u00f1os tips te sean de utilidad.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Una pregunta que he escuchado regularmente al utilizar ASP.NET como framework de programaci\u00f3n en sitios Web est\u00e1 relacionada con retraso en la autenticaci\u00f3n hacia un controlador de dominio Windows utilizando el namespace System.DirectoryServices. En concreto me preguntan si he experimentado un peque\u00f1o retraso al momento del primer intento de autenticaci\u00f3n, a\u00f1adiendo que para los subsecuentes&#8230;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[11,94,46,64],"class_list":["post-1540","post","type-post","status-publish","format-standard","hentry","category-blog","tag-articulos-2","tag-asp-net","tag-desarrollo-de-software","tag-microsoft-2"],"_links":{"self":[{"href":"https:\/\/www.uv.mx\/personal\/gvera\/wp-json\/wp\/v2\/posts\/1540","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.uv.mx\/personal\/gvera\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.uv.mx\/personal\/gvera\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.uv.mx\/personal\/gvera\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.uv.mx\/personal\/gvera\/wp-json\/wp\/v2\/comments?post=1540"}],"version-history":[{"count":0,"href":"https:\/\/www.uv.mx\/personal\/gvera\/wp-json\/wp\/v2\/posts\/1540\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.uv.mx\/personal\/gvera\/wp-json\/wp\/v2\/media?parent=1540"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.uv.mx\/personal\/gvera\/wp-json\/wp\/v2\/categories?post=1540"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.uv.mx\/personal\/gvera\/wp-json\/wp\/v2\/tags?post=1540"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}