The purpose is to send extra information to triggers like current user id from a web application. Since a connection pool is used, and same user id is used for all connections how do I pass the original web user id to trigger? It is a java based application.
If you can't touch the application code and the application itself does not pass this information to the database already, you're at an impasse. The only way to make that information available to back-end code is for the middle tier to pass it in.
Oracle provides a number of ways for applications to pass information from the middle-tier to the back end but the application has to be built to take advantage of them. The DBMS_APPLICATION_INFO package, for example, has a set_client_info procedure that allows the middle tier to pass in the name of the middle tier user that your back end trigger could query. You can also use Oracle contexts if you want a more general mechanism. Either of these approaches, however, realistically require that the Java application be written to pass this information to the back-end when connections are retrieved from the connection pool.
You can make use of proxy authentication to identify the users even with a ConnectionPool.
An example:
me#XE> #man proxy
[ P R O X Y A U T H E N T I C A T I O N ]
drop user application_user
drop user end_user
-- let's create the application user which all users
-- need to connect through.
-- This user is meant as the middle-tier-user in a
-- multi-tier setup.
create user application_user identified by application_user
-- create an end-user
create user end_user identified by end_user
quota unlimited on users
grant create session, create table to end_user
-- this is the clause to grant access to end_user.
alter user end_user grant connect through application_user
-- now, we can connect WITHOUT PASSWORD!
#connect application_user[end_user]/application_user
-- this should display "END_USER"
select user from dual
-- this should display "APPLICATION_USER"
column proxy_user format a30
select sys_context('userenv', 'proxy_user') proxy_user from dual
http://blogs.oracle.com/jheadstart/entry/using_proxy_authentication
Related
I connect with names in capital letters, but it does not want to connect with small letters in the login.
Here is a small test
String ENCODING = "WIN1251";
String CONNECTION_URL = "jdbc:firebirdsql:localhost:C:/ProgramData/test.FDB";
Properties properties = new Properties();
properties.setProperty("encoding", ENCODING);
properties.setProperty("roleName", "GUEST");
properties.setProperty("user", "smoll2");
properties.setProperty("password", "1234567a");
DriverManager.getConnection(CONNECTION_URL, properties);
java.sql.SQLInvalidAuthorizationSpecException: Your user name and password are not defined. Ask your database administrator to set up a Firebird login. [SQLState:28000, ISC error code:335544472]
at org.firebirdsql.gds.ng.FbExceptionBuilder$Type$4.createSQLException(FbExceptionBuilder.java:572)
at org.firebirdsql.gds.ng.FbExceptionBuilder.toFlatSQLException(FbExceptionBuilder.java:302)
at org.firebirdsql.gds.ng.wire.AbstractWireOperations.readStatusVector(AbstractWireOperations.java:138)
at org.firebirdsql.gds.ng.wire.AbstractWireOperations.processOperation(AbstractWireOperations.java:202)
at org.firebirdsql.gds.ng.wire.AbstractWireOperations.readOperationResponse(AbstractWireOperations.java:161)
at org.firebirdsql.gds.ng.wire.version13.V13WireOperations.authReceiveResponse(V13WireOperations.java:122)
at org.firebirdsql.gds.ng.wire.version10.V10Database.authReceiveResponse(V10Database.java:569)
at org.firebirdsql.gds.ng.wire.WireConnection.identify(WireConnection.java:309)
at org.firebirdsql.gds.ng.wire.FbWireDatabaseFactory.performConnect(FbWireDatabaseFactory.java:51)
at org.firebirdsql.gds.ng.wire.FbWireDatabaseFactory.connect(FbWireDatabaseFactory.java:39)
at org.firebirdsql.gds.ng.wire.FbWireDatabaseFactory.connect(FbWireDatabaseFactory.java:32)
at org.firebirdsql.jca.FBManagedConnection.<init>(FBManagedConnection.java:141)
at org.firebirdsql.jca.FBManagedConnectionFactory.createManagedConnection(FBManagedConnectionFactory.java:550)
at org.firebirdsql.jca.FBStandAloneConnectionManager.allocateConnection(FBStandAloneConnectionManager.java:65)
at org.firebirdsql.jdbc.FBDataSource.getConnection(FBDataSource.java:124)
at org.firebirdsql.jdbc.FBDriver.connect(FBDriver.java:137)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:208)
There are basically four situations where this authentication error will happen:
The user does not exist or has the wrong password
You created the user with a case-sensitive username, e.g. using CREATE USER "smoll2" ....
You created the user with the Legacy_UserManager, and are using Jaybird 4, which by default no longer authenticates with Legacy_Auth
The user is marked inactive
I assume case 1 doesn't apply here, but otherwise you need to create the user or change its password.
For case 2, it is important to realise that - since Firebird 3.0 - usernames are identifiers, and follow the same rules as identifiers. Which means unquoted names are stored in uppercase, and match case-insensitively (by means of uppercasing), while quoted names are stored exactly and are compared as is. If you created the user case-sensitively (CREATE USER "smoll2" ...), then you need to authenticate with a quoted user name:
properties.setProperty("user", "\"smoll2\"");
If you don't do this, you are actually authenticating against the user SMOLL2 (which doesn't exist).
For case 3, since Firebird 3.0, Firebird provides multiple authentication plugins with accompanying user managers. Users exist per user manager. Since Jaybird 4, Jaybird by default only authenticates with plugins Srp256 and Srp (which share the Srp user manager). If you created your user with the Legacy_UserManager (either because it is the first configured in UserManager in firebird.conf, or because you used the using plugin Legacy_UserManager clause when creating the user), you cannot authenticate with the default settings of Jaybird, because it doesn't try the Legacy_Auth user plugin.
There are two solutions for this case:
Drop the user with the Legacy_UserManager and create it with the Srp user manager
Configure Jaybird to also try Legacy_Auth:
properties.setProperty("authPlugins", "Srp256,Srp,Legacy_Auth");
If you only want to try Legacy_Auth, you can remove Srp256 and Srp from the list.
As a variation of case 3, this can also occur if you have a custom user manager and authentication plugin which is not supported by Jaybird.
Finally case 4, a user can be inactive (either because it was created with the INACTIVE clause, or altered to inactive). An inactive user is not allowed to authenticate. The inactive state is ignored for Legacy_UserManager/Legacy_Auth. If a user is inactive, you can activate it again with:
alter user smoll2 set active
Be aware that it could also be a combination of 2 and 3 (using a case-sensitive username and Legacy_UserManager). You can verify which user you have, if it is active, and for which user manager, by executing the following query as SYSDBA or a user with RDB$ADMIN role in the current database and the security database:
select sec$user_name, sec$active, sec$plugin from sec$users;
For Legacy_UserManager, the SEC$ACTIVE column is NULL, as it doesn't support the active/inactive state.
I am trying to troubleshoot an issue that presents as different database errors such as, ORA-01000: maximum open cursors exceeded or Unable to create DB Connection. I have reviewed the PLSQL to determine if cursors were left open and all are closed even if there is an error.
The java application and background are as follows:
The original application was a 3-tiered system:
GUI app. -> server app -> 11g Oracle database
The enhancement was to add an API service in a Pivotal Cloud Foundry (PCF) environment.
So this architecture was like this:
Close Function: GUI app -> Server App -> API service -> Database.
All other Functions: GUI app -> Server App -> Database.
This was put into production and run for a week without any database issues described above.
Then another enhancement was added in which the API Service communicates with several other services all in PCF in which 2 communicate with the same oracle database. Now during heavy volume we are getting these database errors.
It seems to me that the Oracle database cannot keep up with the requests from these additional services. But how can I demonstrate that. We have AppD configured for the servers but not the database. Are there queries that I can run in the prod env. that shows that these PCF applications are causing the issue? Or should I look in another area?
Thanks,
UPDATE
I looked at the legacy application and the result sets are closed. The other 3 PCF applications use Spring Boot to connect to the database. From my understanding, closing connections and result sets do not have to be explicitly closed. JDBCTemplate closes these connections/result sets. The PLSQL added has an additional cursor which is closed on success and exception.
UPDATE
I created a query that shows the total open cursor by sessionID
This is the query:
select b.sid, b.username, b.osuser, sum(a.value) total_opened_current_cursors
from sys.v_$statname c,
sys.v_$sesstat a,
sys.v_$session b
where a.statistic#=c.statistic# and
b.sid=a.sid and
c.name in ('opened cursors current') and
(b.username is not null or b.username <> '' )
group by b.sid, b.username, b.osuser
order by total_opened_current_cursors desc
Now, I need to link the sessionID with the application that has this session.
The osuser for the top ones is NULL.
Also, most of the sessions' status are INACTIVE
How to identify the application to the session?
Secondly, is the session is inactive, which I thought meant that no query is happening so why are there open cursors?
**UPDATE**
So, I wrote a query that returns the top 10 sessions with the highest open cursors
select *
FROM
(
select b.sid, b.username, b.osuser, b.status, sum(a.value) total_opened_current_cursors
from sys.v_$statname c,
sys.v_$sesstat a,
sys.v_$session b
where a.statistic#=c.statistic# and
b.sid=a.sid and
c.name in ('opened cursors current') and
(b.username is not null or b.username <> '' )
group by b.sid, b.username, b.osuser, b.status
order by total_opened_current_cursors desc
)
WHERE ROWNUM <= 10;
I found the SQL_TEXT that accounts for most of the open cursors...by far! (87%)
So, how do I find the query that calls this SQL?
There are at least 5 services that hit the database. Some of the services call PLSQL stored procedures some call raw SQL text. The query that accounts for the open cursors is listed as a SELECT statement. Does that mean it is NOT a stored procedure? Or can this SELECT be called within the stored procedures.
How do I find the connection that uses this session?
I am working on a java application which will be deployed in the field and needs to connect to an sql database on my company's server.
What is the best practice for users logging in? I have salted and hashed my passwords, and from what I have read I should save the username/salt/hashed password in an sql database. This sounds fine and dandy, but the question becomes how do I get into the database to get the salt without the salt? The obvious answer is to create one account which logs in and only has access to the table of usernames and salts. This account then "authenticates" the user from that table or kicks them off the server.
Unfortunately, at least in my mind, this introduces a slew of additional security risks. The 'password' for the blanket use account would be available in the source of my java project, as well as any sql script to set up the server. To change that password would also mean a full update to anyone using the project. So, the question I am asking is this:
How can I prevent someone from logging into my sql server from outside of my java application with the credentials I have supplied to that application, or should I not be worried about it?
Here is what I am doing with the server setup file.
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='ANSI';
CREATE DATABASE PM;
USE PM ;
DROP PROCEDURE IF EXISTS PM.drop_user_if_exists ;
DELIMITER $$
CREATE PROCEDURE PM.drop_user_if_exists()
BEGIN
DECLARE foo BIGINT DEFAULT 0 ;
SELECT COUNT(*)
INTO foo
FROM mysql.user
WHERE User = 'Admin' and Host = '%';
IF foo <= 0 THEN
SET #query1 = CONCAT('CREATE USER "Admin"#"localhost" IDENTIFIED BY "',#PASS,'" ');
PREPARE stmt FROM #query1; EXECUTE stmt; DEALLOCATE PREPARE stmt;
CREATE USER 'ParkingManager'#'%' IDENTIFIED BY 'testpass';
GRANT CREATE ON PM.* TO 'Admin'#'%';
GRANT DROP ON PM.* TO 'Admin'#'%';
GRANT LOCK TABLE ON PM.* TO 'Admin'#'%';
GRANT ALTER ON PM.* TO 'Admin'#'%';
GRANT SELECT ON PM.* TO 'Admin'#'%';
GRANT UPDATE ON PM.* TO 'Admin'#'%';
GRANT SELECT ON PM.* TO 'ParkingManager'#'%';
GRANT UPDATE ON PM.* TO 'ParkingManager'#'%';
CREATE DATABASE PMUsers;
END IF;
END ;$$
DELIMITER ;
CALL PM.drop_user_if_exists() ;
DROP PROCEDURE IF EXISTS databaseName.drop_user_if_exists ;
SET SQL_MODE=#OLD_SQL_MODE ;
Thanks!
Edit: The company does not want a VPN. They say that it shouldn't be necessary because the server has SSL.
During the Application startup , using the login Id of the User , i am making a Database call and loading all of his accounts and setting them in the session as shown
session.setAttribute("userinfo",userinfo);
and i am using this accounts information in the service layer to do a check before making a call to the Database
Now the problem is that if a User (who is having multiple accounts ) logs simulatunosly into a same browser , its creating same sessionid , as a result the session is having only the information of the last logged in user .
is there anyway i can solve this , may be the way i am storing data
please help
May not be the best solution but this will help to solve the problem.
What you could do would be to associate the userid with the sessionid and on every pageload / clicks, you will check if the sessionid matches the login user's userid. If it matches, disregard and run the page as usual else you can fetch the user info from the database and reassign the variables again.
You can use URL rewrite instead of cookies. The downside is that the session ID is exposed in the URL.
i have one java web application in jsp and servlet and db as oracle 10g EE. In login if one user has been logged in then how can i prevent same user from logging again unless sign out?
Note: I am not telling that if a logged in user will click on login page then immediately he would be forwarded to his home page.
I am asking is how can i prevent that logged in user to login again if he is already logged in. Suppose user A is already logged in into the db(sign out not done), then user B tries to login in to db with the user id and password of user A, then simply user B will be prevented from login. How do i implement that?
You need to manage a map of logged in users, Map<String, String> userToSessionIdMap when user logs in you check if there is any session exist for this user name if yes deny else allow login,
Now on logout you need to remove the entry from map, also you need to implement HttpSessionBindingListener so when session expires it removes the entry again
Also See
prevent multiple login using the same user name and password
Preventing multiple login
Let the database do it's own job!
(This solution assumes that you can get help from DBAs; or you have SYSDBA access to the database.)
First create a profile that allows only 1 session per user:
CREATE PROFILE single_session_profile
LIMIT SESSIONS_PER_USER 1;
Then create the user with the right profile or alter an existing user to use the profile:
CREATE USER user_a
IDENTIFIED BY user_id
DEFAULT TABLESPACE users
TEMPORARY TABLESPACE temp
QUOTA UNLIMITED ON users
PROFILE single_session_profile;
or
ALTER USER user_a
PROFILE single_session_profile;
Finally, the database needs to be observe these limits:
ALTER SYSTEM SET RESOURCE_LIMIT = TRUE SCOPE = MEMORY;
(SCOPE = MEMORY enables limit enforcement for the currently running database instance; if you want to make it persistent, i.e. enabled after a database restart, you need to use SCOPE = BOTH where BOTH means both MEMORY and SPFILE, i.e. DB initialization file. If the database does not use the new SPFILE format, but the old PFILE (init.ora), then you need to add the RESOURCE_LIMIT setting to the init.ora and restart the database.)
That's it. If a user_a tries to log in twice, it will get:
ORA-02391: exceeded simultaneous SESSIONS_PER_USER limit