Our company has an audit requirement to track individual user interaction with the application by user id. We use Tomcat 7 with the Tomcat connection pool and an Oracle 11.2 database (soon to be 12c). We connect using a Type 4 datasource managed by JNDI on the server which uses a system user id. Users log on using SSO to the web application. We want to make sure that whenever a user modifies a database record, their SSO signon id instead of the system id is used in an audit column to identify who made the modification.
My research shows that using getClientInfo and setClientInfo may be the way to go and I want to be clear on how I would implement this. Would I use the setClientInfo on the pooled datasource Connection to set the client user id, or run the Oracle stored procedure DBMS_APPLICATION_INFO.SET_CLIENT_INFO to pass the client user id? I know that in the Oracle virtual table v$session there is a column for OSUSER that holds this information. How do I get it there? Could I make a direct update to that column?
Since this is a multi-threaded application server, I don't want to end up with a concurrancy issue.
Related
I am porting a legacy application to hibernate 5 and I'm having trouble with the login phase. Here's how it works (I can't change that):
user initially connects to oracle DB with a generic login/password (same for all users)
then user runs a "login" stored procedure and enters a unique password as parameter
the procedure returns a specific Oracle DB username/password to the user
user disconnects from DB and reconnects using the credentials given by the stored procedure
I currently create one instance of sessionFactory per connected user, but I'm worried that this will impact performance. Is there a better way to do this?
Thanks
Hibernate Multitenancy with "Separate database" strategy would work even if you are actually connecting to the same database but different credentials.
MultiTenantConnectionProvider must be specified to return connection with right username and password.
I have an application in MVC with Hnibernate deployed on a server. Currently only one client is using this application. Now there are many clients and all will use this app with different database but the schema will same for all.
For this implementation I am thinking an approach-
I have made a new database in which table hold the information regarding the individual Client database connection strings.
When the application run, Nhiberate makes multiple session factories for all database which includes all client databases and the main database.
For example- there are two clients 'A' and 'B' with their database name 'A_db' and 'B_db'. And the other main database which hold connection strings as 'All_db'. Then in this case nhibernate make 3 session factories for all three db.
So when user enter their login credential, i'll check the related connection string for that client from the main database. and then destroy all session factories which are not related to that client database connection string. So by doing this there will be only one session factory remain that belong to his database.
Is this my approach is correct??
And i am going in right direction then provide some code for this approach as making multiple session factories and after then removing all session factories except the related one?
You can supply a connectionstring to the GetSession method. Check out this link for more intel.
I have a web service which processes inserts/updated data to DB. When client calls this webservice, UserId(currently logged in user to portal) will be sent in Request. I need to pass this userId to Db connection or set it in sys context for Audit purpose. we have existing audit tables and triggers to inserts/updates to Audit table after insert/update on actual table. So to track these changes I need to pass this UserId somehow to connection so that it can be retrieved from DB from Sys Context or $session and inserts in Audit table. I am currently using Spring and Hibernate transactions to process data with DB.
I tried to Set client info on Connection but it's not working. I tried below:
Session session=sessionFactory.getCurrentSession();
SessionImpl sImpl=(SessionImpl) session;
Connection connection=sImpl.connection();
connection.setClientInfo("ClientUser", "ABC");
And also I am trying to set client info by calling Stored procedure DBMS_APPLICATION_INFO.SET_CLIENT_INFO before performing operation on DB every time from application code.but I am not sue if it's a correct way to handle it.
I am trying it with both OCI and thin JDBC drivers but not able find a way to set this user id.
Can someone let me know if there is any efficient way to pass user id on sys context or with Connection. I am currently using hibernate4, Spring, Websphere Server, Oracle DB.
I am using Spring #Transactional to handle hibernate Connections and transactions to perform operation on DB.Connections are from Connection pool and I am using org.springframework.jndi.JndiObjectFactoryBean for dataSource.
is there any way to have interceptor or wrapper around connection to set it when we get the connection from connection pool.
Has anyone done this before?
This is described in spring data JDBC Extensions for the Oracle Database
Chapter
8.2 Configuration of a Custom DataSource Connection Preparer
...but you could implement a ConnectionPreparer that would use the current users login id. That way you can capture user login information even if your data source is configured with a shared user name.
This is a solution for oracle, which I think you are using. It should be also possible to adapt that to another database.
I wanted to form oracle database URL for my JDBC conection and few websites say SID should be part of URL and few say schema name.
Please compare schema, service name and SID in ORACLE? And how they are related?
is it like SID:schema is 1:n as in one SID can point to n schemas?
Please explain with the relation between them.
A SID is the unique identifier for a database, or if it's a RAC system for an instance of a database.
A Service is an identifier for a service offered by the database, and the database should be configured for services such as "BILLING_APP" or "CUST_WEBSITE". http://docs.oracle.com/cd/B28359_01/server.111/b28320/initparams217.htm
Don't confuse a database and an instance, by the way. A database is the set of data and control (etc) files, the instance is the memory areas and processes that access it. RAC has multiple instances per database, each of which can register with the listener to offer all or a subset of the total services offered by the database.
A schema is effectively the username that owns the objects, and there can be multiple schemas in the database.
So an application should be referencing a SERVICE to connect to, through a listener on a certain host and port. The listener resolves this to a database (possibly one of many that register to offer that service). The connection is made to the database as a user who might or might not be the owner of the schema. Typically the connection is not made as the schema owner for security reasons -- in fact the best level of security is to connect as User_A, calling code in User_B's schema, whicxh references tables in other users' schemas.
A SID is a Service ID and refers to a single Oracle database instance
A service name is very like a SID but multiple SIDs can be referenced by one Service Name
E.g. in a Dataguard scenario, the primary instance might be SID_01 and ORA_SRV. SID_02 and SID_03 are running somewhere on the network and receiving and applying the log files. SID_01 fails and SID_02 is brought up (Mounted and Opened) and now exposes itself ont he network as ORA_SRV.
Similarly with RAC multiple SIDs make up a single Service.
A schema is in effect a user.
A JDBC connection will be in some form of "HOST:PORT:(SID or Service name)". You will have to connect to the DB and will do so with a username and password. The username will (almost always) connect you to a schema of that name. You can can reference objects in another schema with dotted notation in your sql, e.g. SCHEMA.OBJECT_NAME
In my project, I am using Oracle Database and SubSonic for DAL. I have a problem with SubSonic and Oracle Schema, that is:
When developing, I used a schema DEV in Oracle Database and generate DAL using SubSonic.
After that when release to customer, he used a new schema TEST in Oracle Database and changed the connection string in app.config to connect to Oracle. The error will appear, that is “Table or View does not exist”. I found this error and see that the schema of tables is still DEV.
I do not want re-generate DAL after change schema and when released to the customer. Please help me.
Firstly, your schema should not be DEV. DEV is a user or role.
Your schema name should be related to the data content (eg ACCOUNTS or SALES)
Secondly, consider whether you or the customer is going to decide the schema name. Say you have a product called FLINTSTONE. You may decide that the schema name should be FLINTSTONE. However your customer may want to run two instances of your product (eg one for local sales, the other for international) and use the same database. So they want FS_LOCAL and FS_INTER as the schema names. Is that option a feature of your product ?
Next, decide if your application should connect as the schema owner. There are good security reasons for NOT doing that. For example, the schema owner has privileges to drop tables, which is generally something the application doesn't do and thus, on the principle of least privilege, is something your application shouldn't have privileges to do.
Generally I would recommend some config parameter for the application for the schema name, and after connecting to the database, the app should do an "ALTER SESSION SET CURRENT_SCHEMA = 'whatever was it the config file'". The application database user would need the appropriate insert/update/delete/select/execute privileges on the objects in the application schema. If the application can't do that, you can have a LOGON trigger in the database.
Gary is correct in not using DEV as a schema on your own machine. In using Oracle we typically set up the schema as what the client is going to name their schema. This however does not fix your issue. What you need to do is create a global alias in Oracle that maps say DEV to CLIENTSCHEMA. You should still rename the schema on your machine but this will allow your schema to differ from your clients.