0

데이터베이스 기능을 사용하여 사용자를 인증하는 더 빠른 방법이 있습니까? crypt() 함수는 많은 시간이 걸렸습니다.데이터베이스 기능을 사용하여 사용자 인증을보다 신속하게 수행

테이블 :

id (bigserial) pkey 
username (text) indexed 
password (text) indexed [password is the hash: crypt('12345678', gen_salt('bf', 8))] 

일반 시험 :

test_db=# explain analyze SELECT id FROM users WHERE id = 1 AND password='12345678' LIMIT 1; 
                   QUERY PLAN 
------------------------------------------------------------------------------------------------------------------------------------------ 
Limit (cost=0.28..8.29 rows=1 width=8) (actual time=0.029..0.029 rows=0 loops=1) 
    -> Index Scan using users_idx_password01 on users (cost=0.28..8.29 rows=1 width=8) (actual time=0.028..0.028 rows=0 loops=1) 
     Index Cond: (password = '12345678'::text) 
     Filter: (id = 1) 
Total runtime: 0.037 ms 
(5 rows) 

크립트() 테스트 :

test_db=# explain analyze SELECT id FROM users WHERE id = 1 AND password=(crypt('12345678',password)) LIMIT 1; 
                  QUERY PLAN 
-------------------------------------------------------------------------------------------------------------------------------- 
Limit (cost=0.28..8.30 rows=1 width=8) (actual time=7.534..7.534 rows=1 loops=1) 
    -> Index Scan using users_pkey on users (cost=0.28..8.30 rows=1 width=8) (actual time=7.534..7.534 rows=1 loops=1) 
     Index Cond: (id = 1) 
     Filter: (password = crypt('12345678'::text, password)) 
Total runtime: 7.550 ms 
(5 rows) 
+1

설계 기준에 따라 아니요. 느려짐은 기능이 아니라 버그입니다. http://stackoverflow.com/a/6364778/239394를 참조하십시오. 게다가 쿼리 당 수 밀리 초의 차이에 대해 이야기하고 있습니다. 한 사용자는 반드시 알 필요가 없습니다. 예, 로그인 시도 횟수가 많은 시스템에 추가 될 수 있습니다 (예 : 서비스 거부 공격에 영향을 줄 수 있음). 그러나 해시 속도를 높이는 것은 문제를 해결하는 방법이 아닙니다. – Andrew

+0

감사합니다 Andrew, 문제를 올바르게 해결합니다. 모든 요청을 인증 받아야하고 서버가 응답하지 않는 보통 동시성 (200 req/초)으로되어 있어야합니다. 그 시점에서 하드웨어 업그레이드와 분할을 고려 중입니다. 감사. – DPZ

답변

0

내가 포스트 그레스는 쿼리를 처리하는 방법에 대해 완전히 잘 모르겠지만, crypt 함수가 모든 행에 대해 실행된다는 것은 나에게 보인다. 목적에 따라 느린 적절한 암호 해시 함수 사용을 고려할 때 이러한 쿼리는 모든 행에서 느려집니다.

SELECT password FROM users WHERE username = "carfield" 

나중에 코드에서 발견 된 암호 해시를 테스트 :

이러한 쿼리를 처리하는 방법은 사용자 만 검색하고 나중에 암호 해시를 확인할 수있다. 이것은 또한 각 암호마다 고유 한 염을 처리 할 수있게 해줍니다. 적절한 해시 함수는 BCrypt, PBKDF2 또는 SCrypt이며 모두 비용 요소가 있습니다. 프로그래밍 환경에서 이미 기능을 제공하는 경우가 많으며, PHP의 예입니다.

$isPasswordCorrect = password_verify($password, $existingHashFromDb); 
+0

감사! 평균 33 % 빨라졌습니다. 어떤 조사가 crypt() 함수가 모든 레코드에 대해 실행되지 않는 것처럼 보인 후에는 postgres/pgcrypto 라이브러리가 PHP 구현보다 느린 호출을 처리하는 방법입니다. 나는 DB가 인증을 관리하도록하는 것이 더 강력하고 빠르다고 잘못 생각했다. – DPZ

+0

@DPZ - 흥미 롭다. PHP는 [password_hash()] (http://www.php.net/manual/en/function.password-hash.php) 함수를 사용하여 BCrypt를 기본 구현했다. 빠른 구현은 물론 보안에 좋은 비용 요소를 증가시킵니다. – martinstoeckli

관련 문제