I'm trying to move from an unencrypted JDBC connection using a username and password to log in to my MySQL database server, to a connection using SSL and certificate-based authentication. I'm using Hibernate with Spring MVC. My WebAppConfig file looks like this:
package com.****.PolicyManager.init;
import java.util.Properties;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
#Configuration
#ComponentScan("com.sprhib")
#EnableWebMvc
#EnableTransactionManagement
#PropertySource("classpath:application.properties")
public class WebAppConfig {
private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
private static final String PROPERTY_NAME_DATABASE_URL = "db.urlSSL";
private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";
#Resource
private Environment env;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
return dataSource;
}
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setPackagesToScan(env.getRequiredProperty(
PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
sessionFactoryBean.setHibernateProperties(hibProperties());
return sessionFactoryBean;
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_DIALECT,
env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL,
env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
return properties;
}
#Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager transactionManager =
new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
}
And my properties config file (application.properties) as follows:
#DB properties:
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/PolicyManager
db.urlSSL=jdbc:mysql://localhost:3306/PolicyManager?autoReconnect=true&verifyServerCertificate=false&useSSL=true&requireSSL=true
db.username=myuser
db.password=mypass
#Hibernate Configuration:
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.show_sql=true
entitymanager.packages.to.scan=com.****.PolicyManager.model
I've generated the right certificates inside /etc/mysql/certs and have edited my.cnf to point to then, but can't find any info online about how to configure my specific method of database initialisation to use certificate-based authentication to remove the need to store my database username and password in plain text on the server.
Can anyone suggest a solution or point me to a tutorial that uses this WebAppConfig.java file (hib properties, DriverManagerDataSource and LocalSessionFactoryBean) for it's configuration?
The MySQL guide has information on what to do on the client side, this bug also has some detailed information.
It basically comes done to the following steps
Create a keystore and truststore with your clients certificate
Configure your environment (or a MysqlDataSource) to use these keystore and truststore
Configure the connection URL properly (which is what you apparently already have done).
And that should be it. The key is to have the correct certificates on the client side.
More information:
Secure JDBC connection to MySQL from GlassFish
Secure JDBC connection to MySQL from Java
MySQL SSL Documentation
Related
I am having problem understanding the usage of #ConfigurationProperties. In my application properties file, all of the variables "is an unknown property" with yellow underline. I run the application but the same thing happens. Is there a way to link the configuration at application.properties to my datasource function?
If I use
spring.datasource.url = jdbc:mysql://127.0.0.1/trs?useSSL=false
it works just fine but it i use app.datasource.url it wouldn't work
My application.properties file
# Primary DataSource configuration
app.datasource.url=jdbc:mysql://127.0.0.1/trs?useSSL=false
app.datasource.username=user
app.datasource.password=pass
my primary .java file
#ConfigurationProperties(prefix="app.datasource")
#Primary
#Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://127.0.0.1/trs?useSSL=false");
dataSource.setUsername("user");
dataSource.setPassword("pass");
return dataSource;
}
For your application.properties, you need a corresponding java class to load the configuration in a bean. Like this -
#ConfigurationProperties(prefix="app.datasource")
#Component
public class DataSourceConfig{
private String url;
private String username;
private String password;
...
}
Now, where you want to use the DataSourceConfig bean, you can inject like this,
#Autowired
DataSourceConfig dataSourceConfig;
And once you have the object just do,
dataSourceConfig.getUrl();
dataSourceConfig.getUsername();
dataSourceConfig.getPassword();
I prepared website in Spring/Maven with use of MySQL db, Tomcat. I decided to use Heroku free account, because I have domain, db and Java in one place. Problem is that Heroku uses postgresql for free but mysql is payable. I would like to ask you help and explanation clearly what I should change in my application's code(pom.xml, hibernate.properties etc) to use postgresql instead of mysql. Below I show files I think should be changed. Do I have to add any new files? I beg your indulgence.
***POM.XML***
jdbc.driver.class.name =com.mysql.jdbc.Driver
jdbc.url =jdbc:mysql://localhost:3306/web_users?useSSL=false&characterEncoding=UTF-8
jdbc.user.name =root
jdbc.password =root
hibernate.hbm2ddl.auto =update
hibernate.show_sql =true
hibernate.format_sql =true
hibernate.generate_statistics=false
***HibernateConfig.java***
#Configuration
#PropertySource(value = {"classpath:hibernate.properties"})
#EnableJpaRepositories(basePackages = "com.website.dao")
public class HibernateConfig {
#Autowired
private Environment environment;
// 1. create DataSource
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driver.class.name"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.user.name"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
return dataSource;
}
// 2. EntityManagerFactory
#Bean
public EntityManagerFactory entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
Properties properties = new Properties();
properties.put("hibernate.hbm2ddl.auto", environment.getProperty("hibernate.hbm2ddl.auto"));
properties.put("hibernate.show_sql", environment.getProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getProperty("hibernate.format_sql"));
properties.put("hibernate.generate_statistics", environment.getProperty("hibernate.generate_statistics"));
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setPackagesToScan("com.website.model");
factoryBean.setJpaVendorAdapter(vendorAdapter);
factoryBean.setJpaProperties(properties);
factoryBean.setDataSource(dataSource());
factoryBean.afterPropertiesSet();
return factoryBean.getObject();
}
I am trying to implement multiple database with Spring Boot Hikari CP. I am getting
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] is defined: expected single matching bean but found 2: hikari_primary,hikari_secondary
For your reference I am attaching my spring boot datasource configuration files,
please dont go over primary and secondary naming conventions(they dont represent priorities), my requirement it to have two connection pool for two different databases.
Any help is appreciated
1.application.properties
spring.datasource.dataSourceClassName=com.microsoft.sqlserver.jdbc.SQLServerDataSource
primary.spring.datasource.url=jdbc:sqlserver://xxx.xxx.xxx.xxx:1433;DatabaseName=training
primary.spring.datasource.username=training
primary.spring.datasource.password=training
primary.spring.datasource.poolName=hikari_primary
primary.spring.datasource.maximumPoolSize=5
primary.spring.datasource.minimumIdle=3
primary.spring.datasource.maxLifetime=2000000
primary.spring.datasource.connectionTimeout=30000
primary.spring.datasource.idleTimeout=30000
primary.spring.datasource.pool-prepared-statements=true
primary.spring.datasource.max-open-prepared-statements=250
secondary.spring.datasource.url=jdbc:sqlserver://xxx.xxx.xxx.xxx:1433;DatabaseName=dev_xxxxx_core_v3
secondary.spring.datasource.username=developer
secondary.spring.datasource.password=Developer
secondary.spring.datasource.poolName=hikari_secondary
secondary.spring.datasource.maximumPoolSize=50
secondary.spring.datasource.minimumIdle=30
secondary.spring.datasource.maxLifetime=2000000
secondary.spring.datasource.connectionTimeout=30000
secondary.spring.datasource.idleTimeout=30000
secondary.spring.datasource.pool-prepared-statements=true
secondary.spring.datasource.max-open-prepared-statements=300
2. PrimaryDataSourceConfig.java
#Configuration
public class PrimaryDataSourceConfig {
#Value("${primary.spring.datasource.username}")
private String user;
#Value("${primary.spring.datasource.password}")
private String password;
#Value("${primary.spring.datasource.url}")
private String dataSourceUrl;
#Value("${spring.datasource.dataSourceClassName}")
private String dataSourceClassName;
#Value("${primary.spring.datasource.poolName}")
private String poolName;
#Value("${primary.spring.datasource.connectionTimeout}")
private int connectionTimeout;
#Value("${primary.spring.datasource.maxLifetime}")
private int maxLifetime;
#Value("${primary.spring.datasource.maximumPoolSize}")
private int maximumPoolSize;
#Value("${primary.spring.datasource.minimumIdle}")
private int minimumIdle;
#Value("${primary.spring.datasource.idleTimeout}")
private int idleTimeout;
#Bean(name="hikari_primary")
public HikariDataSource getHikariDataSourcePrimary() {
Properties dsProps = new Properties();
dsProps.put("url", dataSourceUrl);
dsProps.put("user", user);
dsProps.put("password", password);
Properties configProps = new Properties();
configProps.put("dataSourceClassName", dataSourceClassName);
configProps.put("poolName", poolName);
configProps.put("maximumPoolSize", maximumPoolSize);
configProps.put("minimumIdle", minimumIdle);
configProps.put("minimumIdle", minimumIdle);
configProps.put("connectionTimeout", connectionTimeout);
configProps.put("idleTimeout", idleTimeout);
configProps.put("dataSourceProperties", dsProps);
HikariConfig hc = new HikariConfig(configProps);
HikariDataSource ds = new HikariDataSource(hc);
return ds;
}
}
3. SecondayDataSourceConfig.java
#Configuration
public class SecondaryDataSourceConfig {
#Value("${secondary.spring.datasource.username}")
private String user;
#Value("${secondary.spring.datasource.password}")
private String password;
#Value("${secondary.spring.datasource.url}")
private String dataSourceUrl;
#Value("${spring.datasource.dataSourceClassName}")
private String dataSourceClassName;
#Value("${secondary.spring.datasource.poolName}")
private String poolName;
#Value("${secondary.spring.datasource.connectionTimeout}")
private int connectionTimeout;
#Value("${secondary.spring.datasource.maxLifetime}")
private int maxLifetime;
#Value("${secondary.spring.datasource.maximumPoolSize}")
private int maximumPoolSize;
#Value("${secondary.spring.datasource.minimumIdle}")
private int minimumIdle;
#Value("${secondary.spring.datasource.idleTimeout}")
private int idleTimeout;
#Bean(name="hikari_secondary")
public HikariDataSource getHikariDataSourceSecondary() {
Properties dsProps = new Properties();
dsProps.put("url", dataSourceUrl);
dsProps.put("user", user);
dsProps.put("password", password);
Properties configProps = new Properties();
configProps.put("dataSourceClassName", dataSourceClassName);
configProps.put("poolName", poolName);
configProps.put("maximumPoolSize", maximumPoolSize);
configProps.put("minimumIdle", minimumIdle);
configProps.put("minimumIdle", minimumIdle);
configProps.put("connectionTimeout", connectionTimeout);
configProps.put("idleTimeout", idleTimeout);
configProps.put("dataSourceProperties", dsProps);
HikariConfig hc = new HikariConfig(configProps);
HikariDataSource ds = new HikariDataSource(hc);
return ds;
}
}
4. Application.java
#SpringBootApplication
#ComponentScan("com.xxxx.springsql2o")
#EnableAutoConfiguration
public class Application
{
public static void main( String[] args )
{
SpringApplication.run(Application.class, args);
}
#Autowired
#Qualifier("hikari_primary")
DataSource hikariDataSourcePrimary;
#Autowired
#Qualifier("hikari_secondary")
DataSource hikariDataSourceSecondary;
#Bean(name= "primary_db")
public Sql2o getPrimarySql2o()
{
return new Sql2o(hikariDataSourcePrimary);
}
#Bean(name= "secondary_db")
public Sql2o getSecondarySql2o()
{
return new Sql2o(hikariDataSourceSecondary);
}
}
Spring boot is auto-configuring your application via #EnableAutoConfiguration (note that this annotation is already included in the composed #SpringBootApplication annotation). So my guess would be that you have some dependency that spring is trying to auto-configure (e.g. JPA) which uses/needs DataSource. If you can live with this, you can add #Primary to on of your DataSource Bean provider methods in order to satisfy that dependency.
So, for instance:
#Bean(name="hikari_primary")
#Primary
public HikariDataSource getHikariDataSourcePrimary() {...
Even if this should work, it would be recommended to remove auto-configuration for e.g. JPA or whatever spring boot is trying to auto-configure but you don't use/need and configure everything manually as it suits your application needs. Have two databases is certainly a custom configuration and does not conform to the spring boot easy-out-of-the-box approach.
I just discovered OpenShift and i love it! And i would like to try it with a tomcat app that communicates with mysql.I was able to install tomcat through this tutorial
and my tomcat server is up and running !I also installed mysql and phpmyadmin,but now i have to deploy my servlet in the tomcat server .My servlet communicates with mysql but i cant find where to insert the variables that Openshift give me !Does anyone have any idea?
Thnx in advandce Andi :)
OPENSHIFT VARIABLES ARE:
Root User :andi
RootPassword: andi
Connection URL: mysql://$OPENSHIFT_MYSQL_DB_HOST:$OPENSHIFT_MYSQL_DB_PORT/
MY SERVLET:
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;
#WebServlet("/HelloWorldServlet")
public class HelloWorldServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public HelloWorldServlet() {
super();
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String titulli = request.getParameter("titulli");
String ingredientet = request.getParameter("ingredientet");
String receta = request.getParameter("receta");
final String url = "jdbc:mysql://localhost/andi";
final String user = "andi";
final String password = "andi";
try {
// jdbc try
Class.forName("com.mysql.jdbc.Driver");
Connection con = (Connection) DriverManager.getConnection(url, user,
password);
// insert values into the first table
PreparedStatement s = (PreparedStatement) con
.prepareStatement("INSERT INTO recetat(titulli,ingredientet,receta) VALUES (?,?,?)");
s.setString(1, titulli);
s.setString(2, ingredientet);
s.setString(3, receta);
s.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
PrintWriter out = response.getWriter();
out.println("Receta u ruajt me sukses ne server !");
System.out.println(titulli+ingredientet+receta);
}
}
like you can see i dont know where to insert the
Connection URL: mysql://$OPENSHIFT_MYSQL_DB_HOST:$OPENSHIFT_MYSQL_DB_PORT/
variable...
OpenShift puts the MySQL host and port as environment variables on exactly that name. In Java terms, they are available by
String host = System.getenv("OPENSHIFT_MYSQL_DB_HOST");
String port = System.getenv("OPENSHIFT_MYSQL_DB_PORT");
Then, compose the JDBC URL as follows
String url = String.format("jdbc:mysql://%s:%s/andi", host, port);
The normal approach, however, is to create a connection pooled datasource in context.xml and obtain that by JNDI instead.
Somewhat related - you can now install tomcat directly (without following the DIY steps) but running
rhc app create <name> jbossews-1.0
JBoss EWS is a maintained and supported version of Tomcat from Red Hat - all the same bits. Also, starting next week the rhc client tools will support
rhc app create <name> tomcat6
To make it even simpler.
I am doing a jsp project in which, I have a dbconn.java page in which database connection to MySQL database is created.
I want to call it in an another java page for getting the database connection.
I dont know how to include the page dbconn.java into my page. Please help.
I know its a simple question for you all, but I could not find the answer.
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ActionContext;
import java.util.*;
import java.util.Date;
import java.sql.*;
package com.act;
public class dbconn {
public String execute() throws Exception
{
Connection con=null;
Statement stmt1=null;
Class.forName("com.mysql.jdbc.Driver");
con=DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabasename", "root", "password");
}
}
This is my dbconn.java page. Is this correct?
You need to return the Connection object from this utility class.
I rewrite your class with name ConnectionManager like this :
import java.sql.*;
public class ConnectionManager{
private Connection con = null;
public Connection getCon(){
try{
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabasename","root", "password");
}
catch(Exception e){
e.printStackTrace();
}
return con;
}
}
Now in your other classes, call this class like this whenever you need a db-connection:
Connection con = new ConnectionManager().getCon();
PreparedStatement st = con.prepareStatement("YOUR SQL QUERY");