Thứ Ba, 8 tháng 9, 2020

Thứ Tư, 26 tháng 8, 2020

Xây dựng api tìm kiếm khuôn mặt trong database sử dụng cube trong postgresql

 Bước 1: Install postgresql từ Dockerfile

FROM postgres:10.6
MAINTAINER nikhil baby <nikhil_baby@hotmail.com>

RUN apt-get update && apt-get install -y build-essential curl postgresql-server-dev-10
RUN curl https://ftp.postgresql.org/pub/source/v10.6/postgresql-10.6.tar.bz2 -o /postgresql-10.6.tar.bz2
RUN cd / && tar xvf postgresql-10.6.tar.bz2
RUN cd /postgresql-10.6/contrib/cube && sed -i 's/#define CUBE_MAX_DIM (100)/#define CUBE_MAX_DIM (128)/' cubedata.h && \
    USE_PGXS=true make && USE_PGXS=true make install

Bước 2: Tạo extension cube và tạo bảng

CREATE EXTENSION CUBE

CREATE TABLE images (name text, vector cube);

 Bước 3: Chuyển khuôn mặt thành định dạng vector 128d sử dụng face_recognition và lưu vào db

image = face_recognition.load_image_file(pathImg)

conn = psycopg2.connect(host="localhost",database="postgres", user="postgres", password="mysecretpassword")

face_encoding = face_recognition.face_encodings(image)[0]        

face_encoding_string = ""

name='abc'    

for distance in face_encoding:
    face_encoding_string+=str(distance)
    face_encoding_string+=str(",")
        

face_encoding_string = face_encoding_string[:-1]

print(face_encoding_string)
        

cur = conn.cursor()

cur.execute("INSERT INTO images (name, vector) VALUES (name, '"+face_encoding_string+"')");

 

 Bước 4: Tìm kiếm ảnh trong db

conn = psycopg2.connect(host="localhost",database="postgres", user="postgres", password="mysecretpassword")

image = face_recognition.load_image_file(pathFileSearch)
face_encoding = face_recognition.face_encodings(image)[0]

 

face_encoding_string = ""

for distance in face_encoding:
        face_encoding_string+=str(distance)
        face_encoding_string+=str(",")

face_encoding_string = face_encoding_string[:-1]      
tempstring = "SELECT name FROM images ORDER BY vector<-> cube(array["+face_encoding_string+"]) LIMIT 1"

cur = conn.cursor()
cur.execute(tempstring)
print(cur.fetchall())
conn.commit()
conn.close()

 

Chủ Nhật, 11 tháng 8, 2019

Export file exel với pl/sql

Ở bài này mình sẽ hướng dẫn các bạn 1 cách hết sức đơn giản để export file exel trong pl/sql bằng cách sử dụng package as_xlsx. Các bạn có thể download package tại đây.

Khởi tạo đường dẫn tới thư mục chứa file export

create directory MY_DIR as '/home/oracle/exp';

Okie bây giờ bạn chỉ cần gọi package và sử dụng, có thể tham khảo cách sử dụng từ các ví dụ bên dưới

