1) Using SmartClient Version: v9.1p_2014-07-31/PowerEdition Deployment (built 2014-07-31)
2) IE 11
Background:
We have several tables in our Database (Oracle) that have auditing performed by Triggers when changes are made to data in these table. These triggers use session/connection information in order to determine who is making the change. Since we are using shared connections, the UserId on the DB Connection is not the actual user of the GUI, so we need to tell Oracle the remote UserId. This is being done through a call to DBMS_APPLICATION_INFO.set_client_info('<UserId>').
The way our authentication works is that we get the UserId of the authenticated user from the HTTPServletRequest Header.
Current Approach:
1) Create a StoredProcedure DataSource to hold the various Stored Procedure Calls as OperationBindings
2) Extend SQLDataSource to execute the stored procedure that sets the Client Info before executing the actual SQL (making sure to clear it after).
Questions:
1) Is this the recommended method of doing this or is there an easier way?
2) Is it safe in terms of not allowing multiple users to show the same Remote User Id given that the connection is shared?
3) Any suggestions on improvement?
Thanks!
2) IE 11
Background:
We have several tables in our Database (Oracle) that have auditing performed by Triggers when changes are made to data in these table. These triggers use session/connection information in order to determine who is making the change. Since we are using shared connections, the UserId on the DB Connection is not the actual user of the GUI, so we need to tell Oracle the remote UserId. This is being done through a call to DBMS_APPLICATION_INFO.set_client_info('<UserId>').
The way our authentication works is that we get the UserId of the authenticated user from the HTTPServletRequest Header.
Current Approach:
1) Create a StoredProcedure DataSource to hold the various Stored Procedure Calls as OperationBindings
Code:
<DataSource ID="StoredProcedures" serverType="sql" dbName="Oracle"> <operationBindings> <operationBinding operationType ="update" operationId="spSetClientInfo" > <customSQL>call DBMS_APPLICATION_INFO.set_client_info($userId)</customSQL> </operationBinding> <operationBinding operationType ="update" operationId="spClearClientInfo" > <customSQL>call DBMS_APPLICATION_INFO.set_client_info('')</customSQL> </operationBinding> </operationBindings> </DataSource>
Code:
import javax.servlet.http.HttpServletRequest; import com.isomorphic.datasource.DSRequest; import com.isomorphic.datasource.DSResponse; import com.isomorphic.sql.SQLDataSource; public class CUIDSQLDataSource extends SQLDataSource { private static final long serialVersionUID = 1L; @Override public DSResponse execute(DSRequest req) throws java.lang.Exception{ //If only a fetch, then no need to set Remote USER ID if(req.getOperationType().equalsIgnoreCase("fetch")){ return super.execute(req); }else{ //Get the User Id from the Header, if not found set it to Empty String HttpServletRequest servletReq = req.getHttpServletRequest(); if(servletReq!=null){ String userId=servletReq.getHeader("remote-user"); if(userId==null ) { userId = ""; } //Set the UserId on the RPCManager so the Stored Procedure DS //has access to it via the $userId velocity variable req.getRPCManager().setUserId(userId); //Call Stored Procedure to set Remote User Id DSRequest spReq = new DSRequest("StoredProcedures","update"); spReq.setOperationId("spSetClientInfo"); //Make it part of the same Transaction by using the same RPCManager spReq.setRPCManager(req.getRPCManager()); DSResponse spResp = spReq.execute(); if(spResp.getStatus()==DSResponse.STATUS_SUCCESS){ //Setting of Client User ID succeeded so execute original request DSResponse superResp = super.execute(req); //Call the Stores Procedure to clear the User Id DSRequest spClearReq = new DSRequest("StoredProcedures","update"); spClearReq.setOperationId("spClearClientInfo"); spClearReq.setRPCManager(req.getRPCManager()); DSResponse spClearResp = spClearReq.execute(); //return the response from the original request return superResp; }else{ return new DSResponse(){{setFailure("Unable to set Client Info in the Database.");}}; } } return new DSResponse(){{setFailure("Unable to get Client Info.");}}; } } }
1) Is this the recommended method of doing this or is there an easier way?
2) Is it safe in terms of not allowing multiple users to show the same Remote User Id given that the connection is shared?
3) Any suggestions on improvement?
Thanks!
Comment