encrypt database username and password in java? - java

Actually by type 4 db connection from java i am connecting to oracle database like this:
In dbconnection.java i have written below:
Class.forName("oracle.jdbc.driver.OracleDriver");
con=DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:database host name","database user name", "database user password");
return con;
Is there any method how can i write these 3 fields(database host, database username, database user password) in encrypted form in java class dbconnection.java like below:
Class.forName("oracle.jdbc.driver.OracleDriver");
con=DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:wrtwtr#$%$_rfwrw","regfwerfgwf", "%%5frfr^&%$%4");
return con;
and during database connection, these encrypted fields will be decrypted and will be connected to oracle database in actual names
Then in servlet i am calling like:
dbconnection db= new dbconnection();
Any help please

I'm not aware of any way to do that.
But I also don't see what doing this would achieve. Sure, the username and password are not shown in clear, but a bad guy who had access to those encrypted strings would be able to use them the same way as your program does.

Rather than trying to hide your connection details, you should provide a secure way to allow externally controlled applications (or instances of applications) to access your database.
An API is basically a middle layer between your database and an application you do not have control over. For example, facebook, rather than allowing direct access to their database, allows developers to access their data through an API. This means that applications can be authenticated (thus meaning they can be held responsible), and you can control explicitly what applications can and cannot see and edit.
Basically, through an API, you can protect your database while simultaneously keeping track of who is doing what (though the protection aspect is usually the main draw).
I must say though that sometimes, if you trust the people using the application, it's just easier to not worry about it. For example, if you work at a small company of competent, well meaning people, then it would likely be safe to allow the application to connect directly to the database.
If you are distributing your program to the general public though, or a large set of people whom you do not completely and totally trust, then you should not allow direct access, no matter what kind of precautions are taken.
Assume that you do figure out how to encrypt your credentials. At some point, you must still make the connection. What happens now if a user grabs the decryption/connection code, has the connection made, then inserts his own code after it? Suddenly he has access to your database. With an API, worst case, he could steal the API key and have limited, traceable, easily revokable access.
And besides, if you're allowing access to an API, you only allow users to do what you want them to do. So worst case, if he does figure out how to use the API directly, all he can do is what the program allows him to do anyway.

Passing encrypted data to the DriverManager is not an option.
You should pass the decrypted string into DriverManager. So somewhere you would have the user name and password encrypted and then decrypt them before passing them to the DriverManager
Then you would have other issues e.g. where to store private key etc, but as a first defence it would be better than using plaintext since my understanding is that you have some security requirement.
You did not mention what OS you are using. If you are using Windows I would suggest to use Windows based authentication (the connection to the database is authenticated against the current windows user).So no need to provide user name and password in the connection string. Check if Oracle supports this (have tried only with MS-SQL server.Hopefully the link I provided is useful).
This is IMHO the best option. For Linux there must be something equivalent.

Related

Best way to remove tokens from database

