Related
I have a SQL Server 2008 R2 Express database.
I have written a Delphi application that uses a TADOConnection object to connect to the database. It works just fine on my computer. It fails to connect from other computers on the network.
It gives the error message:
Cannot open database "PeopleNetLink" requested by the login.
I have found all sorts of questions about this error message. I have found none that used SQL Server authentication and worked on one computer and not on others.
My connection string is
Provider=SQLNCLI10.1;
Integrated Security="";
Persist Security Info=False;
User ID=PNetLink;
Initial Catalog=PeopleNetLink;
Data Source=W1CNVS02\SQLEXPRESSPAY12;
Use Procedure for Prepare=1;
Auto Translate=True;
Packet Size=4096;
Initial File Name="";
Use Encryption for Data=False;
Tag with column collation when possible=False;
MARS Connection=False;
DataTypeCompatibility=0;
Trust Server Certificate=False;
Server SPN=""
Further experimentation reveals that if I log on to another computer as an admin, the program will log in successfully. This tells me that it is not using the user ID specified in the connect string. Now the question is "why not?"
This is a bit of a long-shot, as I don't have Sql Server 2008 installed, only the 2014 version. And maybe you've tried this already, but I spent hours on this problem before I found the step I was missing.
Assuming a utility like MS's PortQry shows the server's local network firewall is open and that your edition of 2008 comes with a copy of Sql Server Management Studio installed:
Start SSMS on the server,
Right-click the Sql Server's Properties
In the Properties pop-up, click the Connections tab
Check the checkbox "Allow remote connections to this server."
In some Sql Server editions, "Allow remote connections ..." is not check by default, which seems to square with marc_s's comment.
Update: Regarding your added "This tells me that it is not using the user ID specified in the connect string.":
If you open the DFM as text and hand-edit the connection string so that the "User ID" has a completely bogus value, then go back to the connection string builder, you should find two things:
The Enter information to log on to server reverts to Use a specific user name and password, so if you then click Test connection, the test unsurprisingly fails.
If you then select Use Windows NT Integrated security and click Test connection again, the test succeeds.
From 2., it is evident that the "User ID" in the connection string is ignored when using Windows authentication. That doesn't seem surprising to me, since the point of using Windows authentication is that the credentials used are those of the logged-in Windows user. You've already established that if you log in on the other computer as an admin (I assume you mean a Windows administrator account), the connection succeeds, so I'd have thought that the non-admin account needs to be added to the Sql Server's recognised users if you're wanting to connect using that ID (though I confess it's not at all clear to me whether you're actually trying to connect using Windows authentication of a specific Sql Server account).
If you're still stuck try using e.g. the Microsoft OLE DB Driver for SQL Server instead of the SQL Server Native Client. You might also single-step through this article:
https://social.msdn.microsoft.com/Forums/en-US/523c7b7e-6216-4790-87cb-945f3c1f4c5e/can-not-connect-to-microsoft-sql-server-express-2012?forum=sqlexpress
Also, google
sql server express 2008 remote "secpol.msc"
and note articles such as this one
https://social.msdn.microsoft.com/forums/sqlserver/en-US/1f5221bf-f5c3-4307-836b-a4f9dc07f02f/very-strange-remote-connection-issues
We've got a mirrored SQL server 2012 database setup on Azure VM's - two servers plus a witness, all using client certificates, with SQL logins with the same SID set.
When testing our app from a different VM, everything works as expected when we manually failover the database, there's a one second wait and then it continues to operate quite happily.
If we then do another manual failover, ie moving the principal back to the original server, the app errors and throws a 'no such host in known' error. Recycling the app pool fixes the issue, but this clearly isn't workable in production when one of the servers is updated followed by the other at some later point (both are in an availability set).
The host not known error is somewhat baffling as it was communicating with it happily before the initial failover, and will again after the app pool recycle.
Here's the connection string as it is right now, after a lot of faffing around:
"Data Source=server1,1433;Failover Partner=server2,1433;Initial
Catalog=;MultipleActiveResultSets=True;User Id=user;
Password=password; Network=dbmssocn;Connect Timeout=60; async = true;"
providerName="System.Data.SqlClient"
The app is running on .net 4.5.2, so should be up to date with hotfixes, and we're out of ideas after much Googling with Bing.
I've just solved a problem that I had that looks very similar to your problem. I'd get the host not known error whenever the database switched from the first one listed in the web.config file to the failover one. It was fine switching from the failover to the primary.
The problem that I had was that I set up the database mirroring using server names but my web server did not know the database servers by name. Once I fixed this, I was able to get the failover working smoothly both ways.
This is what I think was happening:
I set up the mirroring using the names SQL1 and SQL2 as the principal and mirror servers
I have their ip addresses in my connection string: 10.1.1.5 and 10.1.1.6
The application tries to get to the first server 10.1.1.5 and succeeds and is then told that the mirror server is SQL2
SQL1 goes down and the database is successfully switched to the mirror server.
The web application attempts to connect, fails and determines that it should try the second server.
It tries to connect to SQL2, which it doesn't know, and fails with the message that the host is unknown.
This answer would only apply to your situation if you actually put ip addresses in your web.config and that server1,1433 and server2,1433 were actually masking place-holders for the ip addresses that you actually used.
I haven't really solved the naming issue though. I just added the two database server names to the HOSTS file which isn't an acceptable situation but does prove my theory on what my problem was.
I am researching a setup just like you have and upon reading this and the response by Steve Kaye, I'm wondering if you have SQL browser running. Take a look at this article for how SQL browser comes into play:
http://blogs.msdn.com/b/spike/archive/2010/12/15/running-a-database-mirror-setup-with-the-sqlbrowser-service-off-may-produce-unexpected-results.aspx
I have read in many forums that mapped drives are not accessible from a service as no user is logged on.
Question 1) I tried making my service as a log on - as some account and i had my network drive mapped in that very account. The service still cannot access it. Why?
Question 2) From the same sevice, i invoke another process. Under what user account will the process run?
Thanks
1) Use UNC paths instead, then you do not need access to mapped drive letters. As to why you cannot access them even when running in the same account, it is hard to say for sure without seeing your actual code.
2) it depends on how you are launching the process. If you use ShellExecute() or CreateProcess(), then it runs in the user account of the calling thread. If you use CreateProcessAsUser(), CreateProcessWithLogonW(), or CreateProcessWithTokenW(), then it runs in the user account that you pass in.
I have faced similar problem wile running JBoss in service mode, my Java code was not able to access Mapped Drive even if i execute the service even after changing "Log on as:" option to the same user who has mapped the drive.
Then I figured out that if I can map the drive using the same service, then it should work.
And finally, adding just a simple command at top of service.bat file resolved the issue.
net use x: \\SERVERNAME\SHARENAME
Services don't have access to mapped drives on XP and beyond, since mapped drives are a per user resource, so they depend on who's logged in. Since it's possible for no-one to be logged in, it's possible that there are no mapped drives.
Your service may map a drive itself.
We use stateful DataSnap servers for some business logic tasks and also to provide clientdataset data.
If we have to update the server to modify a business rule, we copy the new version into a new empty folder and register it (depending on the Delphi version, just by launching or by running the TRegSvr utility).
We can do this even while the old server instance is running. However, after registering the new version, all new client connections will still use the currently running (old) server instance. All clients have to disconnect first, then the new server will be used for the next clients.
Is there a way to direct all new client connections to the new server, immediately after registering?
(I know that new or changed method signatures will also require a change and restart of the clients but this question is about internal modifications which do not affect the interface)
We are using Socket connections, and all clients share the same server application (only one application window is open). In the early days we have used a different configuration of the remote datamodule which resulted in one app window per client. Maybe this could be a solution? (because every new client will launch the currently registered executable)
Update: does Delphi XE offer some support for 'hot deployment' (of updated servers)? We use Delphi 2009 at the moment but would upgrade to XE if it offers easier implementation of 'hot deployment'.
you could separate your appserver into 2 new servers, one being a simple proxy object redirecting all methods (and optionally containing state info if any) to the second one actually implementing your business logic. you also need to implement "silent reconnect" feature within your proxy server in order not to disturb connected clients if you decide to replace business appserver any time you want. never did such design myself before but hope the idea is clear
Have you tried renaming the current server and placing the new in the same location with the correct name (versus changing the registry location). I have done this for COM libraries before with success. I am not sure if it would apply to remote launch rules through as it may look for an existing instance to attach to instead of a completely fresh server.
It may be a bit hackish but you would have the client call a method on the server indicating that a newer version is available. This would allow it to perform any necessary cleanup so it doesn't end up talking to both the existing server instance and new server instance at the same time.
There is probably not a simple answer to this question, and I suspect that you will have to modify the client. The simplest solution I can think of is to have a flag (a property or an out parameter on some commonly called method) on the server that the client checks periodically that tells the client to disconnect and reconnect (called something like ImBeingRetired).
It's also possible to write callbacks under certain circumstances for datasnap (although I've never done this). This would allow the server to inform the client that it should restart or reconnect.
The last option I can think of (that hasn't already been mentioned) would be to make the client/server stateless, so that every time the client wants something it connects, gets what it wants then disconnects.
Unfortunately none of these options are the answer you want to your question, but might give you some ideas.
(optional) set up vmware vSphere, ESX, or find a hosting service that already has one.
Store the session variables in db.
Prepare 2 web boxes with 2 distinct IP address and deploy your stuff.
Set up DNS, firewall, load balancer, or BSD vm so name "example.com" resolves to web box 1.
Deploy new version to web box 2.
Switch over to web box 2 using whatever routing method you chose.
Deploy new version to web box 1 if things look ok.
Using DNS is probably easiest, but it takes time for the mapping to propagate to the client (if the client is outside your LAN) and also two clients may see different results. Some firewalls have IP address mapping feature that you can map public IP address and internal IP address. The ideal way is to use load balancer and configure it to 50:50 and change it to 100:0 when you want to do upgrade, but it costs money. A cheaper alternative is to run software load balancer on BSD vm, but it probably requires some work.
Edit: What I meant to say is session variables, not session. You said the server is stateful. If it contains some business logic that uses session variable, it needs to get stored externally to be preserved across reconnection during switch over. Actual DataSnap session will be lost, so when you shutdown web box 1 during upgrade, the client will get "Session {some-uuid} is not found" error by web box 1, and it will reconnect to web box 2.
Also you could use 3 IP addresses (1 public and 2 private) so the client always sees 1 address , which is better method.
I have done something similar by having a specific table which held my "data version". Each time I would update the server or change a system wide global setting, I would increment this field. When a client starts it always checks this value, and will check again before any transactions/queries. If the value was ever different from when I first started, then I needed to go through my re-initialization logic, which could easily include a re-login to an updated server.
I was using IIS to publish my app servers, so the data that would change would be the path to the app server. I kept the old ones available, to respond to any existing transactions that were in play. Eventually these would be removed once I knew there were no more client connections to that version.
You could easily handle knowing what versions to keep around if you log what server the client last connected too (and therefore would know about).
For newer versions (Delphi 2010 and up), there is an interesting solution
for systems using the HTTP transport:
Implementing Failover and Load Balancing in DataSnap 2010 by Andreano Lanusse
and a related question for the TCP/IP transport:
How to direct DataSnap client connections to various DS Servers?
I have an ASP.NET MVC application that I'm working on. I've been developing it on Windows Server 2003 with IIS6 and SQL 2008 Express, and everything was working great. I recently decided to try out the Windows 7 beta, so now I'm using IIS7, and have run into a problem with connectivity to my database that I can't seem to figure out.
I can run/debug the app just fine, but whenever I try to access a page that needs to access the database, I get the following error:
"Cannot open database "MyDatabaseName" requested by the login. The login failed.
Login failed for user 'IIS APPPOOL\MyApplicationName'."
I've obviously got some security configuration setup incorrectly, but I can't seem to find any good documentation on how to set it up correctly. I've tried giving NETWORK SERVICE permissions on the database, but that didn't seem to work. Anyone know what I need to do to give "IIS APPPOOL\MyApplicationName" permissions to this database? Am I missing something obvious?
Thanks...
If you are NOT using Active Directory, then ignore all of the other solutions mentioned here. The confusion stems from the new ApplicationPoolIdentity setting default in IIS 7.5+ (MS keeps changing the identity mechianisms)
Open SQL Management Studio, connect to your local machine as an admin.
Expand the Security branch.
Right click on Logins and select New Login
Into the Login Name field, type "IIS APPPOOL\MyApplicationName". Do NOT click the search button. The user profile dosn't actually exist on the local machine, it's dynamically created on demand.
While you're looking at it, don't forget to add the user to a database or a server role.
The error means the web application doesn't have access to your database. On Windows 7 / IIS 7, by default each application pool has its own user. It seems the idea is to improve security by restricting what that web application can do (in case it gets compromised and controlled from the outside). You can change what user the application pool is running under but that will defeat its own purpose. A better way seems to give the pool's user the needed permissions (and not a bit more).
On the SQL Management Studio connect to the server you want your web app to connect (tested with SQL server 2008). Go to
Security -> Log ins
right click, New Log in. In the form that comes up leave everything as default except username, where you have to type whatever username the web app is trying to use, in this case 'IIS APPPOOL\MyApplicationName'. Note that the search function of that dialog fails to find or check as valid that user, but nevertheless it works.
Still on the SQL Management Studio connected to the server go to
Databases -> *YOUR-DATABASE* -> Security -> Users
right click and New User. I'm not sure if the user name field there has any effect, I just set it the last part of the username, like MyApplicationName. Then I've set the login name to IIS APPPOOL\MyApplicationName. You can click on the ... button and use the check and search, this time it works. If you don't do the previous step, the user will not be present here. Then give it whatever permissions you want to this user, like db_datareader.
And that's it, you've given permission. If lack of permissions was your problem, then it should be solved (or at least, I've just solved it that way).
I have a total amount of 2hs of experience with IIS and about three weeks with SQL Server and less than two months with Microsoft technologies so take my advice with a grain of salt, I can be totally wrong. (If another person can confirm these are the right steps, feel free to remove the last warning).
Here is an article that explains why AppPoolIdentities are in use; basically, it's about enhanced security: http://learn.iis.net/page.aspx/624/application-pool-identities/
(That article claims I can use these virtual accounts just like any regular account but on my Windows Server 2008 that does not seem to be possible; adding e.g. IIS AppPool\DefaultAppPool just produces an error: "The following object is not from a domain listed in the Select Location dialog box, and is therefore not valid.")
Erick Falsken is right, however he is missing the User Mappings. So right click on the new
IIS APPPOOL/DefaultAppPool, click on Properties and then check boxes for:
1) databases master and yourdatabase
2) db_owner and public
This error usually means that the user that your site is running as (or more to the point the application pool), does not have permissions to use the DB. You can either check in IIS what user the pool is running under and give them permissions, or instead change your SQL connection string to not use trusted authentication and supply the credentials of a user that does have permission in the connection string.
Edit:
If you right click on the pool Identity section and go to properties, it should come up with a box that lets you either choose from 3 builtin system accounts, or specify your own account. Either give one of the builtin accounts permission for the DB, or use an account that has permission. Or leave it as is and change your connection string.
Well...changing the ApplicationPoolIdentity property and setting it to NETWORK SERVICE seems to have fixed my problems. Not sure if that's the "right" way to do things or not (as in, I'm not sure if that's the recommended way to do things in IIS7 or not), but it seems to at least be working and has gotten me past this hang-up for now. Thanks.
I'm familiar with the idea of giving permissions to the user that the application is running under...my problem is that in IIS7, the "user" seems to be virtual or something strange like that. Prior to me changing the "Identity" property of the Application Pool properties to NETWORK SERVICE, it was set to "ApplicationPoolIdentity", and the error I was getting was that "IIS APPPOOL\MyApplicationName" didn't have access to the database. When I attempted to add the "IIS APPPOOL\MyApplicationName" user to the database, it didn't appear to exist...not that I could find anyway.
So my ultimate problem is not understanding or being able to find any good documentation on how the IIS7 security model works. When I created the application, it seemed to create an AppPool with the same name just for this application. I don't know exactly what changes I need to make to give the application and/or the user it runs under privileges to the database, considering the fact that the user that the AppPool runs as doesn't appear to actually exist.
As I mentioned, changing the Identity of the AppPool to NETWORK SERVICE seems to have worked for now, but I'm trying to find out what the best practice is for this kind of thing under IIS7. Thanks.
leave the hard problems for someone else -
create a sql user and use SQL Auth. :D
If you follow Mr. Fernández' advice, you will get everything working. This is the new way of giving least privilege to a site.
So don't do the easy, less secure thing (NETWORK SERVICE). Do the right thing. Scroll up. ;)
Using Trusted Connection in Windows Authenticated Mode:
OS: windows 7 32 bit
IIS 7, Sql Server 2008 R2 Express
Connection String:
cn.open "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=test;Data Source=mycomputername\sqlexpress;" (if instance name is sqlexpress or whatever instance name you have used)
If you are not able to connect sql server using windows mode authenticated connection to sql server 2008.
NT AUTHORITY\IUSR Account might not have permission in sql server to authorize connection with database.
Connect Sql server using windows authentication mode.
Expand Security node.
Select NT AUTHORITY\IUSR (IF NOT THERE THEN ADD NEW LOG IN FOR THAT)
Click on "User Mapping" under Select a page at Log-in properties window.
Select the database that you are trying to connect.
Select following permissions from "Database role membership for:......"
1. db_datareader 'this allows to open connection
2. db_datawriter 'this allows to fetch data records from datatable
The first step is to verify which account your website is running under. Create a simple aspx page with:
<%# Page Language="C#" %>
<% Response.Write(System.Security.Principal.WindowsIdentity.GetCurrent().Name); %>
If you're using windows authentication the WindowsIdentity account will need to have a login in your SQL Server. Under Security -> Logins -> Login New you'll want to add whatever name that was displayed by WindowsIdentity and make sure Windows authentication is selected.
If you ever happen to move your database to a separate machine you'll have to create a domain account and use impersonation in your web.config. Google <identity impersonate="true"> for more info.
If you look in the description of the field it states that running under "Network Services" account is the recommended account to use. Not sure why in Win7 it defaults to the ApplicationPoolIdentity setting.
I have the exact same issue. I'm running Windows 7 RC. When I'm trying to usa a .mdf file (located in App_Data), there is now way to make that thing work. I did try to change the AppPool's identity for LocalSystem, but it simply won't work.
If I use a "standard" database, then it will work if I'm using LocalSystem, but it won't work with the famous 'IIS APPPOOL\DefaultAppPool'.
I find it a bit disturbing not to find any information on that matter, it seems that the 'IIS APPPOOL\DefaultAppPool' user is totally useless if you are using a database of any kind...
I have it running, but I'm also bit frustrated not to understand the security model, as stated by ryexley.
yes, the app pool identity method doesn't work like they say (not in IIS7 anyway) it's supposed to. I think there are hackers at MS who make this security convoluted on purpose so you take the path of least resistance and leave your system less secure (so they can hack into it later). - just kidding, but really, their security model is pure insanity, no straightforward (step by step) instructions anywhere on MSDN - nada, zip!
I faced same problem between (SQL2008 that is installed on standalone Win-server2003 server) and (IIS6 with ASP.NET3.5 that are installed on standalone Win-server2003 server).
Where, IIS tries to access SQL2008 using some user in the domain "domain\username".
I removed following option out of connectionstring, and every thing works fine now.
Integrated Security=True;
Open SQL Management Studio, connect to your local machine as an admin.
Expand the Security branch.
Right click on Logins and select New Login
Into the Login Name field, type "IIS APPPOOL\MyApplicationName". Do
NOT click the search button. The user profile dosn't actually exist
on the local machine, it's dynamically created on demand.
Select Database in User Mapping
Select sysadmin in Server Roles