How to set a proxy for MySQL in Java? - java

This question may seems duplicate, but it’s really not. I have read many of other questions and answers from stackoverflow and also other website but non would match to my requirement.
In most of proxy questions, the matter is just to connect from X => Z going through Y as proxy.
My requirement is to change the query coming from X in proxy(Y) and send it to Z and then getting the result back to the X.
Here is a little more explanation:
I want to make a daemon service which act as proxy (localhost:3310) for MySQL database(localhost:3306) no clients know the address of database, they just know the ip address of proxy thinking it’s the database. So they try connection to it by hostname(localhost:3310) and valid MySQL username and password.
Now when a query comes to the port 3310, the proxy which is to be in java just changes the query say for example (select name from employee; => select substr(name,1,3) from employee;) and send the changed query to the MySQL Server and get the reply back to the user application (Desktop/Web).
(How) Is it possible to do so in Java?

Related

Code showing username and password for connecting to server

I'm writing a method that make it possible for my Java program to create a database connection that will eventually make me able to access it from other classes/methods.
public class DatabaseConnection
{
private Connection databaseLink;
public Connection getConnection()
{
String url = "jdbc:mysql://localhost/DBname";
try
{
Class.forName("com.mysql.cj.jdbc.Driver");
databaseLink = DriverManager.getConnection(url, "fakeUsr", "fakePsw"); //these are not the real username/password
}
catch (Exception e)
{
e.printStackTrace();
}
return databaseLink;
}
}
I've got a couple of issues:
1)people not using my computer will not be able to get into my server since I wrote "localhost":
String url = "jdbc:mysql://localhost/DBname";
2)I've typed the real username and password instead of "fakeUsr" and "fakePsw".
The thing is: I'm quite sure that the average user of my program should NOT be able to access that information. Is there any other way to permit access to a DB without making username and password readable by virtually anyone getting access to my source code?
For issue n. 1: I tried to type my IP address instead of "localhost" here:
String url = "jdbc:mysql://localhost/DBname"; //changed localhost to my IP address
but then I get "Communications link failure".
For issue n. 2: I have literally no idea how to solve this. I've never coded a program that needs access to a DB so I had to improvise a bit for that.
About Issue #2:
There is no secure way of storing the password inside the code itself. You can of course try to encrypt the password, but then your code has to decrypt it when the connection is established and therefore the encryption key is visible virtually "to all that have access to your source code". With this key, it is possible to get to the real password, just a little bit more complicated.
The only secure way is to have the user enter the login credentials by his own. Either low level (program arguments when starting your application) or by some form of "login dialog", if the application has a GUI.
A third option would be to create a technical user with restricted DB access, depending on the application you are working on. But this usually causes security issues.
You could create your application such that it sends an https request and authenticate itself against a webserver. What you use to authenticate is up to you: Client IP, username, password, client certificates, ...
Once authenticated, your webserver could transfer a one-time username/password that the client uses to login into your database.
The advantage here is that you can still control whether the user gets full or restricted access, or gets no password any more for whatever reason. And there is no security hole in your application.
1⁠) Most Internet providers don’t allow ordinary users to accept incoming socket connections, both for security reasons and because the network traffic can quickly overwhelm consumer grade networks. You will have to either purchase a commercial Internet connection which allows incoming connections, or look for a server you can lease or borrow. I’m afraid I don’t know what options are available.
2⁠) As MrFreeze correctly pointed out, there is no way to safely embed credentials in an application. No matter what you do to obscure your database login credentials, someone can always decompile your program and figure out how you are decrypting those credentials. The only truly safe solution is to tell users you trust what the credentials are, then write your application so the user must enter them.
Side note: Class.forName("com.mysql.cj.jdbc.Driver"); has not been needed for many years. You can remove that line.

Java - How to fetch email address from phpMyAdmin and send using javamail

