The standard question asked by a Java/Oracle developer.
Should I Encrypt OR Hash the passwords ? What is the difference ?
The BIG difference between Encryption and Hashing is that, the data that is encrypted, should be able to be decrypted. Whereas, the data that is hashed, CANNOT be reversed.
Let's take an example.
Usually we authenticate users to log on to our systems or web sites. So, following are the steps :
1. User logs onto a web site and provides user name/password.
2. We need to authenticate the user and if the credentials are valid, log him in or deny access.
So, in step 2, we just need to make sure that he entered a correct password. For that, we DON'T need to store the user's password either in text form or in an encrypted form.
In either of these cases, I mean either you store the password in text form or in encrypted form, there is a possibility that the password can be stolen and reversed.
If we store the password in the HASH form, since it cannot be reversed, we are SAFE.
Unix/Oracle ...etc., follow the same methodology for authentication.
So, how do we apply hashing on plain text passwords.
Let us suppose that the password is : password123
Then the query would look like :
select dbms_crypto.hash(utl_raw.cast_to_raw('password123'),dbms_crypto.HASH_MD5) hashed_password from dual;
If you notice, the hash() takes a second parameter where you can specify, which hashing algorithm you would like to use.
-- Hash Functions
HASH_MD4 CONSTANT PLS_INTEGER := 1;
HASH_MD5 CONSTANT PLS_INTEGER := 2;
HASH_SH1 CONSTANT PLS_INTEGER := 3;
If you are using Oracle 10g, then you can use dbms_crypto.hash().
Otherwise, if you are using Oracle 8i/9i, you have to use - DBMS_OBFUSCATION_TOOLKIT.MD5.
Take a stab at the Oracle Guru's web site : http://asktom.oracle.com/tkyte/Misc/Passwords.html
Long Live "Tom Kyte".
Good Luck !!
r-a-v-i
Wednesday, March 5, 2008
Tuesday, March 4, 2008
Oracle 10g : PL/SQL : Conditional Compilation
If you are a pl/sql developer and if you looking for best practices on unit testing, this is for you.
Usually we run into situations where we need to debug some code, but we don't want to be running the debug code in production. Do we ???
Oracle 10g provides a beautiful feature - conditional compilation. (Like #ifdef in C).
Let's see an example.
Create a test procedure ...
create or replace procedure test_proc
as
begin
dbms_output.put_line( 'Debug 1' );
dbms_output.put_line( 'Debug 2' );
$IF $$debug_code $THEN
dbms_output.put_line( 'Debug 3' );
dbms_output.put_line( 'Debug 4' );
$END
dbms_output.put_line( 'Debug 5' );
end;
set echo on;
set serveroutput on;
Let us suppose that we are running this procedure on our dev/qa environment.
Then, you have to run the following command :
------------------------------------------------------------------------------------
SQL> alter procedure test_proc compile plsql_ccflags = 'debug_code:true' reuse settings;
Procedure altered
SQL>
------------------------------------------------------------------------------------
Now let's run the procedure and see what the output is ....
------------------------------------------------------------------------------------
SQL> exec test_proc;
Debug 1
Debug 2
Debug 3
Debug 4
Debug 5
PL/SQL procedure successfully completed
SQL>
------------------------------------------------------------------------------------
Let's suppose that we are all set to go to production and we need to deploy this procedure on production and we don't want all the debugging.
Then, execute the command :
------------------------------------------------------------------------------------
SQL> alter procedure test_proc compile plsql_ccflags = 'debug_code:false' reuse settings;
Procedure altered
SQL>
------------------------------------------------------------------------------------
That's it. Let's see the output of the procedure, if we run it on production.
------------------------------------------------------------------------------------
SQL> exec test_proc;
Debug 1
Debug 2
Debug 5
PL/SQL procedure successfully completed
SQL>
------------------------------------------------------------------------------------
So, on production when the debug is disabled, you might have noticed that the statements "Debug 3" and "Debug 4" did not print.
Plan B : If you don't want to pollute your code, you can you Log4PLSQL.
Long Live "Tom Kyte".
Good Luck !!
r-a-v-i
Usually we run into situations where we need to debug some code, but we don't want to be running the debug code in production. Do we ???
Oracle 10g provides a beautiful feature - conditional compilation. (Like #ifdef in C).
Let's see an example.
Create a test procedure ...
create or replace procedure test_proc
as
begin
dbms_output.put_line( 'Debug 1' );
dbms_output.put_line( 'Debug 2' );
$IF $$debug_code $THEN
dbms_output.put_line( 'Debug 3' );
dbms_output.put_line( 'Debug 4' );
$END
dbms_output.put_line( 'Debug 5' );
end;
set echo on;
set serveroutput on;
Let us suppose that we are running this procedure on our dev/qa environment.
Then, you have to run the following command :
------------------------------------------------------------------------------------
SQL> alter procedure test_proc compile plsql_ccflags = 'debug_code:true' reuse settings;
Procedure altered
SQL>
------------------------------------------------------------------------------------
Now let's run the procedure and see what the output is ....
------------------------------------------------------------------------------------
SQL> exec test_proc;
Debug 1
Debug 2
Debug 3
Debug 4
Debug 5
PL/SQL procedure successfully completed
SQL>
------------------------------------------------------------------------------------
Let's suppose that we are all set to go to production and we need to deploy this procedure on production and we don't want all the debugging.
Then, execute the command :
------------------------------------------------------------------------------------
SQL> alter procedure test_proc compile plsql_ccflags = 'debug_code:false' reuse settings;
Procedure altered
SQL>
------------------------------------------------------------------------------------
That's it. Let's see the output of the procedure, if we run it on production.
------------------------------------------------------------------------------------
SQL> exec test_proc;
Debug 1
Debug 2
Debug 5
PL/SQL procedure successfully completed
SQL>
------------------------------------------------------------------------------------
So, on production when the debug is disabled, you might have noticed that the statements "Debug 3" and "Debug 4" did not print.
Plan B : If you don't want to pollute your code, you can you Log4PLSQL.
Long Live "Tom Kyte".
Good Luck !!
r-a-v-i
Oracle 10g : Case-Insensitive Searching
Say in the famous Scott's "emp" table, I have data like : "Ravi", "rAvi", "RAvi" ...etc.,. So, if I need to fire a query for "ravi", the standard practice is to create a Upper(emp_name) index and fire the following query :
select * from emp where upper(emp_name) like upper('%raVI%');
Prior to Oracle 10g, you had to adopt one of the following strategies:
* Use a function-based index on UPPER (column_name) and modify the queries to use WHERE UPPER (column_name) = value.
* Use a trigger to roll the column value to upper- or lowercase upon modification.
* Use Oracle Text to create a TEXT index on the column; text indexes (which would then mandate the use of the CONTAINS operator in the predicate) can be case-sensitive or -insensitive.
In each of these cases, one of your conditions would have been violated. You would have needed to use triggers, or UPPER() or CONTAINS in the WHERE clause.
In Oracle 10g, you can do this transparently, without effecting your query. Which means that, you don't have to use UPPER() or CONTAINS in your where clause.
Wait ...wait ...I know ... you will believe only if I show you an example. right ?
Here you go ...
drop table cit;
create table cit ( data varchar2(20) );
insert into cit values ( 'Ravi' );
insert into cit values ( 'rAVi' );
insert into cit values ( 'rAvI' );
commit;
/*Create a function-based index on the DATA column and use the binary case insensitive sort*/
create index cit_idx on cit( nlssort( data, 'NLS_SORT=BINARY_CI' ) );
select * from cit where data = 'ravi';
--You will get zero records.
alter session set nls_comp=ansi;
alter session set nls_sort=binary_ci;
select * from cit where data = 'ravi';
--You will get 3 records.
--Now, let's take a look at the explain plan. CBO is using FTS.
--Let's fake CBO that there are 10000000 in the table.
exec dbms_stats.set_table_stats (ownname=>user,tabname=>'CIT',numrows=> 10000000);
--Now run the select again and take a look at the explain plan.
select * from cit where data = 'ravi';
Execution Plan
------------------------------
SELECT STATEMENT (Cost=2)
TABLE ACCESS (BY INDEX ROWID)
INDEX (RANGE SCAN) OF 'CIT_IDX'
Isn't it just awsome !!
Long live "Tom Kyte".
Source : http://www.oracle.com/technology/oramag/oracle/04-jul/o44asktom.html
Good Luck !!
r-a-v-i
select * from emp where upper(emp_name) like upper('%raVI%');
Prior to Oracle 10g, you had to adopt one of the following strategies:
* Use a function-based index on UPPER (column_name) and modify the queries to use WHERE UPPER (column_name) = value.
* Use a trigger to roll the column value to upper- or lowercase upon modification.
* Use Oracle Text to create a TEXT index on the column; text indexes (which would then mandate the use of the CONTAINS operator in the predicate) can be case-sensitive or -insensitive.
In each of these cases, one of your conditions would have been violated. You would have needed to use triggers, or UPPER() or CONTAINS in the WHERE clause.
In Oracle 10g, you can do this transparently, without effecting your query. Which means that, you don't have to use UPPER() or CONTAINS in your where clause.
Wait ...wait ...I know ... you will believe only if I show you an example. right ?
Here you go ...
drop table cit;
create table cit ( data varchar2(20) );
insert into cit values ( 'Ravi' );
insert into cit values ( 'rAVi' );
insert into cit values ( 'rAvI' );
commit;
/*Create a function-based index on the DATA column and use the binary case insensitive sort*/
create index cit_idx on cit( nlssort( data, 'NLS_SORT=BINARY_CI' ) );
select * from cit where data = 'ravi';
--You will get zero records.
alter session set nls_comp=ansi;
alter session set nls_sort=binary_ci;
select * from cit where data = 'ravi';
--You will get 3 records.
--Now, let's take a look at the explain plan. CBO is using FTS.
--Let's fake CBO that there are 10000000 in the table.
exec dbms_stats.set_table_stats (ownname=>user,tabname=>'CIT',numrows=> 10000000);
--Now run the select again and take a look at the explain plan.
select * from cit where data = 'ravi';
Execution Plan
------------------------------
SELECT STATEMENT (Cost=2)
TABLE ACCESS (BY INDEX ROWID)
INDEX (RANGE SCAN) OF 'CIT_IDX'
Isn't it just awsome !!
Long live "Tom Kyte".
Source : http://www.oracle.com/technology/oramag/oracle/04-jul/o44asktom.html
Good Luck !!
r-a-v-i
Oracle 10g : How to pass ARRAYS of records from Java/Tomcat to Oracle
Environment : JDK 1.5, Tomcat 5.5, Oracle 10gR2.
Let's suppose that you have a web app where you get some records from the user interface and from your DAO, you are trying to pass the records as Oracle ARRAYS to database. Here is a step by step example.
Yes, it's a nightmare as you have to take care of some steps. But, once you understand what to do and what are the issues, it's pretty easy.
Use Case : Let us suppose that we have a java bean Employee and we are trying to send an array of employee records at a time to database.
/*Step 1 : Create a object type in the database*/
/*
CREATE OR REPLACE TYPE "EMP_TYPE" is object(
emp_id Varchar2(500),
emp_name varchar2(500));
*/
/*
Step 2 : Create a type EMP_TYPE_TABLE
CREATE OR REPLACE TYPE "EMP_TYPE_TAB";
*/
/*Step 3 : Create a Java bean which maps the attributes of the above object type in Step 2.*/
import java.io.Serializable;
import java.sql.SQLData;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;
public class Employee implements SQLData, Serializable{
static final long serialVersionUID = 4070409649129120458L;
public Employee(){}
// constructor that takes parameters
// getters and setters for emp_id, emp_name
// You have to implement readSQL() and writeSQL() methods, as shown below.
// This is where you are mapping the Employee table's columns to the Employee
//java bean.
public void readSQL(SQLInput stream, String typeName) throws SQLException {
this.emp_id = stream.readString();
this.emp_name = stream.readString();
}
public void writeSQL(SQLOutput stream) throws SQLException {
stream.writeString(emp_id);
stream.writeString(emp_name);
}
}
//EmpDAO class gets a connection to the database and passes the data.
public class EmpDAO{
java.sql.Connection conn;
java.sql.Connection dconn;
/*
Step 1 : Get database connection
This is a very important step. To pass your records of data as Arrays, you need to get a oracle.jdbc.driver.T4CConnection and then use ArrayDescriptor's. So, how do you get a T4CConnection ?
To get T4CConnection from java.sql.Connection, you need to cast like this :
t4cConn = ((DelegatingConnection)conn).getInnermostDelegate();
If you are working on tomcat, you have two options to get a DataSource in your context.xml.
a) By using apache commons-dbcp
OR
b) by directly using javax.sql.DataSource.
Let's see how to get the T4CConnection in both these cases.
*/
public void sendRecordsToDB(){
//Use Case (a) : if you configured apache commons-dbcp
BasicDataSource ds = (BasicDataSource)ctx.lookup(jndiName);
ds.setAccessToUnderlyingConnectionAllowed(true);
conn = ds.getConnection();
dconn = ((DelegatingConnection)conn).getInnermostDelegate();
//Use Case (b) : if you are directly using javax.sql.DataSource
BasicDataSource bds = new BasicDataSource();
bds.setDriverClassName("");
bds.setUsername("");
bds.setPassword("");
bds.setUrl("jdbc:oracle:thin:@");
bds.setAccessToUnderlyingConnectionAllowed(true);
conn = bds.getConnection();
dconn = ((DelegatingConnection)conn).getInnermostDelegate();
/*So, using either of the above approaches we got dconn, which is an instance of T4CConnection.*/
/* Now let's build an array list of employees.
*/
final List
Let's suppose that you have a web app where you get some records from the user interface and from your DAO, you are trying to pass the records as Oracle ARRAYS to database. Here is a step by step example.
Yes, it's a nightmare as you have to take care of some steps. But, once you understand what to do and what are the issues, it's pretty easy.
Use Case : Let us suppose that we have a java bean Employee and we are trying to send an array of employee records at a time to database.
/*Step 1 : Create a object type in the database*/
/*
CREATE OR REPLACE TYPE "EMP_TYPE" is object(
emp_id Varchar2(500),
emp_name varchar2(500));
*/
/*
Step 2 : Create a type EMP_TYPE_TABLE
CREATE OR REPLACE TYPE "EMP_TYPE_TAB";
*/
/*Step 3 : Create a Java bean which maps the attributes of the above object type in Step 2.*/
import java.io.Serializable;
import java.sql.SQLData;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;
public class Employee implements SQLData, Serializable{
static final long serialVersionUID = 4070409649129120458L;
public Employee(){}
// constructor that takes parameters
// getters and setters for emp_id, emp_name
// You have to implement readSQL() and writeSQL() methods, as shown below.
// This is where you are mapping the Employee table's columns to the Employee
//java bean.
public void readSQL(SQLInput stream, String typeName) throws SQLException {
this.emp_id = stream.readString();
this.emp_name = stream.readString();
}
public void writeSQL(SQLOutput stream) throws SQLException {
stream.writeString(emp_id);
stream.writeString(emp_name);
}
}
//EmpDAO class gets a connection to the database and passes the data.
public class EmpDAO{
java.sql.Connection conn;
java.sql.Connection dconn;
/*
Step 1 : Get database connection
This is a very important step. To pass your records of data as Arrays, you need to get a oracle.jdbc.driver.T4CConnection and then use ArrayDescriptor's. So, how do you get a T4CConnection ?
To get T4CConnection from java.sql.Connection, you need to cast like this :
t4cConn = ((DelegatingConnection)conn).getInnermostDelegate();
If you are working on tomcat, you have two options to get a DataSource in your context.xml.
a) By using apache commons-dbcp
OR
b) by directly using javax.sql.DataSource.
Let's see how to get the T4CConnection in both these cases.
*/
public void sendRecordsToDB(){
//Use Case (a) : if you configured apache commons-dbcp
BasicDataSource ds = (BasicDataSource)ctx.lookup(jndiName);
ds.setAccessToUnderlyingConnectionAllowed(true);
conn = ds.getConnection();
dconn = ((DelegatingConnection)conn).getInnermostDelegate();
//Use Case (b) : if you are directly using javax.sql.DataSource
BasicDataSource bds = new BasicDataSource();
bds.setDriverClassName("
bds.setUsername("
bds.setPassword("
bds.setUrl("jdbc:oracle:thin:@
bds.setAccessToUnderlyingConnectionAllowed(true);
conn = bds.getConnection();
dconn = ((DelegatingConnection)conn).getInnermostDelegate();
/*So, using either of the above approaches we got dconn, which is an instance of T4CConnection.*/
/* Now let's build an array list of employees.
*/
final List