Oracle Proxy Users by example

The following example illustrates the use of Oracle proxy users. If you wonder what proxy users are, have a look at my previous posting: Oracle Proxy Users.

First we’ll create two database users. One normal application user, pu_user_1, and a Big Application User, pu_pool_user. The big application user will be used by a web application to connect to the database. Usually the application user, in this case pu_user_1, will be authenticated by the web application.

create user pu_pool_user identified by pu_pool_user;
grant create session to pu_pool_user;

create user pu_user_1 identified by pu_user_1;
alter user pu_user_1 grant connect through pu_pool_user;
grant create session to pu_user_1;

By granting pu_user_1 the connect through privilege, you allow pu_pool_user to proxy for pu_user_1, i.e., pu_pool_user connects to the database, but it will be as if pu_user_1 is connected.

First a normal connection. The following example connects to oracle using the user pu_pool_user:

    private void normalConnection() throws Exception {
        Properties properties = new Properties();
        Connection conn = DriverManager.getConnection(
                "jdbc:oracle:thin:pu_pool_user/pu_pool_user@localhost:1521:ora1012",
                properties);
        printUserInfo(conn);
        conn.close();
    }

If you ask oracle who is connected, oracle will identify the connected user as pu_pool_user. This is displayed using the following code:

    private void printUserInfo(Connection conn) throws Exception {
        System.out.println(
            "Is proxy session: " + ((OracleConnection) conn).isProxySession());

        PreparedStatement stmt = conn.prepareStatement(
                " select user, username "
                 +", sys_context('USERENV','PROXY_USER') "
                 +", sys_context('USERENV','CURRENT_USER') "
                 +", sys_context('USERENV','SESSION_USER') "
                 +" from sys.v_$session"
                );
        ResultSet rset = stmt.executeQuery();

        if (rset.next()) {
            System.out.println("user                  : " + rset.getString(1));
            System.out.println("username              : " + rset.getString(2));
            System.out.println("userenv proxy_user    : " + rset.getString(3));
            System.out.println("userenv current_user  : " + rset.getString(4));
            System.out.println("userenv session_user  : " + rset.getString(5));
        }

        stmt.close();
    }

This method prints the following info for the normal connection:

Is proxy session: false
user                  : PU_POOL_USER
username              : null
userenv proxy_user    : null
userenv current_user  : PU_POOL_USER
userenv session_user  : PU_POOL_USER

The following code connects to the database as pu_pool_user, but then we tell the connection that we’re actually proxying for pu_user_1.

    private void proxyConnection() throws Exception {
        Properties properties = new Properties();
        properties.put("PROXY_USER_NAME", "pu_user_1");

        OracleConnection conn = (OracleConnection) DriverManager.getConnection(
                "jdbc:oracle:thin:pu_pool_user/pu_pool_user@localhost:1521:ora1012",
                properties);
        conn.openProxySession(OracleConnection.PROXYTYPE_USER_NAME, properties);

        printUserInfo(conn);
        conn.close();
    }

The result of calling printUserInfo:

Is proxy session: true
user                  : PU_USER_1
username              : PU_USER_1
userenv proxy_user    : PU_POOL_USER
userenv current_user  : PU_USER_1
userenv session_user  : PU_USER_1

As you can see, USER now returns PU_USER_1, eventhough we connected to the database as pu_pool_user.

This is very convenient, you do not have to rewrite your security code and your auditing code.

blog comments powered by Disqus