I've designed ForgotMyPassword.java jFrame Form on NetBeans IDE 8.2
wherein I'm using phpMyAdmin for fetching the E-Mail Address of registered users from it and sending it to their E-Mail Addresses through MYSQL Database using JavaMail
I basically want to fetch the E-Mail Address of registered users from it and send it to their E-Mail Addresses through MYSQL Database using JavaMail as One Time Password (OTP) recovery option
Here's the source code :
String username = usrnmfield.getText();
String email = emailID.getText();
String[] to = {"emailaddr#gmail.com"};
Connection conn=null;
PreparedStatement pstn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
Connection db = DriverManager.getConnection("jdbc:mysql://localhost:3307/app" , "xxxx" , "xxxx");
pstn=db.prepareStatement("select * from register where USERNAME=? and EMAIL=?");
pstn.setString(1,username);
pstn.setString(2,email);
ResultSet i=pstn.executeQuery();
if(i.next())
{
if(JavaMail.send
("abc#gmail.com",
"xxxx",
to,
"Hello world",
"Thank you for reading my post"))
{
JOptionPane.showMessageDialog(null , " Please Check out your Inbox for any Password sent by us to you ");
}
}
else if (usrnmfield != i && emailID != i)
{
JOptionPane.showMessageDialog(null, "Wrong Username or E-Mail ID");
}
} catch(HeadlessException | ClassNotFoundException | SQLException e) {
JOptionPane.showMessageDialog(null, e);
}
}
Some remarks and adjustements that could help:
Concerning your application design you should strongly consider another architecture. It is far not recommended to let a client (desktop) app work directly with the SQL database for security matters. Implementing the whole security on the client-side is obviously a bad idea (and will get bypassed easily) as well as it will be unmanageable. Consider using a centralized secure database on a distant also secure server that provides state-of-the-art authentication and authorization mecanisms (eg. through REST-API over HTTPS). Server-side security frameworks include Keycloak, SpringSecurity, Apache Shiro, JaaS... By searching the Web you will see that your design is not so common. Moreover for OTP the use of a Web server or simply remote exchanges seem obvious (and you will need them). You may also consider implement logging through a centralized LDAP server.
Name your fields in the select statement. Eg. "select password from register where ..." so that you know what you expect in order OR use the field name when using select *:
ResultSet rs = ...
String myValue = rs.getString(1);
String myValueBis = rs.getString("password");
Always surround your database queries with a try-finally block in order to close your ResultSet, the prepared statement and eventually the connection (if not reused) and preferably in this order.
I don't see the purpose of this condition:
else if (usrnmfield != i && emailID != i) { ...
You are comparing text fields against a ResultSet but neither the value contained in the text nor the values of the current row of the ResultSet (cf. 1). This makes no sense.
If you want to allow you user to retrieve its password based on its username or its e-mail you should consider using an "OR" (instead of "and") in your SQL statement.
When using JavaMail you must make sure that your Session contains enough information to send an email. It is generally the first step in any JavaMail app to create a javax.mail.Session object. So you need to configure the smtp server or relay, eventually the port and authentication. As you don't show the code of your JavaMail class I suggest you put it in your original question if you have any issue about it and clarify what is the problem (if any).
Generally speaking if you consider using this app for commercial use or some serious purpose you should also quickly think about storing your passwords in an encrypted way (eg. as SHA-256). And also think about not sending the password via E-mail (it will out come naturally if you only store the hash of the users' password...) but instead propose them a secure way to reset/renew it.
I think you should update your question with more code (more finalized and cleaner preferably) and be more precise about your issue. I would not be surprized that a moderator flags your question as too "general" or obscure.

querying remote mysql database from java application

I want to be able to able to get a connection to a remote mysql database from a hava application. That is suppose i have a database server in london with user table, and another database server in paris with a product table and i want to be able from anywhere to get connection to these 2 databases and perform operations on them separately from a java application. My hope is to hide details such as ip address where the servers are located. I just want a kind of handle that abstract the lower level details for each of the servers and using this handle get a connection in a java application. Any help will be highly appreciated
I think that this works for me, if it is what you are searching for:
try {
connection = DriverManager.getConnection("jdbc:mysql://" + host + "/" + database, username, password);
Statement stm = connection.createStatement();
stm.execute("SOME PIECE of SQL CODE HERE");
} catch (SQLException e) {
}
Talking about address and that kind of stuff, if just you will have acess to the application, there's no problem to have your mysql data in the code. But if you will send this code for another people, you might need to create a client/server based application to avoid losing your credentials.

Access denied for User 'root'#'localhost' (using password: YES )

I would like to connect with my local MYSQL data base, which is installed along with XAMP server. I created a new User ie, " NewUser " and its password is "password". I given all PRIVILEGES to this user.
I write the code to connect with data base by using user "root" (No password for this user).
Its connected . Like bellow..
return DriverManager.getConnection("jdbc:MySql://localhost/database_name","root","");
Now I wrote the code to connect with same data base by another user ie, "NewUser" and its pasword "password"
return DriverManager.getConnection("jdbc:MySql://localhost/database_name","NewUser","password");
but its not connected.
The error in console is
java.sql.SQLException: Access denied for user 'NewUser'#'localhost' (using password: YES)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4120)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4052)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:925)
at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1704)
at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1250)
at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2465)
at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2498)
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2283)
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:822)
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
at sun.reflect.GeneratedConstructorAccessor207.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:404)
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:317)
at org.eclipse.datatools.connectivity.drivers.jdbc.JDBCConnection.createConnection(JDBCConnection.java:214)
at org.eclipse.datatools.connectivity.DriverConnectionBase.internalCreateConnection(DriverConnectionBase.java:105)
at org.eclipse.datatools.connectivity.DriverConnectionBase.open(DriverConnectionBase.java:54)
at org.eclipse.datatools.connectivity.drivers.jdbc.JDBCConnection.open(JDBCConnection.java:73)
at org.eclipse.datatools.enablement.internal.mysql.connection.JDBCMySQLConnectionFactory.createConnection(JDBCMySQLConnectionFactory.java:28)
at org.eclipse.datatools.connectivity.internal.ConnectionFactoryProvider.createConnection(ConnectionFactoryProvider.java:83)
at org.eclipse.datatools.connectivity.internal.ConnectionProfile.createConnection(ConnectionProfile.java:359)
at org.eclipse.datatools.connectivity.ui.PingJob.createTestConnection(PingJob.java:76)
at org.eclipse.datatools.connectivity.ui.PingJob.run(PingJob.java:59)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:53)
I give the host type while providing PRIVILEGES to this user, as " any host" ie."%".
If I change this to " localhost " or "127.0.0.1" its working.
So How can i use my database with " anyhost " PRIVILEGES to the particular user like "NewUser" .
If I got success here then I successes in connection to client live Data base..
Thanks to all and please let me out from this one.....
Since the first specified code works and also based on the reported trace, i'm pretty sure the problem is on the database, not the code syntax.
Based on the Mysql version, please try as an alternative to set privileges without specifying the any host (%) as based on Mysql documentation,
The simple form user_name is a synonym for user_name#'%'
Also flush privileges immediately after using FLUSH PRIVILEGES;
Just to make sure everything is correct, also run a
SHOW GRANTS FOR NewUser; and check if NewUser appears in the list with the corresponding permissions.
your URL is meant to be all lowercase -- `jdbc:MySql://localhost/database_name"
Is your database really called database_name?
Please try this syntax
return DriverManager.getConnection("jdbc:mysql://localhost/database_name?user=NewUser&password=your_password_here");
(just replace your password where it says "your_password_here")
EDIT - SECOND GUESS:
Its possible you have firewalled yourself by blocking 192.168.x.x range.
i assume you running windows. open up command prompt, type "ipconfig" press enter. see your ipv4 adress (should be something like 192.168.1.x)
Be sure your antivirus/firewall program permits connection from 192.168.1.x (which is yourself) and then try using that instead of "%" or "localhost"
If this doesn't work, close all your firewall/antivirus and try again.
Also try reloading privileges either by:
restarting xampp
FLUSH PRIVILEGES;
In order to give users access to your database, you need to specify a host where they should be allowed to connect from.
But please be careful: Even if you use a wildcard (%) as the host name, the user cannot connect from localhost. They can connect from ANY host, but not from localhost.
When connecting from localhost, I assume your mysql installation assumes you to be an anonymous user.
In order to allow a user to connect from localhost, you need to add a separate user whith "localhost" in the host field.
For more details, please refer to the MySQL documentation
Two of the accounts have a user name of monty and a password of
some_pass. Both accounts are superuser accounts with full privileges
to do anything. The 'monty'#'localhost' account can be used only when
connecting from the local host. The 'monty'#'%' account uses the '%'
wildcard for the host part, so it can be used to connect from any
host.
It is necessary to have both accounts for monty to be able to connect
from anywhere as monty. Without the localhost account, the
anonymous-user account for localhost that is created by
mysql_install_db would take precedence when monty connects from the
local host. As a result, monty would be treated as an anonymous user.
The reason for this is that the anonymous-user account has a more
specific Host column value than the 'monty'#'%' account and thus comes
earlier in the user table sort order. (user table sorting is discussed
in Section 6.2.4, “Access Control, Stage 1: Connection Verification”.)
GO to users/privileges/edit privileges/
change password or select no password
update the password in hibernate config file and restart the server.

Problems logging into MSSQL server from Java

I am trying to connect to MSSQL server 2008 on my localhost, but I am getting Errors
WARNING: ConnectionID:2 Prelogin error: host 127.0.0.1 port 1434 Error reading prelogin response: Connection reset
this error repeats like 20 times very quickly, then i get
com.microsoft.sqlserver.jdbc.SQLServerException: Connection reset
I suspect this is some wrong configuration of server. I can connect to external servers with no issues. I can also connect via management studio with no problems.
Please help me, I am getting sick of this issue :|
1) TCP protocol for MSSQL 2008 is disabled by default. You need to enable it from SQL Configuration Manager (in the same [Start], Programs folder as MSSQL):
http://msdn.microsoft.com/en-us/library/ms190425%28v=sql.105%29.aspx
2) To use TCP connections (even on localhost!) you need to allow MSSQL in Windows Firewall:
http://technet.microsoft.com/en-us/library/cc646023.aspx
3) You don't necessarily need to use TCP/IP in order to access MSSQL:
http://msdn.microsoft.com/en-us/library/ms187892%28v=sql.105%29.aspx
'Hope that helps!
To connect to MSSQL Server from a Java application, you need to use the JDBC API. The JDBC API provides classes and methods that connect to the database, load the appropriate driver, send SQL queries, retrieve results etc.
HOW TO CONNECT TO THE DATABASE A ‘Connection’ object represents a connection with a database. To establish the connection, use the method ‘DriverManager.getConnection’. This method takes a string containing a URL which represents the database we are trying to connect to. Below is the sample code for establishing a connection:
private String DATABASE_URL = "jdbc:odbc:embedded_sql_app"; // establish connection to database
Connection connection = DriverManager.getConnection( DATABASE_URL,"sa","123" );
Detailed discussion about the Database URL and how to create it can be found in the resource provided at the end of this post.
QUERYING THE DATABASE The JDBC API provides three interfaces for sending SQL statements to the database, and corresponding methods in the ‘Connection’ interface create instances of them. 1. Statement - created by the ‘Connection.createStatement’ methods. A ‘Statement’ object is used for sending SQL statements with no parameters.
2. PreparedStatement - created by the ‘Connection.prepareStatement methods’. A ‘PreparedStatement’ object is used for precompiled SQL statements. These can take one or more parameters as input arguments (IN parameters).
3. CallableStatement - created by the ‘Connection.prepareCall’ methods. ‘CallableStatement’ objects are used to execute SQL stored procedures from Java database applications.
RETRIEVING THE RESULT A ‘ResultSet ‘is a Java object that contains the results of executing a SQL query. The data stored in a ‘ResultSet’ object is retrieved through a set of get methods that allows access to the various columns of the current row. The ‘ResultSet.next’ method is used to move to the next row of the ‘ResultSet’, making it the current row. The following code fragment executes a query that returns a collection of rows, with column ‘a’ as an ‘int’, column ‘b’ as a ‘String’, and column ‘c’ as a ‘float’:
java.sql.Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");
while (rs.next()) { // retrieve and print the values for the current row
int i = rs.getInt("a");
String s = rs.getString("b");
float f = rs.getFloat("c");
System.out.println("ROW = " + i + " " + s + " " + f); }
This is just a brief introduction on how to interact with a database from Java. For more details on the items discussed above as well as information on passing parameters, executing stored procedures etc. please refer to the following resource: ( http://www.shahriarnk.com/Shahriar-N-K-Research-Embedding-SQL-in-C-Sharp-Java.html#Shahriar_N_Embedding_SQL_in_Java ) Here, you will also find information on how to interact with a database programmatically; i.e. without using SQL. Hope you find this useful.

Categories