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.
Related
sorry if this is a super easy question, but I have been googling a lot and I have failed to get a result.
I am looking for a way that I can either purchase or host so that I and others can connect remotely.
I have all my code working locally, but I would just like to know how to host for others to join.
There are many ways to provide a MySQL server instance that's accessible over the public internet.
For this to be secure, you'll need to use transport layer security (TLS) for the connections from JDBC clients to the server. Even when you do this you'll need to be vigilant about the security of your database.
If your users' data is sensitive, or needs protection against cybercriminals, this is probably a bad idea. (Sensitive data: personally identifiable information, payment/credit card data, health data, personal financial data). It's much safer to put MySQL instances behind solid firewalls, and use web services and/or web sites to grant access to the public internet.
You could run a virtual machine instance on AWS or some other cloud service provider, and put MySQL on it. AWS also offers a Relational Database managed service you could use.
You could use a GoDaddy style service, and enable remote access to your own MySQL instance on that service.
You could put a MySQL instance on a machine in the DMZ -- the publicly visible segment -- of your home or office network. Most home and small-office routers allow a particular port on a particular machine to be made visible to the public network.
Be careful, k?
Currently I have a Java application which performs all I wanted and the limitation
in it is "It only resides on the Local machine for which it needs to work". I have the Access Databases located on a Remote Server and I install the Java app on the remote server to connect the databases using a connection string jdbc:odbc:DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=D:\\DATA\\DPPI\\DATA\\DPPI\\DPPIPR01.mdb;
It connects to Access Databases and do all the business logic with them.
Enhancements (to be done):
Making the application online - not a big issue.
Connecting the databases remotely - its the only concern.
If I make the Application Online the Access Databases need to be connecting through network (somewhat like IP or some web address).
Problem:
But after going through this Connect to Access database remotely It seems my requirement can not be completed.
Is there any way if I'm able to upload the database to the online web hosting server and access the database from there only? If yes, then how should I do the connectivity since Access Database connects by giving the fully qualified name containing drive letter and all.
But how should I proceed further so that I may be able to connect the mdb Databases remotely?
ADO Solution:
But after going through the link: http://webcheatsheet.com/ASP/access_connection_strings.php, it seems we can perform remote Access Database connectivity.
The solution for the ADO is something like:
connectionString="Provider=MS Remote; Remote Server=http://your_remote_server_ip;" &_
"Remote Provider=Microsoft.Jet.OLEDB.4.0; Data Source=c:\your_database_name.mdb"
I'm a tad confused to how Access Database we can connect.
There is one more question in my head.
I'm making use of Type-1 Driver. Should the Type-4 Driver support the remote connectivity?
If your application is a server side application (like a web application) and your server's OS is Windows then theoretically it is possible to use your Access database. In this scenario, the Access database is local to your application. In your connection string you can simply use the path to the Access database inside your server's file system.
But keep in mind, that Access is a desktop database not made to use it as a server database. This can lead to poor performance and maybe system crashes. And it is possible that there are some licencing issues for this use case.
So even it may be possible to use Access with a server application it is strongly recommended to use a real server database like MySQL, MS SQL Server, etc. Even an embedded database like Apache Derby or H2 would be a better fit.
If your application runs at client side like a fat client, then your only chance to use Access is to put it on a network filesystem, so it is visible from every client. But this works only inside a LAN. If you cannot put it on a network filesystem then you have to use a real server database.
Do not use Provider=MS Remote (RDS) for new development. Here is a quote from the MSDN article
Microsoft OLE DB Remoting Provider (ADO Service Provider)
Important
Beginning with Windows 8 and Windows Server 2012, RDS server components are no longer included in the Windows operating system (see Windows 8 and Windows Server 2012 Compatibility Cookbook for more detail). RDS client components will be removed in a future version of Windows. Avoid using this feature in new development work, and plan to modify applications that currently use this feature. Applications that use RDS should migrate to WCF Data Service.
As others have suggested, you should seriously consider using a different back-end database for this particular application.
What if I'm able to call another java application residing on the Server housing the Microsoft Access Databases? Can you please let me know if it can be the solution such that I will have the division of my application into two:
1. The Online java Application performing 2 things: Accepting the requests coming in and waiting for the response to come from another application running on the Server housing the Microsoft Access Databases.
2. The Java application installed on the Server housing the Microsoft Access Databases only responsible for connecting and returning the DTO (Data Transfer Objects) -or some kind of objects in Collections.
So, I would expect a serverside program to handle the communication with the DB and the client application would communicate with the server app.
Please let me know if I should proceed in this manner.
it can be done by marking the traffic and queueing the traffic from the server---to----remote site ---(QOS..quality of service ) .....the two sites will be connected through VPN methods to reduce the unnecessary hops that will improve the latency plus add the security , thus server and remote site will logically act as if they are on the same network (LAN)
regards ,
Ali Rehan
I have already developed a JAVA SWING Application. I want to install this application in several computers which all have access to internet .
So where should I place my MYSQL Database ? All these computers should have the ability to access the same database via the internet.
It's not very common to allow access to a database directly over the internet for security (authentication authorization, encryption) and performance reasons. In most cases, you would create a web-based server application which can perform database operations, enforcing business, domain, and security rules. The client application makes calls over the internet (using REST calls, AJAX calls, or something proprietary), and gets the results back from the server.
In your case, since your client software is Java, you may want to research Java Servlets and run something lightweight like Tomcat as a serer.
Please see this page and this page for an explanation of client-server relationships.
Put your database in host that is accessable by Internet.
For each of the external ip addresses of each of the Applicaton host create a user on mysql.
GRANT ALL PRIVILEGES TO database.* to `user1`#`APPLICATION_HOST_IP` identified by 'PASSWORD';
Now user1 will have access from APPLICATION_HOST_IP IP.
Well the possibility is limitless.. You can place it on every computer that is accessible by the others. As long as you can acces the database via network it does not really matter where it is. But if the Computers with your client Swing are all connected in LAN, than store the DB on the computer with best Performance.
As a tip use the IP, and port dynamicaly from text or entry, so u do not recompile every time u change the IP.
Chiers!!
I am developing a java applet which connects to mysql database, the applet works fine on local host but when I uploaded it and tried to run, i get an error as "communications link failure the last packet sent successfully to the server was 0 milliseconds ago.
the driver has not recieved any packets from the server"
i tried it on x10hosting and hostable, please help me if anyone knows the solution...
Are you sure your MySQL server port is really open to the public? E.g., on a publicly-routable IP address and not blocked by your routers/network? Most likely your MySQL instance is not accessible from the outside world...
...which is how it should be. It's very, very, very rarely appropriate to have an applet talk directly to your database server. The usual thing is for the applet to talk to a middle tier on your web server, which in turn talks to the database server. There's a security aspect to that (your middle-tier can defend against various attacks on your database), and there's a practicality aspect: You'll probably want to keep the chatter across the public network to a minimum, and your server can roll up the results of multiple operations into one bundle it then sends to the client.
If your MySQL server really is available to the outside world, is its host the same as the host the applet is loaded from? That's one of the security requirements for (unsigned) applets, that they can only open network connections to the same host they were loaded from. But if that were the issue, I would have expected you to get a security exception (unless Connector/J is hiding it from you).
The applet is client-side. If you want to directly connect to a mysql server this would mean each user that opens the applet should either have mysql installed or have access and credentials to the remote database. Even if your firewall allows the access it is a very bad idea to do so. If you do everyone will have access to your database.
So if you want to communicate with a remote database, use some protocol (http would be easiest, via a Servlet) to send requests to the server and receive responses generated based on the database results. For example invoking http://yoursite.com/addRecord?name=foo&email=bar#baz.com could tell the server-side application to open a (local) connection to mysql and insert a record.
I am making an application which have to be used in different pc's, and it has to share the same database. I have no idea how to do it. I am using the java as programming language and mysql as database. Please help me to do this task...
Use JDBC and connect all your app to one MySql DB Server
The way to talk to a database in Java is JDBC.
See http://download.oracle.com/javase/tutorial/jdbc/index.html for a good tutorial on how to use it.
On server-side you should create user which will be granted privileges to access your database from different foreign hosts:
GRANT ALL ON *.* TO 'someuser'#'somehost';
Read more here: http://dev.mysql.com/doc/refman/4.1/en/grant.html
On client-side you should configure database connection to use host where your database is installed. Read JDBC API reference for details.
Does a client-server model not work for you? If you have somewhere to host a server the normal method accomplishing something like this is to encapsulate your database behind the server and all clients connect to your server to exchange information.
You have a variety of options for communicating between the clients and the server:
Your server could be a simple web app where your clients all make URL calls to the server to accomplish various tasks. Implementing REST or SOAP would make the calls even easier if you're doing anything non-trivial.
RMI if your not going over the internet makes things really easy (you can get the basics of RMI in a few hours of reading).
Assuming you have the network connectivity, you can also just have each client make their own connection directly to the database. But only do this if you are on a safe intranet only.