/* Example
begin
  as_xlsx.clear_workbook;
  as_xlsx.new_sheet;
  as_xlsx.cell( 5, 1, 5 );
  as_xlsx.cell( 3, 1, 3 );
  as_xlsx.cell( 2, 2, 45 );
  as_xlsx.cell( 3, 2, 'Anton Scheffer', p_alignment => as_xlsx.get_alignment( p_wraptext => true ) );
  as_xlsx.cell( 1, 4, sysdate, p_fontId => as_xlsx.get_font( 'Calibri', p_rgb => 'FFFF0000' ) );
  as_xlsx.cell( 2, 4, sysdate, p_numFmtId => as_xlsx.get_numFmt( 'dd/mm/yyyy h:mm' ) );
  as_xlsx.cell( 3, 4, sysdate, p_numFmtId => as_xlsx.get_numFmt( as_xlsx.orafmt2excel( 'dd/mon/yyyy' ) ) );
  as_xlsx.cell( 5, 5, 75, p_borderId => as_xlsx.get_border( 'double', 'double', 'double', 'double' ) );
  as_xlsx.cell( 2, 3, 33 );
  as_xlsx.hyperlink( 1, 6, 'http://www.amis.nl', 'Amis site' );
  as_xlsx.cell( 1, 7, 'Some merged cells', p_alignment => as_xlsx.get_alignment( p_horizontal => 'center' ) );
  as_xlsx.mergecells( 1, 7, 3, 7 );
  for i in 1 .. 5
  loop
    as_xlsx.comment( 3, i + 3, 'Row ' || (i+3), 'Anton' );
  end loop;
  as_xlsx.new_sheet;
  as_xlsx.set_row( 1, p_fillId => as_xlsx.get_fill( 'solid', 'FFFF0000' ) ) ;
  for i in 1 .. 5
  loop
    as_xlsx.cell( 1, i, i );
    as_xlsx.cell( 2, i, i * 3 );
    as_xlsx.cell( 3, i, 'x ' || i * 3 );
  end loop;
  as_xlsx.query2sheet( 'select rownum, x.*
, case when mod( rownum, 2 ) = 0 then rownum * 3 end demo
, case when mod( rownum, 2 ) = 1 then ''demo '' || rownum end demo2 from dual x connect by rownum <= 5' );
  as_xlsx.save( 'MY_DIR', 'my.xlsx' );
end;
--
begin
  as_xlsx.clear_workbook;
  as_xlsx.new_sheet;
  as_xlsx.cell( 1, 6, 5 );
  as_xlsx.cell( 1, 7, 3 );
  as_xlsx.cell( 1, 8, 7 );
  as_xlsx.new_sheet;
  as_xlsx.cell( 2, 6, 15, p_sheet => 2 );
  as_xlsx.cell( 2, 7, 13, p_sheet => 2 );
  as_xlsx.cell( 2, 8, 17, p_sheet => 2 );
  as_xlsx.list_validation( 6, 3, 1, 6, 1, 8, p_show_error => true, p_sheet => 1 );
  as_xlsx.defined_name( 2, 6, 2, 8, 'Anton', 2 );
  as_xlsx.list_validation
    ( 6, 1, 'Anton'
    , p_style => 'information'
    , p_title => 'valid values are'
    , p_prompt => '13, 15 and 17'
    , p_show_error => true
    , p_error_title => 'Are you sure?'
    , p_error_txt => 'Valid values are: 13, 15 and 17'
    , p_sheet => 1 );
  as_xlsx.save( 'MY_DIR', 'my.xlsx' );
end;
--
begin
  as_xlsx.clear_workbook;
  as_xlsx.new_sheet;
  as_xlsx.cell( 1, 6, 5 );
  as_xlsx.cell( 1, 7, 3 );
  as_xlsx.cell( 1, 8, 7 );
  as_xlsx.set_autofilter( 1,1, p_row_start => 5, p_row_end => 8 );
  as_xlsx.new_sheet;
  as_xlsx.cell( 2, 6, 5 );
  as_xlsx.cell( 2, 7, 3 );
  as_xlsx.cell( 2, 8, 7 );
  as_xlsx.set_autofilter( 2,2, p_row_start => 5, p_row_end => 8 );
  as_xlsx.save( 'MY_DIR', 'my.xlsx' );
end;
--
begin
  as_xlsx.clear_workbook;
  as_xlsx.new_sheet;
  as_xlsx.setUseXf( false );
  for c in 1 .. 10
  loop
    as_xlsx.cell( c, 1, 'COL' || c );
    as_xlsx.cell( c, 2, 'val' || c );
    as_xlsx.cell( c, 3, c );
  end loop;
  as_xlsx.freeze_rows( 1 );
  as_xlsx.new_sheet;
  for r in 1 .. 10
  loop
    as_xlsx.cell( 1, r, 'ROW' || r );
    as_xlsx.cell( 2, r, 'val' || r );
    as_xlsx.cell( 3, r, r );
  end loop;
  as_xlsx.freeze_cols( 3 );
  as_xlsx.new_sheet;
  as_xlsx.cell( 3, 3, 'Start freeze' );
  as_xlsx.freeze_pane( 3,3 );
  as_xlsx.save( 'MY_DIR', 'my.xlsx' );
end;
*/

Done!

Thứ Bảy, 10 tháng 8, 2019

Đọc json trong pl/sql oracle

Ở đây tôi sẽ hướng dẫn các bạn đọc chuỗi Json từ pl/sql

Bước 1: Download package tại đây
Bước 2: Giải nén và chạy file install.sql tại nơi có thể chạy câu sql như oracle sql developer chẳng hạn. Chạy xong trong package của bạn sẽ có các package sau.



Okie, nhiệm vụ bây giờ hết sức đơn giản chỉ là khai báo và sử dụng. Các bạn có thể xem qua ví dụ dưới đây.


declare
  obj pljson;
  list pljson_list;