I'm developing a token based api gateway. Its basically provide a token for authentic clients. So I'm not sure how to remove expired tokens. For every request I checked whether the token is valid or not.
Option 1 is
Mark status of token as expired in database table row.
and create a scheduler to run in midnight to delete expired tokens.
Option 2 is
Delete the token from the row when its expired.
In here No need to run a scheduler.
Normally this API Gateway will handle around 1000 requests per second and and this will increase day by day.
So I'm not sure which option I should use.
The technology I have used is.
Spring mvc,Spring data jpa and Postgre DB. Will deploy on tomcat server.
Neither of the two options is particularly good as both will modify a table row and therefore generate I/O. At 1,000 q/s you need a better solution. On 2ndQuadrant is a blog post on authenticating users through connection pooling in the context of row-level security. The blog post has some issues IMHO and non-relevant material as well so I'll try to redo it here in the right way (or read my comment on the blog post over there).
In Java - as in most other programming languages and/or frameworks - connection pooling is the preferred way to connect to a database server for performance reasons. There is an implicit contract that the application requests a Connection instance from the pool, uses it and then returns the instance to the pool for some other thread. Holding on to a Connection is not an option as it breaks the pooling logic. So proceed as follows:
Connection pool object
Create a connection pool object with database cluster credentials. That role should be GRANTed all necessary privileges on tables and other objects.
Authentication
In the application a user authenticates doing myapp_login(username, password) or something similar using a Connection from the pool. In the database the credentials are checked against a table users or whatever it is called in your setup. If a match is found then create a random token and insert that in a table:
CREATE UNLOGGED TABLE sessions (
token text DEFAULT uuid_generate_v4()::text,
login_time timestamp DEFAULT CURRENT_TIME,
user_name integer,
...
);
Add as many fields as you want. I use a uuid here (cast to text, read on) but you could also md5() some data or use some pg_crypto routine.
This table has to be fast so it is UNLOGGED. That means it is not crash-safe and will be truncated after some server error but that is not a problem: all database sessions will have been invalidated anyway. Also, do not put any constraints like NOT NULL on the table because the only access to this table is through the functions that you as a developer design, no ordinary user ever touches this table, and every constraint involves more CPU cycles.
The myapp_login() function looks somewhat like this:
CREATE FUNCTION myapp_login(uname text, password text) RETURNS text AS $$
DECLARE
t text;
BEGIN
PERFORM * FROM app_users WHERE username = uname AND pwd = password;
IF FOUND THEN
INSERT INTO sessions(user_name) VALUES (uname) RETURNING token INTO t;
EXECUTE format('SET SESSION "my_app.session_user" TO %s', t);
RETURN t;
END IF;
SET SESSION "my_app.session_user" = '';
RETURN NULL;
END;
$$ LANGUAGE plpgsql STRICT SECURITY DEFINER;
REVOKE EXECUTE ON FUNCTION myapp_login(text, text) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION myapp_login(text, text) TO myapp_role;
As you can see, the token is also set in an environment variable with SET SESSION (which needs a literal text value, hence the uuid::text cast and the EXECUTE command) and then returned to the caller. That session token should be stored somewhere in your application code on the Java side.
The function does a lookup on the app_users table and an INSERT on the sessions table. The first is cheap, the second is expensive.
Resume the same session for further queries
If your app user needs further database access after the first queries, then get a Connection instance from the connection pool again, but don't call myapp_ login() but myapp_resume(token) instead. This latter function looks up the token in the sessions table (cheap) and, if found, sets the session variable to this new token. You can also check that the login_time value is recent or set it with the CURRENT_TIME to keep the session "alive" (expensive) or do any other necessary business.
The trick is to keep resuming the session as lean as possible because this is likely to be happening multiple time during a session (from the application perspective).
Close the session
When your app user is done, do myapp_logout(token) which deletes the row from the sessions table that corresponds to the token.
Sessions that are not properly closed are not deleted from the sessions table, but I would not worry too much about that.You could schedule a job that runs once a week to delete all rows that are older than 6 hours or so. That would also allow you to figure out where the error comes from, for instance.
A final word on the token. A uuid is just a random number, but you could also make a hash of the application user name with some random data and use that, for instance, in RLS or some other row-based access mechanism; the blog post I link to above has good info on that. In an application I have developed myself I link the row from the users table to what the user is allowed to see. In either case you should really weigh the pro's and con's: a hash that can be used in RLS sounds nice, but it requires the hash to be re-calculated (which tends to be expensive) and compared to the session hash on every query, a repeated lookup against a users table is also an overhead. Setting another session variable that can be checked at query time with current_setting() might be a good alternative.
I think the easiest way would be like this. When you generate token in your database, you can store time of generation. So that when client sends a request to your database, you can check if it's expired and delete it in request time.

Is it a bad practice to expose DB internal IDs in URLs?

Is it a bad practice to expose DB internal IDs in URLs?
For example, suppose I have a users table with some IDs (primary key) for each row. Would exposing the URL myapp.com/accountInfo.html?userId=5, where 5 is an actual primary key, be considered a "bad thing" and why?
Also assume that we properly defend against SQL injections.
I am mostly interested in answers related to the Java web technology stack (hence the java tag), but general answers will also be very helpful.
Thanks.
That bases on the way you parse the URL. If you allow blind SQL injections that is bad. You have to only to validate the id from the user input.
Stackexchange also puts the id of the row into the URL as you can see in your address bar. The trick is to parse the part and get did of all possible SQL. The simples way is to check that the id is a number.
It isn't a bad thing to pass through in the URL, as it doesn't mean much to the end user - its only bad if you rely on that value in the running of your application. For example, you don't want the user to notice that userId=5 and change it to userID=10 to display the account of another person.
It would be much safer to store this information in a session on the server. For example, when the user logs in, their userID value is stored in the session on the server, and you use this value whenever you query the database. If you do it this way, there usually wouldn't be any need to pass through the userID in the URL, however it wouldn't hurt because it isn't used by your DB-querying code.
To use the database ID in URLs is good, because this ID should never change in an objects (db rows) life. Thus the URL is durable - the most important aspect of an URL. See also Cool URIs don't change.
Yes it is a bad thing. You are exposing implementation detail. How bad? That depends. It forces you to do unneeded checks of the user input. If other applications start depending on it, you are no longer free to change the database scheme.
PKs are meant for the system.
To the user, it may represent a different meaning:
For e.g.
Let's consider following links. Using primary-key,it displays an item under products productA, productB,productC;
(A)http://blahblahsite.com/browse/productA/111 (pkey)
(B)http://blahblahsite.com/browse/productB/112 (pkey)
(C)http://blahblahsite.com/browse/productC/113 (pkey)
User on link B may feel there are 112 items under ProductB, which is misleading.
Also it will cause problem while merging tables since PK will be auto-incremented.

