How does the SQL Server JDBC Trusted Connection Authentication work? (ie how does the trusted connection authenticate the logged in AD user in such a transparent and elegant fashion and how can I implement a similar authentication solution for my client-server applications in Java without a database connection or any use of the existing SQL Server solution.)
Assumptions
* Working within a Windows 2003 domain
* You have access to the Windows API via JNI/JNA
It depends on the client. For example if you have a Web Browser, it can use the NTLM Authentication to pass the domain authentication of your current client to the server. In this case the browser like IE or FF supports this, and you web server needs the support for NTLM. For example here for Tomcat: http://jcifs.samba.org/src/docs/ntlmhttpauth.html
There is also the SPNEGO protcol in combination with Kerberos, as explained here: http://java.sun.com/javase/6/docs/technotes/guides/security/jgss/lab/index.html
If you have your own client, it depends on the client's framework if it is able to use the local user's security context and is able to pass it on. The page above describes this at least for a kerberos scenario.
Greetings
Bernd
PS: I am not sure if you can pass the authentication context established with the jcifs/ntmlm solution to a backend component like SQL Server. It should work with Kerberos tickets (if configured).
jTDS and Microsoft JDBC Driver both offer native Windows Authentication.
Have you looked at this question? The situation seems to be similar to yours (connecting to a SQL Server database using Windows authentication).
Related
Is JDBC connection to a remote database over the internet without SSL but authentication with username and password enabled is insecure ? Is attack like man in the middle possible for such scenarios ?
Authentication NOT implies confidentiality. SSL/TLS was born to grant the latter. So you have to use a secured connection. But I'd suggest you to not expose you DB to the Internet. Use a microservices-like pattern to isolate the DB from unwanted exposures.
It is insecure, never expose your database on internet, not even using ssl. If you really need to do so, make a ssh tunnel or configure a vpn.
Our customers connect to our databases exclusively with jdbc thin client calls on the SSL port, authenticating externally with PKI certificates in keystores. I would like to collect some of their client certificate information at logon time, as I would be able to do using OWA_UTIL.GET_CGI_ENV if they were connecting via https.
I've researched this for quite a while now, and I've found something in the SYS_CONTEXT userenv parameters called AUTHENTICATION_DATA that seems promising. However, the documentation states only that for users connecting externally with x503 certificates (do they mean x509v3?), that parameter contains "Data being used to authenticate the login user. For X.503 sessions, returns the context of the certificate in HEX2 format."
That's all Oracle has to say about that. No documentation of "HEX2 format" exists. No explanation anywhere about how to view the authentication data.
Does anyone have any experience using that data or at least reading what it really is?
I'm developing a Java Swing based app which uses JDBC to connect to a MySQL database. As such, the software directly remotely access the database from whichever computer it happens to be running on. Additionally, the app uses prepared statements to query the database and the database is hosted on a shared CPanel hosting account (if that matters).
The snippet of code I use to connect to the database is as follows (fairly standard connect code I think and all strings in all caps contain the correct contents):
String url = "jdbc:mysql://URL:PORT/DB_NAME?connectTimeout=3000";
Connection conn = DriverManager.getConnection(url, USERNAME, PASSWORD);
I have only ever successfully used the app from one IP. Before I use the app from an IP, I have to manually whitelist the IP by adding it as an allowed remote MySQL access host. If I don't add the IP as an allowed access host, the server refuses my connection and I get the resultant error:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
Then if I whitelist an IP and try to connect from it, I don't get that error and the app connects to the database properly.
This system would be okay if the app were only going to be used from one IP, but it needs to work from any IP since I cannot predict who will download and use it. The only solution I see would be to do a global whitelist of all IPs in the allowed MySQL access hosts area. However, that seems like it has many drawbacks, such as being insecure as anyone who has the correct password could log in (and would thus be susceptible to brute force attacks). This seems to corroborate the hypothesis that that method is insecure. Thus, I would like to have a system of communicating between the app and database that is IP-independent (doesn't require whitelisting all the IPs).
Additionally (I don't know if this makes sense or matters), but I believe some of the areas I expect the app to be used in block certain protocols. Thus, (I think) I would like it if the selected method of communication only used HTTP or some other widely-used protocol.
I did some research into this problem and my efforts led me to 2-tier and n-tier models of database communication. Perhaps I could do something like make a PHP page which accepts a statement and a series of parameters (plus a password to gain entry), executes the statement, and then returns the result back as JSON. However, this seems like another less-than-ideal method as it seems like it would also have security problems.
I'm sure someone more experienced and knowledgeable than I has already come across this problem and developed a solution.
Therefore, my question: What is the preferred method of connecting to a MySQL database from a Java app in an IP-independent way?
I greatly appreciate and thank you for your time.
You're on the right track:
1) If you want any arbitrary client to connect directly to your database, and the clients can have any arbitrary IP address ... then you're probably going to have to effectly disable IP security be whitelisting all possible client IP addresses.
2) On the other hand, if you only allow local access to mySql (by far the most common scenario), then you can create a web app to interface between your clients and mySql.
SUGGESTION:
Consider creating a "REST" web service that your clients can talk to.
Here's a good tutorial that might help you get started:
REST with Java (JAX-RS) using Jersey - Tutorial
Q: Does your Swing app really need to emit "raw SQL"? Or can it make "high level" queries? REST is ideally suited for the latter.
PS:
Here's another, short example that might help suggest some design alternatives with REST, mySQL and Java for you:
http://www.9lessons.info/2012/09/restful-web-services-api-using-java-and.html
You are up against the policies -- primarily the security policies -- of your hosting provider. It's generally considered insecure to allow port 3306 (MySQL) connections from the whole internet. It certainly lays your MySQL server open to trivial denial-of-service attacks. (It just takes some knucklehead controlling a botnet to send in lots of port 3306 connection attempts. They don't even have to be successful connection attempts.) If you're sharing your MySQL server with other customers of your hosting provider, they have every incentive to restrict your remote access to their server.
Most folks who build database applications for deployment on the public internet do it by providing web services to hit the database with the specific operations required by the application. The application deployed at the end-user's machine then uses HTTP (or HTTPS for security) to access those web services. In turn the web services access the database. That's what multitier operations do. You're right that there are security problems, but you can mitigate them with careful development of your web service code.
You could use SSH tunneling to handle your database access. The SSH suite of remote-access applications allows port forwarding. To use this, you would establish (authenticated and encrypted) ssh connections between your end-users' machines and your database machine, that forward port 3306. Then your users could connect to localhost:3306, and that net traffic would be forwarded to your database server. It's pretty flexible and quite secure, if not completely simple to configure.
You might also investigate using SQL Relay. It's generally used for connection pooling and management within a data center network, but it might work for this purpose.
Be careful opening up your MySQL server to the world! If you do that you may want to require the use of TLS encrypted conections.
I've got backend running on the tomcat server and client running in the browser. Application is built on Spring 3 MVC + Spring security framework. How to secure the communication ? Is there other option than just to set the server to be accessed only via HTTPS ? I've got no experience with this so it might be a stupid question, but will this affect my application and do I have to set something up in my app, when the server shall communicate with client via GET/POST request via https ?
It depends somewhat what you mean by "secure." If you want privacy, you must use TLS (SSL) as a transport.
If you're only concerned with authentication, then you have another option: Digest Authentication.
Digest Authentication allows the client (browser, usually) and the server to exchange authentication credentials in a secure manner without securing the entire communication. If you use Digest Authentication, then third parties can still:
See what data the client and server exchange
Insert themselves between the client and server and alter the exchange
What third parties cannot do is spoof the authentication or steal username/passwords in transit.
If that's not secure enough, you need TLS. You do not necessarily have to purchase a certificate. You can use OpenSSL to generate your own. This certificate will not automatically be trusted by browsers, however, so you can't really use it for public sites.
You will need to consult your server documentation for how to set up HTTPS or Digest Authentication, depending on which fits your needs.
Your application should not be affected by switching from HTTP to HTTPS, Tomcat handles this or maybe an Apache in front. It's important to understand, that HTTPS is a server-thing, not an application topic, because the client makes a connection to the server (Tomcat), not to your application. Check out the Tomcat documentation, it's pretty clear about how things work.
And, like the others said: From what you've said it's best to use HTTPS (TLS/SSL). Certificates are a bit frightning at the beginning, but it's worth to invest the time.
HTTPS is the (S)ecure form of HTTP, since you have an HTTP client server application I would certainly used HTTPS. All you need is to create an SSL certicate for your website and restrict access to your website to HTTPS only, then you are 99.99% secure.
Your certicate can be either commercial from Versign or equivalent or some open source engine.
for the clients nothing needs to be done to support HTTPS
In an interview, Interview asked me an question :
The communication between our application and the remote database must be done with https (more secure).
How could you do it? I didn't find any clue for this question in google also.
How to establish secure connection between java application and database? Please help me.
HTTPS? If your client is using something proprietary with a web server acting as an intermediary to talk to the db server it would (one would hope) be transparent between your application the & web server; simply change from HTTP to HTTPS, ditto if you’re using SQL Server web service end-points (which you can make use HTTPS).
If perhaps you mean SSL then SQL server supports encrypted connections between client and server, see this question.
Google for JDBC connection over SSL. See here for an example.
Hopefully the person who asked the question wasn't seriously thinking about exposing a database to the wider Internet. If they were, better not to accept that position.