begin

  obj := pljson('
    {
      "a": null,
      "b": 12.243,
      "c": 2e-3,
      "d": [true, false, "abdc", [1,2,3]],
      "e": [3, {"e2":3}],
      "f": {
        "f2":true
      }
    }');
  obj.print;
  -- equivalent to print
  dbms_output.put_line(obj.to_char);

  -- print compact way
  obj.print(false);
  -- equivalent to print compact way
  dbms_output.put_line(obj.to_char(false));

  -- add to json object
  obj.put('g', 'a little string');
  -- remove from json object
  obj.remove('g');

  -- count of direct members in json object
  dbms_output.put_line(obj.count);

  -- test if an element exists
  if not obj.exist('json is good') then
    obj.put('json is good', 'Yes!');
    if obj.exist('json is good') then
      obj.print;
      dbms_output.put_line(':-)');
    end if;
  end if;

  -- you can build lists (arrays) too
  -- however notice that we have to use the 'to_json_value' function on json objects
  list := pljson_list(); --fresh list;
  list.append(pljson('{"lazy construction": true}').to_json_value);
  list.append(pljson_list('[1,2,3,4,5]'));
  list.print;
    -- empty list and nested lists are supported
  list := pljson_list('[1,2,3,[3, []]]');
  list.print;
  -- count of direct members in json list
  dbms_output.put_line(list.count);

  -- you can also put json object or json lists as values
  obj.put('nested json', pljson('{"lazy construction": true}'));
  obj.put('an array', pljson_list('[1,2,3,4,5]'));
  obj.print;

  -- support for dates
  obj.put('a date', pljson_ext.to_json_value(to_date('2017-10-21', 'YYYY-MM-DD')));
  -- and convert it back
  dbms_output.put_line(pljson_ext.to_date(obj.get('a date')));

  obj := pljson(
    '{
      "a" : true,
      "b" : [1,2,"3"],
      "c" : {
        "d" : [["array of array"], null, { "e": 7913 }]
      }
    }');

  -- get elements using a json path expression
  -- pljson supports a simple dot path expression and '[n]' for arrays
  -- it never raises an exception (null is returned instead)
  -- arrays are 1-indexed
  -- the empty string as path returns the entire json object
  -- can 'get_string', 'get_number', etc.
  dbms_output.put_line(pljson_ext.get_number(obj, 'c.d[3].e'));

  -- all pljson_... objects are copies
  -- so modification in place is difficult
  -- but put with path can do it
  pljson_ext.put(obj, 'c.d[3].e', 123);
  obj.print;

  -- if you provide an invalid path then an error is raised
  -- you can, however, specify a path that doesn't exists but should be created
  -- arrays are 1-indexed.
  -- gaps will be filled with json null(s)
  obj := pljson();
  pljson_ext.put(obj, 'a[2].data.value[1][2].myarray', pljson_list('[1,2,3]'));
  obj.print;
  -- fill the holes
  pljson_ext.put(obj, 'a[1]', 'filler1');
  pljson_ext.put(obj, 'a[2].data.value[1][1]', 'filler2');
  obj.print;
  -- replace larger structures:
  pljson_ext.put(obj, 'a[2].data', 7913);
  obj.print;

  obj := pljson(
    '{
      "a" : true,
      "b" : [1,2,"3"],
      "c" : {
        "d" : [["array of array"], null, { "e": 7913 }]
      }
    }');
  obj.print;

  -- remove element
  pljson_ext.remove(obj, 'c.d[3].e');
  obj.print;
  -- remove array of array
  pljson_ext.remove(obj, 'c.d[1]');
  obj.print;
  -- remove null element
  pljson_ext.remove(obj, 'c.d[1]');
  obj.print;

  -- you can ignore check for duplicate keys
  obj := pljson();
  -- enables fast construction without checks for duplicate keys
  obj.check_duplicate(false);
  for i in 1 .. 10 loop
    obj.put('a'||i, i);
  end loop;
  obj.put('a'||5, 'tada');
  obj.print;
  obj.check_duplicate(true);
  -- fix possible duplicates but does not preserve order
  obj.remove_duplicates();
  obj.print;

  -- create json objects and lists from sql statements
  list := pljson_dyn.executeList('select * from tab');
  list.print;
  obj := pljson_dyn.executeObject('select * from tab');
  obj.print;
end;
/
 
okie done;

Thứ Tư, 31 tháng 7, 2019

Transparent Data Encryption (TDE) oracle

 

Mã hóa dữ liệu không cần sử dụng dòng lệnh code

Đây là cơn ác mộng tồi tệ nhất của các tổ chức: Bị ăn cắp dữ liệu lưu trữ của cơ sở dữ liệu. Chắc chắn rằng bạn đã xây dựng 1 hệ thống an ninh, mã hóa hầu hết dữ liệu, và xây dựng 1 tường lửa xung quanh cơ sở dữ liệu trong máy chủ. Nhưng những tên trộm vẫn dễ dàng tiếp cận: chúng lấy dữ liệu lưu trữ, phát sinh dữ liệu của bạn trên 1 máy chủ khác, khởi động dữ liệu và chuyển dữ liệu thành của chính chúng. Bảo vệ cơ sở dữ liệu khỏi những tên trộm không chỉ là 1 bài tập, nó là 1 yêu cầu cấp thiết với hầu hết luật lệ, quy định và hướng dẫn. Làm cách nào để bảo vệ dữ liệu khỏi mối nguy hại này ?
Một giải pháp là mã hóa ẩn dữ liệu và lưu trữ khóa giải mã trong 1 khu vực khác. Nếu không có mã khóa, không thể ăn cắp dữ liệu. Tuy nhiên, bạn phải phối hợp 2 điều kiện trái ngược: ứng dụng có thể truy xuất khóa mã hóa 1 cách tiện lợi, và yêu cầu bảo mật ngăn cấm những tên trộm khóa. Và theo chỉ thị của công ty, bạn cần 1 giải pháp ngay lập tức, mà không cần bất cứ 1 bước code nào.
Một chức năng mới trong Oracle Database 10g Release 2 có thể giúp bạn làm điều đó: bạn có thể khai báo 1 cột được mã hóa mà không cần viết 1 dòng code nào. Khi người dùng thêm dữ liệu, cơ sở dữ liệu mã hóa ẩn nó đi và lưu trữ nó vào trong cột này. Tương tự, khi người dùng lấy dữ liệu của 1 cột, cơ sở dữ liệu tự động giải mã nó. Tất cả những điều đó được làm mà không hề thay đổi code của ứng dụng, chức năng này mang tên: Mã hóa dữ liệu – Tranparent Database Encryption (TDE)

Cách thức hoạt động
Tất cả những gì bạn phải làm là xác định 1 cột thuộc tính cần được mã hóa, và Oracle Database 10g tạo ra một khóa mật mã cho bảng chứa đựng thuộc tính và mã hóa toàn bộ dữ liệu trong thuộc tính đó,  bằng cách sử dụng thuật toán mã hóa mà bạn đã chỉ định. Việc bảo vệ khóa mật mã của bảng là vô cùng quan trọng, Oracle Database 10g mã hóa nó bằng 1 khóa chủ và khóa này được lưu trữ trong 1 khu vực bảo mật gọi là wallet, có thể là 1 file trong cơ sở dữ liệu của máy chủ. Khóa mật mã của bảng nằm trong từ điển dữ liệu. Khi người dùng nhập dữ liệu vào thuộc tính được mã hóa, Oracle Database 10g sẽ lấy khóa chủ từ wallet, giải mã để lấy khóa mã hóa từ điển dữ liệu, sử dụng khóa mã hóa đó trên dữ liệu đầu vào, và lưu trữ dữ liệu đã được mã hóa trong cơ sở dữ liệu.

TDE sử dụng kiến trúc mã hóa 2 lớp:
  • Table key/Tablespace key: table key dùng để mã hóa column trong table, được lưu trong dictionary. Tablespace key dùng để mã hóa tablespace, được lưu trong datafile header
  • Master encryption key: dùng để mã hóa table key/tablespace key. Master key được lưu bên ngoài db, có thể ở trong Oracle Wallet, hay lưu ở HSM

Cấu hình TDE

Đầu tiên ta cần 1 thư mục để làm wallet. Ta tạo thư mục trên OS và cấu hình thêm nội dung ENCRYPTION_WALLET_LOCATION vào file sqlnet.ora

ENCRYPTION_WALLET_LOCATION =

 (SOURCE=

   (METHOD=file)

     (METHOD_DATA=

       (DIRECTORY=/home/oracle/wallet )))


Tạo wallet với password bảo vệ

sql>alter system set encryption key identified by "walletPassword123456"

Trong thư mục wallet, 1 file ewallet.p12 được tạo ra, lưu giữ master key. Wallet sẽ được open ngay khi tạo xong

Kiểm tra wallet
sql>select * from v$encryption_wallet;

Cấu hình auto login

Nếu không cấu hình auto login, khi shutdown database và start lại, ta phải tự open wallet, nếu không dữ liệu mã hóa sẽ không truy cập được.
sql>alter system set encryption wallet open identified by "walletPassword123456";
Cấu hình auto login giúp wallet luôn được open. Ta sử dụng orapki để cấu hình auto login. 1 file cwallet.sso sẽ được tạo ra trong thư mục
sql>orapki wallet create -wallet /home/oracle/wallet -auto_login

Close wallet

sql>alter system set encryption wallet close identified by "walletPassword123456";


Thuộc tính mã hóa
Để mã hóa thuộc tính sử dụng TDE, tất cả những gì bạn cần làm là thêm vào 1 mệnh đề đơn giản —ENCRYPT— để định nghĩa thuộc tính. Tuy nhiên, trước khi bạn làm điều đó, bạn phải quyết định loại mã hóa và độ dài khóa sử dụng.  


Trên 1 lược đồ, bạn có 1 bảng tài khoản như sau:

ACC_NO      NUMBER

ACC_NAME    VARCHAR2(30)

SSN         VARCHAR2(9)

Thông thường, bảng này có tất cả dữ liệu dạng text. Bạn muốn chuyển đổi thuộc tính SSN (Social Security Number) lưu trữ dạng mã hóa. Bạn có thể đưa lệnh:

sql>alter table accounts modify (ssn encrypt);

Dòng lệnh này làm 2 việc:
  • Tạo một khóa mã hóa cho bảng. Nếu bạn thay đổi, muốn mã hóa 1 thuộc tính khác, khóa mã hóa của bảng vẫn sử dụng được.
  • Chuyển tất cả giá trị trong thuộc tính đó thành dạng mã hóa


Mặc định, thuật toán AES với khóa 192-bit được dùng để mã hóa. Bạn cũng có thể chọn 1 thuật toán khác bằng cách xác định mệnh đề điều kiện chính xác trong dòng lệnh. Chẳng hạn dùng mã hóa AES 128-bit, bạn có thể sử dụng:

sql>alter table accounts modify (ssn encrypt using 'AES128');

Bạn có thể dùng AES128, AES192, AES256, hay 3DES168 (thuật toán DES 168-bit Triple) như mệnh đề. Những giá trị này có thể tự giải thích về nó, chẳng hạn: AES256 là đại diện cho thuật toán Advanced Encryption Standard với khóa 256-bit.

Vì việc mã hóa và giải mã tiêu tốn chu kỳ CPU, bạn phải nghĩ đến ảnh hưởng của chúng trong việc thực thi. Khi bạn truy cập những thuộc tính không mã hóa của bảng, việc thực thi không khác gì nhiều so với bảng không dùng TDE. Tuy nhiên, khi bạn truy cập các thuộc tính được mã hóa, có một bộ xử lý thông tin phụ cho việc giải mã trong khi truy vấn, mã hóa trong khi thêm dữ liệu, để bạn có thể mã hóa các thuộc tính được chọn. Nếu bạn không còn cần mã hóa 1 thuộc tính, bạn có thể tắt nó đi theo bước sau:

sql>alter table account modify (ssn decrypt);
 
Việc mã hóa là tất cả về ẩn dữ liệu, nhưng thỉnh thoảng rất dễ để đoán được dữ liệu mã hóa nếu có sự lặp lại trong giá trị của dữ liệu gốc. Chẳng hạn, bảng thông tin lương nhân viên có thể chứa đựng những giá trị lặp lại. Trong truờng hợp đó, giá trị mã hóa sẽ tương tự, và 1 người xâm phạm có thể nhận ra tất cả những bộ có cùng mức lương. Để tránh sự cố này, một chút “muối” được thêm vào dữ liệu để làm cho dữ liệu mã hóa khác đi cho dù dữ liệu đầu vào giống nhau. Mặc định TDE có thêm “muối”


Tuy nhiên, nếu bạn tạo 1 chỉ mục trên 1 thuộc tính mã hóa, bạn không thể thêm “muối” vào nó. Ví dụ, để xóa bỏ “muối” khỏi thuộc tính SSN, thực thi như sau:

sql>alter table accounts modify (ssn encrypt no salt);

Bảo vệ dữ liệu của bạn khỏi tấn công và tuân theo vô số điều luật là điều không hề tầm thường. TDE giúp bạn cung cấp dữ liệu mã hóa đáp ứng yêu cầu mà không cần code và quản lý khóa phức tạp, từ đó bạn có thể tập trung vào những mục tiêu khác chiến lược hơn.