How to get a unique username

I'm looking to use Google's App Engine (Java) to provide the backend to an Android messaging app I'm currently writing, I'm just starting out with GAP but have a little experience with Java (through Android).
The first time someone uses the app it will send some sign-up data to the server, this will stored in the GAE datastore, and a unique id returned to the phone (or an error message if something broken).
As I can't see something that looks like key = datastore.giveMeAUniqueKey or datastore.hasThisBeenUsedBefore(key) I guess I'm going to have to generate a random key and see if it's been taken (I'm not that sure how to do that to be honest).
Any ideas (either answers to the specific question, or pointer to useful "getting started" resources)?
Thanks.
If this value is not security sensitive (ie, it's just a user ID and you have some other method to authenticate the phone), just do an insert and take the key of the newly inserted entity. The datastore will assign a guarenteed-unique key automatically if you insert a new entity without providing one. Alternately, you can explicitly request an ID with the allocate_ids call.
If the value is security sensitive (it's a session nonce or something used for authentication), use the SecureRandom class to generate a sequence of random bytes. Do not use this as a key for an entity such as a user object; this would preclude changing the session ID if the user's session is compromised. Have a separate user ID used for that purpose, and use this secure nonce only for the authentication step.
Note that simply looping creating IDs, testing for conflicts, and inserting is not safe without using a transaction; it's easier (and faster, and cheaper...) just to use app engine's built in ID assignment system.

Set Oracle NLS_LANGUAGE from java in a webapp

My understanding of JDBC is that it automatically sets the Oracle NLS_LANGUAGE/NLS_TERRITORY session parameters based on the default Locale of the JVM. This is handy for a stand-alone swing app, but seems useless for a java webapp. The only solution I can come up with is to specifically set the session parameters right before actually doing a database query, something similar to:
Connection c = // However you get it.
Statement s = c.createStatement();
s.execute("alter session set NLS_LANGUAGE = 'SPANISH'");
// Do actual query here
My questions:
Is this the best way to set the Oracle language/country parameters from a webapp?
Since the Oracle parameters take language names rather than codes, is there a mapping from java/ISO language codes to Oracle language names? For example, can I use Locale.getDisplayLanguage() and be safe?
Can depend on your architecture.
Some places opt to have multiple geographically local web-apps against a single database (ie one in the France, one in the UK, one in Spain).
Or you pull data (eg dates, numbers) in 'computer' format from the database and have the web-app convert it to the end-user's preferences (or possibly based on browser information if you don't have user logins).
Or you have separate connection pools for different 'territories'.
Bear in mind that queries changing territories can affect index usage and sorting.
If you're using connection pooling, it's the best way to make sure that Johnny's results are in American and Johann's results are in German.
You could store the user's preferred NLS value for LANGUAGE, TERRITORY, CHARACTERSET, and SORT, using V$NLS_VALID_VALUES as a data source, assuming you store login/user information.

Java: Query Active Directory information with minimal user information

So, here's the situation. We'd like to be able to query active directory for a user's roles/group memberships, etc. Now, I can already do that using standard Java API (javax.naming), but I need a username, domain server name/address, and a password to do it. Users also have limited rights, so I can't use any external calls to fancy administrative tools.
In Java, is there a way that I can get that information with just the username and domain server name/address? I'm also open to 3rd party packages to do this. Alternatively, you could provide me with (or point me to) information on what to configure in AD to allow this.
Hopefully that makes sense. I'm not an AD guru, so the more info the better.
Your problem of needing to login first is because AD does not allow anonymous querying. Before you can query the database you must login ("bind" in LDAP terms) as a valid user with sufficient rights to issue the query.
If your AD admin is willing, you could have them create a special user (we call ours "ldapquery") that is permitted to bind and query the database. The userid and password for that user would become configuration values in your code.
Okay, so expounding on what others have told me and the vast research I had to do with the clues given here, it appears that I'd just use my "special user" as the login info in my code, transparent to the user, and then perform the query using their credentials. So: in the code, bind using the "special user", then perform the query with the current user as a query parameter (sAMAccountName=username).
Thanks all, for your input.

Categories

Resources