{"id":23557,"date":"2018-08-12T19:18:52","date_gmt":"2018-08-12T19:18:52","guid":{"rendered":"http:\/\/www.inacreditavel.pt\/?p=23557"},"modified":"2018-08-12T19:51:34","modified_gmt":"2018-08-12T19:51:34","slug":"iis-e-sql-server","status":"publish","type":"post","link":"http:\/\/www.inacreditavel.pt\/?p=23557","title":{"rendered":"IIS e SQL Server"},"content":{"rendered":"<p>Como disse na <a href=\"http:\/\/www.inacreditavel.pt\/?p=23522\">cr\u00f3nica anterior<\/a>, a Microsoft est\u00e1 sempre a mudar a forma de trabalhar, os processos de comunica\u00e7\u00e3o, as configura\u00e7\u00f5es dos programas e dos sistemas, tudo.<\/p>\n<p>Depois de instalar o Windows 2012 Server, com IIS e SQL Server Express, criei uma aplica\u00e7\u00e3o em C# para Web, no Visual Studio e tentei fazer o deployment para o servidor.<\/p>\n<p>O SQL Server estava a funcionar, e conseguia aceder a ele localmente e remotamente, atrav\u00e9s do SQL Server Management Studio. Algumas pistas da forma de configurar este ambiente, est\u00e3o na tal <a href=\"http:\/\/www.inacreditavel.pt\/?p=23522\">cr\u00f3nica anterior<\/a>.<\/p>\n<p>Criei uma base de dados simples, para teste, e conseguia aceder a ela, modific\u00e1-la, local e remotamente. Para isso tive que abri o porto 1433 em TCP, nas firewalls de Linux que ficam entre as m\u00e1quinas Windows. No entanto, a aplica\u00e7\u00e3o Web C# n\u00e3o conseguia aceder \u00e0 BD.<\/p>\n<p>Quando escrevi a 1\u00aa edi\u00e7\u00e3o do meu livro <a href=\"http:\/\/linguagens.w3.pt\/\">Linguagens WEB<\/a>, a Microsoft tinha acabado de lan\u00e7ar a primeira vers\u00e3o do dotNet. Usei as strings de liga\u00e7\u00e3o (connection strings) e as configura\u00e7\u00f5es dos sistemas de ent\u00e3o. Mais tarde, na 4\u00aa edi\u00e7\u00e3o, tive que mudar tudo, pois a Microsoft decidiu alterar uma s\u00e9rie de coisas, inclusive o nome da m\u00e1quina local, que por vezes \u00e9 localhost, outras vezes \u00e9 (local), \u00e9 como lhes apetece. Mas as strings de liga\u00e7\u00e3o \u00e0 BD e as configura\u00e7\u00f5es tamb\u00e9m mudaram nessa altura. Al\u00e9m disso, passou a existir um servidor IIS Express no Visual Studio, para que os deployments n\u00e3o fossem feitos logo no servidor de produ\u00e7\u00e3o, e assim, poder-se fazer debug.<\/p>\n<p>Agora, mudou tudo outra vez: strings de liga\u00e7\u00e3o, formas de autentica\u00e7\u00e3o, utilizadores do sistema, configura\u00e7\u00f5es, e por a\u00ed fora. Ficam aqui registadas as configura\u00e7\u00f5es necess\u00e1rias para fazer o deployment local (no IIS Express) e remoto (no IIS de produ\u00e7\u00e3o). Na minha configura\u00e7\u00e3o, decidi ter apenas uma base de dados no servidor de produ\u00e7\u00e3o, portanto, tanto o IIS de produ\u00e7\u00e3o, como o virtual acedem \u00e0 mesma BD.<\/p>\n<p>A configura\u00e7\u00e3o \u00e9 a seguinte: no Windows Server 2012, est\u00e1 o servidor Web (IIS) de produ\u00e7\u00e3o e a BD (SQL Server Express); na m\u00e1quina de desenvolvimento, est\u00e1 o Visual Studio, com um IIS Express.<\/p>\n<p>No ficheiro Web.Debug.config, coloquei a seguinte string de liga\u00e7\u00e3o:<\/p>\n<pre style=\"font-size: 0.8em;\">&lt;connectionStrings&gt;\r\n&lt;add name=\"BD\"\r\nconnectionString=\"Data Source=192.168.4.201\\SQLEXPRESS;Initial Catalog=escola;User Id=sa;Password=Pass-xxxx\"\r\nproviderName=\"System.Data.SqlClient\" \/&gt;\r\n&lt;\/connectionStrings&gt;\r\n<\/pre>\n<p>No ficheiro Web.Release.config, coloquei a seguinte string de liga\u00e7\u00e3o:<\/p>\n<pre style=\"font-size: 0.8em;\">&lt;connectionStrings&gt;\r\n&lt;add name=\"BD\"\r\nconnectionString=\"Data Source=localhost\\SQLEXPRESS;Initial Catalog=escola;Integrated Security=SSPI\"\r\nproviderName=\"System.Data.SqlClient\" xdt:Transform=\"SetAttributes\" xdt:Locator=\"Match(name)\" \/&gt;\r\n&lt;\/connectionStrings&gt;\r\n<\/pre>\n<p>A liga\u00e7\u00e3o no Web.Release.config pode ser feita atrav\u00e9s de autentica\u00e7\u00e3o integrada, pois os dois servidores (IIS e SQL Server) est\u00e3o na mesma m\u00e1quina. O mesmo j\u00e1 n\u00e3o acontece no Web.Debug.config, pois o IIS Express est\u00e1 a correr na m\u00e1quina de desenvolvimento e tem que aceder \u00e0 BD remotamente, por isso precisa de usar credenciais de autentica\u00e7\u00e3o: nome de utilizador e password.<\/p>\n<p>Mas as coisas n\u00e3o s\u00e3o assim t\u00e3o simples. \u00c9 necess\u00e1rio que o SQL Server aceite estas dusa formas de autentica\u00e7\u00e3o, para permitir o acesso aos dados.<\/p>\n<p>Na vers\u00e3o anterior destas confus\u00f5es, desculpe, configura\u00e7\u00f5es da Microsoft, havia um utilizador IUSR_&lt;m\u00e1quina&gt; que era respons\u00e1vel pelo IIS, e bastava autoriz\u00e1-lo junto do SQL Server. Agora tudo mudou. E provavelmente vai mudar de novo daqui a 2 ou 3 anos. Mas continuemos.<\/p>\n<p>Configurar o SQL Server para aceitar pedidos locais do IIS<\/p>\n<p>Para conseguir chegar a esta configura\u00e7\u00e3o, os dois sites seguintes foram fundamentais:<br \/>\n<a href=\"https:\/\/www.codeproject.com\/Articles\/674930\/Configuring-IIS-ASP-NET-and-SQL-Server\">Configuring IIS, ASP.NET, and SQL Server<\/a><br \/>\n<a href=\"https:\/\/stackoverflow.com\/questions\/1933134\/add-iis-7-apppool-identities-as-sql-server-logons\">Add IIS 7 AppPool Identities as SQL Server Logons<\/a><br \/>\nO primeiro diz como configurar corretamente um utilizador para aceder ao SQLEXPRESS, mas falha no Login name. O segundo diz qual \u00e9 o login name, que no meu caso foi: IIS APPPOOL\\DefaultAppPool<\/p>\n<p>Eis a lista de instru\u00e7\u00f5es. De notar que o utilizador est\u00e1 errado: n\u00e3o \u00e9 NT AUTHORITY\\NETWORK SERVICE, mas sim IIS APPPOOL\\DefaultAppPool, como indica o 2\u00ba site.<\/p>\n<p>Adicionar o utilizador \u00e0 lista de utilizadores com permiss\u00f5es<\/p>\n<div style=\"border: 1px solid black; padding: 7px;\">Open SQL Server Management Studio (shortcut: Start -&gt; Run -&gt; ssms)<br \/>\nConnect when prompted.<br \/>\nExpand Security and then expand Logins.<br \/>\nIf you don&#8217;t have the network service listed (should be NT AUTHORITY\\NETWORK SERVICE):<br \/>\nRight-click on the Logins folder and select New Login.<br \/>\nAt the top, in the &#8216;Login Name&#8217; field, enter NETWORK SERVICE. If it refuses to accept that, try entering NT AUTHORITY\\NETWORK SERVICE.<br \/>\nNow select the Server Roles tab on the left.<br \/>\nYou can tick any role you like, but for me I will give it &#8216;public&#8217; access.<br \/>\nNow select the User Mapping tab on the left.<br \/>\nTick all the databases you want to allow this service account to access.<br \/>\nIn the Schema column for each selected database, set the value to dbo (or whatever schema you are using in your database).<br \/>\nThen, select one database row at a time and set the following permissions for it:<br \/>\ndb_datareader<br \/>\ndb_datawriter<br \/>\npublic<br \/>\nNow click OK.<br \/>\nIf you do have the network service account listed, edit that login entry and then follow steps (5 &#8211; 9) above.<\/div>\n<p>Autorizar o acesso a uma BD<\/p>\n<div style=\"border: 1px solid black; padding: 7px;\">\n<p>Expand Databases on the left.<br \/>\nExpand the Security folder and then expand Users.<br \/>\nThe service account should be listed there. Right-click and Properties on the service account (for us, NT AUTHORITY\\NETWORK SERVICE).<br \/>\nSelect the Securables tab on the left.<br \/>\nClick on the Search button.<br \/>\nSelect &#8216;Specific Objects&#8217; and click OK.<br \/>\nNow click the Object Types button.<br \/>\nScroll down and tick Schemas. Click OK.<br \/>\nIn the textbox below, enter the schema you are giving access for (the same as Step 7 above). In our case, it will be dbo. Click OK.<br \/>\nAt the bottom, select all the permissions you want to give for that database. In my case, I need quite extensive access to my database so I will be selecting these permissions:<br \/>\nAlter<br \/>\nControl<br \/>\nCreate Sequence<br \/>\nDelete<br \/>\nExecute<br \/>\nInsert<br \/>\nReferences<br \/>\nSelect<br \/>\nUpdate<br \/>\nNow click OK.<\/p>\n<\/div>\n<p>E aqui vai a corre\u00e7\u00e3o \u00e0 primeira caixa (nome correto do utilizador do IIS)<\/p>\n<div style=\"border: 1px solid black; padding: 7px;\">In SQL Server Management Studio, look for the Security folder (the security folder at the same level as the Databases, Server Objects, etc. folders&#8230;not the security folder within each individual database)<br \/>\nRight click logins and select &#8220;New Login&#8221;<br \/>\nIn the Login name field, type IIS APPPOOL\\YourAppPoolName &#8211; do not click search<br \/>\nFill whatever other values you like (i.e., authentication type, default database, etc.)<br \/>\nClick OK<\/div>\n<p>Para o acesso remoto, atrav\u00e9s do IIS virtual, a p\u00e1gina seguinte foi fundamental, principalmente a 2\u00aa resposta:<br \/>\n<a href=\"https:\/\/stackoverflow.com\/questions\/13754563\/sql-network-interfaces-error-26-error-locating-server-instance-specified\">SQL Network Interfaces, error: 26 &#8211; Error Locating Server\/Instance Specified<\/a><\/p>\n<div style=\"border: 1px solid black; padding: 7px;\">&#8220;Every time a client makes a connection to SQL Server named instance, we will send a SSRP UDP packet to the server machine UDP port 1434.&#8221;<br \/>\nMake sure the SQL Browser service is running on the server.<br \/>\nIf the firewall is enabled on the server, you need to put sqlbrowser.exe and\/or UDP port 1434 into exception.<\/div>\n<p>Foi necess\u00e1rio p\u00f4r a correr, em modo autom\u00e1tico, o servi\u00e7o SQL Server Browser, abrir o porto 1434 em UDP, na firewall do Windows Server e dos sistemas Linux interm\u00e9dios.<\/p>\n<p>J\u00e1 agora, fica aqui o resto do c\u00f3digo da aplica\u00e7\u00e3o<\/p>\n<p>Default.aspx<\/p>\n<pre style=\"font-size: 0.8em;\">&lt;%@ Page Language=\"c#\" AutoEventWireup=\"false\" Codebehind=\"Ola.aspx.cs\" Inherits=\"ola.Ola\"%&gt;\r\n&lt;% ola.Ola t = new ola.Ola(); %&gt;\r\n\r\n&lt;!DOCTYPE html&gt;\r\n&lt;html&gt;\r\n&lt;head&gt;\r\n&lt;meta charset=\"utf-8\" \/&gt;\r\n&lt;title&gt;&lt;\/title&gt;\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n&lt;h1&gt;Teste&lt;\/h1&gt;\r\n&lt;p&gt;Mensagem: &lt;% Response.Write(t.Message); %&gt;&lt;\/p&gt;\r\n&lt;p&gt;IPv6: &lt;% Response.Write(t.IPv6); %&gt;&lt;\/p&gt;\r\n&lt;p&gt;IP: &lt;% Response.Write(t.IP); %&gt;&lt;\/p&gt;\r\n&lt;p&gt;Data: &lt;% Response.Write(t.date); %&gt;&lt;\/p&gt;\r\n&lt;p&gt;Connection String : &lt;% Response.Write(t.conString); %&gt;&lt;\/p&gt;\r\n&lt;p&gt;Dados: &lt;% Response.Write(t.dados); %&gt;&lt;\/p&gt;\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;\r\n<\/pre>\n<p>Ola.aspx.cs<\/p>\n<pre style=\"font-size: 0.8em;\">\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Data.SqlClient;\r\nusing System.Linq;\r\nusing System.Web;\r\n\r\nnamespace ola\r\n{\r\n    public class Ola : System.Web.UI.Page\r\n    {\r\n        public string Message;\r\n        public string IPv6;\r\n        public string IP;\r\n        public string date;\r\n        public string dados;\r\n        public string conString;\r\n        private SqlConnection ligacao;\r\n\r\n        public Ola ()\r\n        {\r\n            Message = \"Aplica\u00e7\u00e3o de teste\";\r\n            IPv6 = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList.GetValue(0).ToString();\r\n            IP = HttpContext.Current.Request.Params[\"HTTP_CLIENT_IP\"] ?? HttpContext.Current.Request.UserHostAddress;\r\n            date = DateTime.UtcNow.ToString(\"dd\/MM\/yyyy HH:mm zzz\");\r\n            \r\n            System.Configuration.Configuration rootWebConfig = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(\"\/wwwroot\");\r\n            System.Configuration.ConnectionStringSettings connString;\r\n            connString = rootWebConfig.ConnectionStrings.ConnectionStrings[\"BD\"];\r\n            conString = connString.ConnectionString;\r\n            dados = \"\";\r\n            ligacao = new SqlConnection(conString);\r\n            try\r\n            {\r\n                ligacao.Open();\r\n                String sql = \"SELECT * FROM aluno\";\r\n                SqlCommand comando = new SqlCommand(sql, ligacao);\r\n                using (SqlDataReader dbDados = comando.ExecuteReader())\r\n                {\r\n                    while (dbDados.Read())\r\n                    {\r\n                        dados += dbDados.GetString(1) + \", \" + dbDados.GetString(2) + \";\";\r\n                    }\r\n                }\r\n                ligacao.Close();\r\n            }\r\n            catch (Exception e)\r\n            {\r\n                dados = \"ERRO: \" + e.Message;\r\n            }\r\n        }\r\n\r\n\r\n    }\r\n}\r\n<\/pre>\n<p>E o resultado<\/p>\n<div style=\"border: 1px solid black; padding: 7px;\">\nTeste<br \/>\nMensagem: Aplica\u00e7\u00e3o de teste<br \/>\nIPv6: fe80::7c07:5225:9e81:8b40%12<br \/>\nIP: 192.168.0.54<br \/>\nData: 12\/08\/2018 20:27 +01:00<br \/>\nConnection String : Data Source=localhost\\SQLEXPRESS;Initial Catalog=escola;Integrated Security=SSPI<br \/>\nDados: Maria, Lisboa;Jo\u00e3o, Porto;\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Como disse na cr\u00f3nica anterior, a Microsoft est\u00e1 sempre a mudar a forma de trabalhar, os processos de comunica\u00e7\u00e3o, as configura\u00e7\u00f5es dos programas e dos sistemas, tudo. Depois de instalar o Windows 2012 Server, com IIS e SQL Server Express, criei uma aplica\u00e7\u00e3o em C# para Web, no Visual Studio e tentei fazer o deployment [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"_links":{"self":[{"href":"http:\/\/www.inacreditavel.pt\/index.php?rest_route=\/wp\/v2\/posts\/23557"}],"collection":[{"href":"http:\/\/www.inacreditavel.pt\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.inacreditavel.pt\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.inacreditavel.pt\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.inacreditavel.pt\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=23557"}],"version-history":[{"count":4,"href":"http:\/\/www.inacreditavel.pt\/index.php?rest_route=\/wp\/v2\/posts\/23557\/revisions"}],"predecessor-version":[{"id":23561,"href":"http:\/\/www.inacreditavel.pt\/index.php?rest_route=\/wp\/v2\/posts\/23557\/revisions\/23561"}],"wp:attachment":[{"href":"http:\/\/www.inacreditavel.pt\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=23557"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.inacreditavel.pt\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=23557"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.inacreditavel.pt\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=23557"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}