My question is very related to this one: Multiple dynamic data sources for a servlet context. However I haven’t found a proper solution just yet and would like to ask it again.
I have a little JSF application that talks to a MS SQL Server via JDBC. Tomcat is used as the web container. The application retrieves and stores its data from a single database. A login screen is provided. If the credentials match the ones stored in the database then access is granted and I can play around with the application.
Now I would like to add more databases and provide a login screen which not only requests the username and password but the database name as well. Different databases are used because I would like to have some for testing and development. The backup plans are also not the same for every database.
Currently I use JNDI Resources to look up the databases in my code. However this forces me to edit context.xml and web.xml and to restart tomcat. I don’t want to do that. The restart forces me to run around an tell everyone: “Hey I am rebooting do you mind losing all your connections?”
Is the some more dynamic way to do that?
For your purposes, you should really have three separate application server instances (either on three separate machines, or on the same machine listening to different ports, or different host headers etc). The development server instance should always look up the development database, the staging server looks up the staging database etc, and JNDI should be set up to reflect this. That's what JNDI is for.
That said, if you must set things up with just a single application server, you will probably need to look into writing a custom authentication realm that does this. You could either do the actual work of determining which data source to use yourself, or look into something like Hibernate Shards.
Create an array of datasources and let the user select which index in this array you want to use.
I dont know the answer but if you call OSQL -L from JNI you can get a list of available SQL database instances in the area. Then you can connect and get the list of databases within.
So:
user enters username and password
app runs OSQL -L to get the list of instances and provides a select list
user selects instance, jdbc uses credentials in step 1 to get a list of databases from the instance
jdbc uses selected database to connect.
You could get the databases in SQL server using a select statement and eventually discard some of them which are not relevant to your applications.
ResultSet rs = stmt.executeQuery("show databases");
Related
I have two war files such as war1 and war2
If am login the application, the session will be created in war1 and from that if am navigate to war2, there i need the same session data.
I tried crossContext=true in context.xml of server from that i can access the data by storing it in servletContext.
But the issue is once i logined the screen in chrome the session data will be stored in servletContext and the data will maintain till the application is running.
If am giving the same URL in another browser like IE here also, i can get the servletContext data so instead of navigate to login page the corresponding screen will be opened
Kindly suggest me how can i overcome this issue in java?
Is there any way to findout browser switching or incognito window mode of the browser in java?
Note: am using tomcat server
I have never dealt with your exact configuration problem, but even if you can make this work on a single Tomcat instance, you might have problems should your two web applications ever be distributed across multiple Tomcat instances.
So, I am going to suggest that you actually use a database to store state which needs to be passed between the two applications in a safe and reliable way. Note that the database approach also scales nicely in a distributed environment, so long as you have a single logical database.
While session replication indeed can be done in Tomcat (see here) I really suggest you to avoid this type of issues by eliminating the session altogether.
This session replication is an approach that was somewhat common before ~15-10 years, but nowadays when we have a lot of servers running in parallel to serve user requests and have elastic clusters, this approach is not good enough because basically it doesn't scale well.
There are many ways to achieve what you want, though:
Use a shared database to store the session information. Add some session Id to the response and require the client to pass this id back into all subsequent request along the session. Then execute a query to the Database by this Id and retrieve all the session information.
This solution also doesnt really scale well, but then you can shard the session information if the db permits to do so...
Use Redis/Aerospike to save the session information of the currently connected user. somewhat like DB approach, but since redis run in-memory it will be much faster. In general, this approach can be used in conjunction with 1 where redis is an in-memory cache.
Encrypt the session information or even just sign cryptographically and send back to client. Client will have to supply this information along with the request without knowing which server will actually serve this request.
Without delving into cryptography I'll just state that encryption can be done if you don't want client to see the session information (despite the fact that this is the user whose information is supplied) and signature is used to prevent tempering the data (while sending it back to server).
The data can be supplied to server from client via Header or cookie for instance.
So, I'm in the middle of building an application where I want the user to be able to send a link to another user and work on the same data. There is little need to persist the data for more than 15 minutes and I want the application to not have to rely on a database.
I have a few variables which I am currently storing in a HttpSession.
Ideally I'd like to be able to set a parameter "sid" in the URL, and use that to set the session ID on the second client's browser - the one that's received a link with the SID.
Unfortunately, there seems to be no way to change the SID of a current session once it's been set up.
The only solution I've come up with so far is referring to the doGet() with a HttpPost.setHeader("Cookie", "JSESSIONID="+ getSessionId()) method, and getting the data with a specific session that way, but this seems pretty clunky.
Any suggestions?
EDIT
This has seemingly turned into a discussion about the wisdom of setting two users up to have the same session so session vars may be kept the same. Note that a non-db, ie light weight solution was what I was looking for. PHP allows you to arbitrarily set a session ID to do this, but I'm deploying to Tomcat in this instance. Something which allows lightweight sharing of a few parameters, that's it...
What I've done, then, is to set context vars using context.setAttribute(). Ugly as sin, but all I can come up with, unless anyone has any better ideas.
This approach has some security issues because you are simulating [session hijacking] with it 1:
In computer science, session hijacking, sometimes also known as cookie
hijacking is the exploitation of a valid computer session—sometimes
also called a session key—to gain unauthorized access to information
or services in a computer system. In particular, it is used to refer
to the theft of a magic cookie used to authenticate a user to a remote
server. It has particular relevance to web developers, as the HTTP
cookies used to maintain a session on many web sites can be easily
stolen by an attacker using an intermediary computer or with access to
the saved cookies on the victim's computer (see HTTP cookie theft).
Better approach is to set your data in a way that both users can approach it from their sessions. If you are using single server you can do that with some global data within a server. In clustered or cloud environments you'll need some common storage for that (ie. database, global cache, etc.)
EDIT
You are on a right track to share data among two users with different sessions.
There is one context per "web application" per Java Virtual Machine
where an attribute allows a servlet container to give the servlet
additional information.
Attributes are meant to be used to share data inside container among servlets of the same web application.
For clusters:
In the case of a web application marked "distributed" in its
deployment descriptor, there will be one context instance for each
virtual machine. In this situation, the context cannot be used as a
location to share global information (because the information won't be
truly global). Use an external resource like a database instead.
I'm looking for a way to open a JDBC connection without specifying my database login and password in plain text, as the application will be distributed and any Java decompiler would reveal them, allowing the users to access the database easily.
Is there any way to encrypt them, or store them somewhere else?
Looks like you want to let Android application talk to your database directly? Don't do that. It's a major security flaw. No matter how you encrypt your credential, you have to reveal your plain text somewhere during the execution of the program, and anyone with a debugger can see that. The correct way is to have use an API on your web service and call that API from client. All database transaction should happen in a trusted intranet.
Why would you want to do this? Generally the business side of your application would have this info and connect to MySQL. There, a user does not have access to any code. Then you create an endpoint that actually is accessible to the public. There you can worry about passing username and password stuff to the business logic, which again, actually has direct access to your database.
Basically, do not open a jdbc connection anywhere but your server side. Its a security measure.
First, I will present what it is doing my web-application :
The subject of this web-application is different distributed databases and distributed data sistems with a specific type of information. Until now I programed using PHP, JavaScript and JQuery-ui. For databases I used MySQL and PostgreSQL and I thinking to use and Oracle. On short way on my web application the user firstly have to register. If he is accepted by Admin then he have the possiblities :
Connect to HIS database (MySQL, Oracle, Access, PostgreSQL)
Run queries between two, different or not, databases
To connect to his database the user enter information like : host, user, password and name of database. At next step he can see the tables from database. If he select one line he will be able to Update, Create and Delete the content from the selected table.
On this section the user can look for similarities between the two databases (with key words or structures of tables) : one that belongs to him and another one that belongs to the Admin.
I use WampServer, version 2.1 with Apache/2.2.17 and PHP/5.3.5 and I want to do a bridge who will be responsable with the connection to the databases and in which I will comunicate with different databases. The informations from interface will be sent as MySQL queries and in the bridge I will adapt that queries for each type of database.
Can someone to help me ?
Soon as possible.
Thank you !
Simon
The informations from interface will
be sent as MySQL queries and in the
bridge I will adapt that queries for
each type of database.
This is a very bad idea for two serious reasons:
To implement it, you'd have to write your own SQL parser.
Each major database implements its own dialect of SQL, which means you'll have to know how to translate between their specific syntax and command sets.
I have a plain Java application which is supposed to connect to the database. I don't want to store database connection url and username/password in a properties file or hardcode it in application. What is a common way to solve this problem? How a Java application can connect to database without revealing username/password?
I'm a .NET dev, but I've run into the exact same situation.
Last year I was working at a company that had to be PCI compliant to store credit card data, so security was a big deal. The URL/login data has to exist somewhere. The most common method I've seen for securing it is with encryption. I don't know about Java in particular, but .NET has several encryption namespaces in the core Framework. We used these to encrypt the database logins.
You still have a potential security vulnerability, which are the encryption keys used to encrypt/decrypt the data. We used the PCI "compensating controls" method here. Access to the keys is restricted to "key management" role. We also tracked access of the key itself so that there was a record of all user-initiated and system-initiated access. No one user had access to these logs, so there could be no covering of tracks by a single user. These overlapping security methods essentially create a situation where nothing less than a coordiated conspiracy between multiple administrators is required to put the data in jeopardy.
If you aren't willing to store it, you have to prompt for it. You could encrypt the password, but then you have to have a key to decrypt it and you are stuck in the same problem.
One of the common solutions to this problem for server based applications is to store the username and password in a file that has user permissions set in such a way that only the executing user of the application/service can read its contents.
For example, you run your application as user foo-service and it inherits all of the access privileges of the foo-service user. The file containing the username and password is only readable by that user. You read the value from the file and connect to the database as normal.
Possible problems with this approach:
The superuser of this machine may be able to get the password to the database.
An attacker who has penetrated your application security can get access to the database credentials.
The above problems are normally mitigated by tuning the access privileges for the application to the database and the network. Nearly any other solution you come up will get you into a chicken-and-egg problem because you are basically trying to hide something from itself.
The best way would be to store the information as a configured data source in the JNDI context of your application server. You can then use the facilities of the application server to configure data sources at deployment time. All the application has to do is look up the appropriate JNDI name at runtime and use that. This is a common pattern for Java web applications.
Use web services to separate your application from the server doing the database access. Sign your web application and then only allow a properly signed application to call the web services server.
You can try to load a file using system properties.
-Dapplication.configuration=application.properties.
When the property file is not passed then the you should use default file with default config.
When the file exists you override the defaults with the values provided from configuration.
java -Dlog4j.configuration=file:/log4j.properties -Dapplication.configuration=file:/live-conf.conf -jar app.jar "applicationarg1" "applicationarg1"
More sources to follow:
https://docs.oracle.com/javase/tutorial/essential/environment/properties.html
How to override system properties:
-Dproperty=value
Set a system property value. If value is a string that contains spaces, you must enclose the string in double quotes:
http://docs.oracle.com/javase/6/docs/technotes/tools/windows/java.html