DBMS 2

DA, SQL, DB보안 등 실무자를 위한 위한 DB기술 바이블!

MySQL 접근 권한 시스템

DBMS 2
MySQL 가이드
데이터 베이스 관리
MySQL 접근 권한 시스템
작성자
admin
작성일
2021-02-19 10:51
조회
4800

MySQL 접근 권한 시스템

권한 시스템이 하는 일
권한 시스템은 어떻게 동작하는가
MySQL이 제공하는 권한
MySQL 서버에 접속하기
접근 제어, Stage 1: 접속 검증
접근 제어, Stage 2: 요청 검증
권한 변경이 적용되는 시점
Access denied 에러의 원인
MySQL 4.1 이후의 패스워드 해싱

MySQL 은 진보된 보안 및 권한 시스템을 가지고 있다. 이 섹션에서는 이 권한 시스템이 어떻게 동작되는지를 설명하고 있다.


권한 시스템이 하는 일

MySQL 권한 시스템은 지정 호스트로부터 접속하는 사용자를 승인하고 그 사용자에게 SELECT, INSERT, UPDATE, 그리고 DELETE와 같은 데이터 베이스 권한을 부여하는 일을 주로 한다.

또 다른 기능으로는 익명의 사용자를 허용하고, LOAD DATA INFILE과 같은 MySQL-관련 함수 및 관리 동작 권한을 승인하는 것이다.


권한 시스템은 어떻게 동작하는가

MySQL 권한 시스템은 모든 사용자가 허용된 연산만을 하도록 한다. 한명의 일반 사용자로 여러분이 MySQL 서버에 접속을 하게 되면, 여러분이 접속한 서버와 여러분이 지정한 사용자 이름을 가지고 ID를 결정한다. 접속을 한 후에 어떤 요청을 할 경우에는, 시스템은 여러분의 ID와 여러분이 원하는 것에 따라서 권한을 승인하게 된다.

MySQL은 여러분을 구분하기 위해 여러분의 호스트 이름과 사용자 이름을 모두 고려한다. 예를 들면, office.example.com에서 접속한 사용자 joe는 home.example.com에서 접속한 사용자 joe와 동일한 사람일 필요는 없다. MySQL은 우연히 동일한 이름을 가지고 있는 서로 다른 머신상의 사용자로 여러분을 인식해서 이것을 처리한다: 여러분은 office.example.com에서 접속한 joe를 위해 하나의 권한 셋을 승인하고, 그리고 home.example.com에서 접속한 joe를 위한 권한 셋을 다르게 승인할 수가 있다.

서버에 접속을 하는 클라이언트 프로그램을 구동 시킬 때 MySQL 접근 제어는 두 단계로 이루어진다:


  • Stage 1: 서버는 여러분의 접속을 허용할지 검사.
  • Stage 2: 여러분이 접속을 할수 있다고 가정하면, 서버는 여러분이 입력하는 각 명령문에 대해서 충분한 실행 권한을 가지고 있는지를 검사. 예를 들면, 만일 여러분이 데이터 베이스에 있는 테이블에서 열을 선택하거나 또는 데이터 베이스에서 테이블을 삭제하고자 할 경우, 서버는 선택한 테이블에 대해 여러분이 SELECT 권한을 가지고 있는지 또는 삭제하고자 하는 데이터 베이스에 대해 DROP 권한을 가지고 있는지를 검사한다.

만약에 접속을 하고 있는 동안에 여러분의 권한이 변경된다면, 여러분이 입력하는 그 다음 명령문에 대해서는 변경된 내용이 즉시 효과를 나타내지는 못한다. Section 5.8.7, “권한 변경이 적용되는 시점”를 참조할 것.

서버는 mysql 데이터 베이스의 그랜트 테이블에 권한 정보를 저장한다. MySQL 서버는 시작을 할 때 이 테이블에 있는 내용을 메모리로 읽어 오며, Section 5.8.7, “권한 변경이 적용되는 시점”에서 지정하는 환경이 되면 다시 한번 그것들을 읽어 들인다. 접근-제어 결정은 그랜트 테이블의 메모리 복사본을 근거로 이루어진다.

일반적으로, 여러분은 GRANT 와 REVOKE 같은 명령문을 사용해서 계정을 설정해서 각 사용자가 그 권한을 사용할 수 있도록 그랜트 테이블 내용을 사용할 수 있다. Section 13.5.1, “계정 관리 명령문”을 참조할 것. 여기에서는 그랜트 테이블의 하부 구조와 서버가 클라이언트와 상호 통신을 할 때 그 내용을 어떻게 사용하는지에 대해 설명을 하도록 한다.

서버는 접근 제어 두 단계 모두에서 mysql 데이터 베이스에 있는 user, db, 그리고 host 테이블을 사용한다. user 와 db 테이블에 있는 컬럼들이 아래에 나와 있다. host 테이블은 db 테이블과 유사하지만, Section 5.8.6, “접근 제어, Stage 2: 요청 검증”에서 설명한 것과 같은 특별한 쓰임새를 가지고 있다.



Table Name user db
Scope columns Host Host
User Db
Password User
Privilege columns Select_priv Select_priv
Insert_priv Insert_priv
Update_priv Update_priv
Delete_priv Delete_priv
Index_priv Index_priv
Alter_priv Alter_priv
Create_priv Create_priv
Drop_priv Drop_priv
Grant_priv Grant_priv
Create_view_priv Create_view_priv
Show_view_priv Show_view_priv
Create_routine_priv Create_routine_priv
Alter_routine_priv Alter_routine_priv
Execute_priv Execute_priv
Create_tmp_table_priv Create_tmp_table_priv
Lock_tables_priv Lock_tables_priv
References_priv References_priv
Reload_priv
Shutdown_priv
Process_priv
File_priv
Show_db_priv
Super_priv
Repl_slave_priv
Repl_client_priv
Security columns ssl_type
ssl_cipher
x509_issuer
x509_subject
Resource control columns max_questions
max_updates
max_connections
max_user_connections

Execute_priv는 MySQL 5.0.0에서부터 존재는 했지만, MySQL 5.0.3 이후에야 제대로 동작을 한다.

Create_view_priv 와 Show_view_priv 컬럼은 MySQL 5.0.1에 추가되었다.

Create_routine_priv, Alter_routine_priv, 그리고 max_user_connections 컬럼은 MySQL 5.0.3에 추가 되었다.

두 번째 단계의 접근 제어가 진행되는 동안, 서버는 각 클라이언트가 각각의 요청에 대해 충분한 권한을 가지고 있는지에 대한 검증을 한다. user, db, 그리고 host 그랜트 테이블뿐만 아니라, 서버는 tables_priv 과 columns_priv 테이블에 대해서도 요청 검증을 한다. tables_priv 와 columns_priv 테이블은 테이블과 컬럼 레벨에서 파인더(finder) 권한 제어를 제공한다. 이 테이블들은 아래와 같은 컬럼을 가지고 있다:



Table Name tables_priv olumns_priv
Scope columns Host Host
Db Db
User User
Table_name Table_name
Column_name
Privilege columns Table_priv Column_priv
Column_priv
Other columns Timestamp Timestamp
Grantor

Timestamp 와 Grantor 컬럼은 현재로서는 사용되지 않기 때문에, 여기에서는 더 구체적으로 설명을 하지 않기로 한다.

스토어드 루틴을 포함하는 요청에 대해서는 서버가 procs_priv 테이블을 참조할 수도 있다. 이 테이블은 아래의 컬럼을 가지고 있다:



Table Name procs_priv
Scope columns Host
Db
User
Routine_name
Routine_type
Privilege columns Proc_priv
Other columns Timestamp
Grantor

procs_priv 테이블은 5.0.3 부터 추가되었다. Routine_type 컬럼은 MySQL 5.0.6에서 추가 되었다. 'FUNCTION' 또는 'PROCEDURE' 값을??입을 가리키기 위해 것이다. 이 컬럼은 동일한 이름을 가지고 있는 함수와 프로시저에 대해 개별적으로 권한을 허용한다.

Timestamp 와 Grantor 컬럼은 현재까지는 사용되지 않기 때문에, 여기에서는 더 이상 설명을 하지 않기로 한다.

각 테이블은 범위 (scope) 컬럼과 권한 컬럼을 가지고 있다:


  • 범위 컬럼은 테이블에 있는 각 열(엔트리)의 범위를 결정한다; 즉, 열이 적용되는 문장. 예를 들면, 'thomas.loc.gov' 와 'bob' 의 Host 와 User 값을 가지고 있는user 테이블 열은 bob의 사용자 이름을 지정하는 클라이언트가 호스트thomas.loc.gov에서 서버로 연결하는 것을 승인하기 위해 사용된다. 비슷하게, 'thomas.loc.gov', 'bob' 그리고 'reports'의 Host, User, 그리고 Db 컬럼 값을 가지고 있는 db 테이블 열은 reports 데이터 베이스에 접근하기 위해 bob이 호스트 thomas.loc.gov에서 접속을 할 때 사용된다. tables_priv 와 columns_priv 테이블은 각 열이 적용하는 테이블 또는 테이블/컬럼 조합을 지정하는 범위 컬럼을 가지고 있다. procs_priv 범위 컬럼은 각 열이 적용하는 스토어드 루틴을 가리킨다.
  • 권한 컬럼은 테이블 열이 승인한 권한을 가리킨다; 즉, 어떤 어플리케이션이 수행되고 있는지를 나타낸다. 서버는 다양한 그랜트 테이블에 있는 정보를 조합해서 사용자 권한을 완성한다. Section 5.8.6, “접근 제어, Stage 2: 요청 검증”에서는 이러한 작업을 하는데 사용되는 규칙을 설명하고 있다

범위 컬럼에는 스트링이 들어 있다. 이 컬럼들은 다음과 같이 선언된다; 각각의 디폴트 값은 빈 스트링이다:



Column Name Type
Host CHAR(60)
User CHAR(16)
Password CHAR(16)
Db CHAR(64)
Table_name R CHAR(64)
Column_name CHAR(64)
Routine_name CHAR(64)

접근-검사에 대해서는Host 값 비교는 대소 문자를 구분하지 않는다. User, Password, Db, 그리고 Table_name 값은 대소 문자를 구분한다. Column_name 과 Routine_name 값은 대소 문자를 구분하지 않는다.

user, db, 그리고 host 테이블에서 각각의 권한은 ENUM('N','Y') DEFAULT 'N'로 선언된 개별 컬럼에 지정된다. 달리 말하면, 각 권한은 비활성화 또는 활성화 될 수 있으며, 디폴트는 비활성화 상태이다.

tables_priv, columns_priv, 그리고 procs_priv 테이블에서 권한 컬럼은 SET 으로 선언된다. 이러한 컬럼 값은 테이블이 제어하는 권한의 모든 조합을 가질 수가 있다:



Table Name Column Name Possible Set Elements
tables_priv Table_priv 'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter', 'Create View', 'Show view'
tables_priv Column_priv 'Select', 'Insert', 'Update', 'References'
columns_priv Column_priv 'Select', 'Insert', 'Update', 'References'
procs_priv Proc_priv 'Execute', 'Alter Routine', 'Grant'

간단히 말하자면, 서버는 아래와 같은 방식으로 그랜트 테이블을 사용한다:


  • user 테이블 범위 컬럼은 서버에 인커밍 (incomming) 접속을 거절할지 또는 허용할지를 결정한다. 허용된 접속의 경우, 사용자 테이블에서 승인된 권한은 사용자 글로벌 (superuser) 권한을 가리킨다. 이 테이블에서 승인된 권한은 서버에 있는 모든 데이터 베이스에 적용된다.
    Note: 글로벌 권한이 모든 데이터 베이스에 대한 권한으로 간주되기 때문에, 글로벌 권한은사용자가 SHOW DATABASES를 사용하거나 또는 INFORMATION_SCHEMA 테이블의 SCHEMATA 테이블을 조사해서 모든 데이터 베이스 이름을 볼 수 있도록 한다.
  • db 테이블 범위 컬럼은 어떤 사용자가 어떤 호스트에서 어떤 데이터 베이스를 접근할 수 있는지를 알려준다. 권한 테이블은 허용되는 서버의 동작이 무엇인지를 알려준다. 데이터 베이스 레벨에서 승인된 권한은 그 데이터 베이스 및 그 안에 있는 모든 테이블에 적용된다.
  • host 테이블은 지정한db 테이블 열을 서버 호스트에 적용하고자 할 때 db 테이블과 함께 사용된다. 예를 들면, 사용자가 네트워크 상에 있는 어떤 호스트에서 데이터 베이스를 사용할 수 있도록 하기 위해서는, 사용자 db 테이블 열의 Host 값을 비워둔 다음에, host 테이블에 사용자가 사용하는 각 호스트에 대한 열을 넣어둔다. 이 방식에 대한 보다 자세한 설명은 Section 5.8.6, “접근 제어, Stage 2: 요청 검증”에서 하고 있다.
    Note: host 테이블은 INSERT, UPDATE, DELETE와 같은 명령문으로 직접 수정해야 한다. 이 테이블은 그랜트 테이블을 간접적으로 수정하는 GRANT 와 REVOKE와 같은 명령문을 사용해서는 수정할 수가 없다. 대부분의 MySQL 설치에는 이러한 테이블이 필요가 없다.
  • tables_priv 와 columns_priv 테이블은 db 테이블과 비슷하지만, 보다 잘 만들어져 있다: 이것들은 데이터베이스 레벨이 아니라 테이블과 컬럼 레벨에서 적용된다. 테이블 레벨에서 승인되는 권한은 그 테이블과 거기에 속한 컬럼에 적용된다. 컬럼 레벨에서 승인된 권한은 특정 컬럼에만 적용된다.
  • procs_priv 테이블은 스토어드 루틴에 적용된다. 루틴 레벨에서 승인된 권한은 단일 루틴에만 적용된다.

관리 권한 (RELOAD 또는 SHUTDOWN과 같은)은 user 테이블에서만 지정할 수 있다. 그 이유는 관리적인 동작이 서버 자체에서 이루어지고 데이터베이스와 관련해서는 수행되지 않기 때문이며, 따라서 이 권한들을 다른 그랜트 테이블에 기록해둘 필요는 없다. 사실, 여러분이 관리적인 동작을 수행할 수 있을지를 판단하기 위해서 서버는 user 테이블만을 참조한다.

FILE 권한 역시 user 테이블에만 지정할 수 있다. 이것은 관리적인 권한은 아니지만, 서버 호스트에서 파일을 읽거나 쓰는 능력은 여러분이 접근하는 데이터 베이스와는 무관한 것이다.

mysqld 서버는 시작이 될 때 그랜트 테이블에 있는 내용을 메모리로 읽어 들인다. FLUSH PRIVILEGES 명령문을 입력하거나 또는 mysqladmin flush-privileges 또는 mysqladmin reload 명령문을 실행해서 그 테이블의 내용을 서버가 다시 읽도록 할 수도 있다. 그랜트 테이블을 변경하면 Section 5.8.7, “권한 변경이 적용되는 시점”에서 기술한 효과가 나타난다.

여러분이 그랜트 테이블 내용을 수정하면, 변경한 내용이 권한을 원하는 형태로 설정하는지 확인하는 것이 좋다. 지정한 계정에 대해 권한을 검사하기 위해서는, SHOW GRANTS 명령문을 사용한다. (Section 13.5.4.12, “SHOW GRANTS 신텍스” 참조.) 예를 들면, pc84.example.com 과 bob에 대해서 Host 와 User 값을 가지고 있는 계정을 승인하는 권한을 알아보기 위해서는, 아래의 명령어를 입력한다:


SHOW GRANTS FOR 'bob'@'pc84.example.com';
권한-관련 문제 진단에 대한 보다 자세한 정보는 Section 5.8.8, “Access denied 에러의 원인”를 참조하기 바란다. 보안 이슈에 대한 일반적인 사항은 Section 5.7, “일반적인 보안 이슈”를 참조하기 바란다.
MySQL이 제공하는 권한

계정 권한에 대한 정보는 mysql 데이터 베이스에 있는 user, db, host, tables_priv, columns_priv, 그리고 procs_priv 테이블에 저장된다. MySQL 서버는 시작될 때 이러한 테이블의 내용을 메모리로 읽어 들이고 Section 5.8.7, “권한 변경이 적용되는 시점”에서 기술한 환경이 되면 그것들을 다시 읽어 들인다. 접근-제어 결정은 그랜트 테이블의 메모리 복사본을 근거로 이루어진다.

아래의 테이블은 GRANT 와 REVOKE 명령문에서 권한을 참조하기 위해 사용하는 이름과, 그랜트 테이블에서 각각의 권한과 함께 사용되는 컬럼 이름 그리고 그 권한이 적용되는 문장 (context)이 표시되어 있다. 각 권한이 의미하는 정보에 대해서는 Section 13.5.1.3, “GRANT 신텍스”를 참고하기 바란다.



Privilege Column Context
CREATE Create_priv databases, tables, or indexes
DROP Drop_priv databases or tables
GRANT OPTION Grant_priv databases, tables, or stored routines
REFERENCES References_priv databases or tables
ALTER Alter_priv tables
DELETE Delete_priv tables
INDEX Index_priv tables
INSERT Insert_priv tables
SELECT Select_priv tables
UPDATE Update_priv tables
CREATE VIEW Create_view_priv views
SHOW VIEW Show_view_priv views
ALTER ROUTINE Alter_routine_priv stored routines
CREATE ROUTINE Create_routine_priv stored routines
EXECUTE Execute_priv stored routines
FILE File_priv file access on server host
CREATE TEMPORARY TABLES Create_tmp_table_priv server administration
LOCK TABLES Lock_tables_priv server administration
CREATE USER Create_user_priv server administration
PROCESS Process_priv server administration
RELOAD Reload_priv server administration
REPLICATION CLIENT Repl_client_priv server administration
REPLICATION SLAVE Repl_slave_priv server administration
SHOW DATABASES Show_db_priv server administration
SHUTDOWN Shutdown_priv server administration
SUPER Super_priv server administration

MySQL의 몇몇 릴리즈판에는 그랜트 테이블의 구조를 변경해서 새로운 권한 또는 기능을 추가할 수 있도록 하고 있다. 새로운 버전의 MySQL로 업데이트를 하는 경우에는, 항상 그랜트 테이블이 새로운 버전의 기능을 포함할 수 있도록 그랜트 테이블에 대한 갱신도 함께 해야 한다. Section 5.6.2, “mysql_upgrade -MySQL 업그레이드에 대한 테이블 검사”를 참조할 것.

CREATE VIEW 와 SHOW VIEW는 MySQL 5.0.1에서 추가 되었다. CREATE USER, CREATE ROUTINE, 그리고 ALTER ROUTINE은 MySQL 5.0.3에 추가 되었다. 비록 5.0에 EXECUTE가 존재하기는 하지만, MySQL 5.0.3 이후부터 그 기능을 발휘하게 된다.

바이너리 로그가 활성화 되어 있을 때 스토어드 루틴을 생성 또는 변경하기 위해서는, Section 17.4, “스토어드 루틴과 트리거에 대한 바이너리 로깅”에서 언급하듯이 SUPER 권한이 함께 필요할 수도 있다.

CREATE와 DROP 권한은 새로운 데이터 베이스와 테이블을 생성 하거나, 또는 이미 존재하는 데이터 베이스와 테이블을 제거할 수 있도록 한다. 만약mysql 데이터 베이스 사용자에게DROP 권한을 승인한다면, 그 사용자는 MySQL 접근 권한이 저장되어 있는 데이터 베이스를 제거할 수가 있다.

SELECT, INSERT, UPDATE, 그리고 DELETE 권한은 데이터 베이스 테이블 열에서 연산을 수행한다.

SELECT 명령문은 테이블에서 열을 실제로 추출하는 경우에만 SELECT 권한을 필요로 한다. 어떤 SELECT 명령문은 테이블에 접근할 수는 없으나 데이터 베이스에 대한 권한 없이도 실행될 수 있는 것이 있다. 예를 들면, 여러분은 테이블을 참조하지 않는 수식을 계산하기 위해 mysql 클라이언트를 단순한 계산기로 사용할 수가 있다:



SELECT 1+1;
SELECT PI()*2;


INDEX 권한은 여러분이 인덱스를 생성 또는 제거할 수 있도록 한다. INDEX는 현재 존재하는 테이블에 적용된다. 만약에 여러분이 어떤 테이블에 대해서 CREATE 권한을 가지고 있다면, 여러분은 CREATE TABLE 명령문 안에 인덱스 정의문을 포함 시킬 수가 있다.

ALTER 권한은 여러분이 테이블 구조를 변경하거나 또는 이름을 바꿀 수 있는 ALTER TABLE을 사용할 수 있도록 한다.

CREATE ROUTINE 권한은 스토어드 루틴 (함수 및 프로시저)를 생성하기 위해 필요한 것이다. ALTER ROUTINE 권한은 스토어드 루틴을 변경 또는 제거하기 위해 필요하며, EXECUTE는 스토어드 루틴 실행을 위해 필요하다.

GRANT 권한은 여러분 자신이 가지고 있는 권한을 다른 사용자에게 제공할 수 있도록 한다. 이것은 데이터베이스, 테이블, 그리고 스토어드 루틴을 위해 사용될 수 있다.

FILE 권한은 여러분이 서버 호스트에서 LOAD DATA INFILE 및 SELECT ... INTO OUTFILE 명령문을 사용해서 파일을 읽고 쓸 수 있도록 해 준다. FILE 권한을 가지고 있는 사용자는 서버 호스트에 있는 모든 파일을 읽을 수 있다. (이것은 그 사용자가 모든 데이터베이스 디렉토리에 있는 모든 파일을 읽을 수가 있다는 것을 의미하는데, 그 이유는 서버가 이러한 파일들에 접근할 수 있기 때문이다.) FILE 권한은 MySQL 서버가 쓰기 권한을 가지고 있는 모든 디렉토리에서 사용자가 새로운 파일을 생성할 수 있도록 해 준다. 보안상의 이유로, 서버는 현재 존재하는 파일에 덮어 쓰기를 하지는 않는다.

나머지 권한들은 관리 연산을 위한 것들이다. 이러한 권한들 대부분은 mysqladmin 프로그램 또는 SQL 명령문 입력을 통해서 수행될 수 있다. 아래의 테이블은 mysqladmin 명령어를 사용해서 실행할 수 있는 각 관리 권한을 보여 준다:



Privilege Commands Permitted to Privilege Holders
RELOAD flush-hosts, flush-logs, flush-privileges, flush-status, flush-tables, flush-threads, refresh, reload
SHUTDOWN Shutdown
PROCESS Processlist
SUPER Kill

reload 명령어는 서버가 그랜트 테이블의 내용을 메모리로 다시 읽어 들이도록 만든다. flush-privileges는 reload과 동일한 기능을 한다. refresh 명령어는 로그 파일을 닫은 다음에 다시 열고 모든 테이블을 플러시한다. 또 다른 flush-xxx 명령어는 refresh와 유사한 기능을 수행하지만, 좀더 구체적이며 어떤 인스턴스에서는 보다 많이 사용되기도 한다. 예를 들면, 만일 여러분이 로그 파일만을 플러시 하고자 한다면, flush-logs를 사용하는 것이 refresh 보다 나은 선택이 된다.

shutdown audfudd는 서버를 셧다운 시킨다. 이것과 같은 기능을 하는 SQL 명령문은 없다.

processlist 명령어는 서버 안에서 실행되는 쓰레드에 대한 정보를 화면에 출력 한다 (즉, 클라이언트가 실행하는 명령문에 대한 정보). kill 명령어는 서버 쓰레드를 종료 시킨다. 여러분은 항상 여러분 소유의 쓰레드를 화면에 출력 또는 종료 시킬 수는 있지만, 다른 사용자가 초기화 시킨 쓰레드를 디스 플레이 하기 위해서는 PROCESS 권한이 필요하며, 다른 사용자의 쓰레드를 종료 시키기 위해서는 SUPER 권한이 있어야 한다. Section 13.5.5.3, “KILL 신텍스”를 참조할 것.

CREATE TEMPORARY TABLES 권한은 CREATE TABLE 명령문에서 키워드 TEMPORARY를 사용할 수 있도록 해 준다.

LOCK TABLES 권한은 여러분이 SELECT 권한을 가지고 있는 테이블을 잠그기 위한LOCK TABLES 명령문을 사용할 수 있도?데, 이것은 누구라도 잠겨 있는 테이블을 읽지 못하도록 해준다.

REPLICATION CLIENT 권한은 SHOW MASTER STATUS 와 SHOW SLAVE STATUS를 사용할 수 있도록 해 준다.

REPLICATION SLAVE 권한은 슬레이브 서버가 현재의 서버를 자신의 마스터로 접속하기 위해 사용하는 계정을 승인한다. 이 권한이 없다면, 슬레이브는 마스터 서버에 있는 데이터 베이스에서 이루어지는 업데이트를 요청할 수 없게 된다.

SHOW DATABASES 권한을 가지고 있는 계정은 SHOW DATABASE 명령문을 이용해서 데이터 베이스의 이름을 볼 수가 있다. 이 권한을 가지고 있지 않는 계정은 자신이 소유한 권한 내의 데이터 베이스만을 볼 수 있고, 만약에 서버가 --skip-show-database 옵션을 가지고 시작되었다면, 명령문을 전혀 사용할 수가 없게 된다. 모든 글로벌 권한은 데이터 베이스에 대한 권한을 가지고 있음을 알아두기 바란다.

각각의 계정에는 꼭 필요한 권한만을 부여하는 것이 좋다. 특정 계정에 FILE 및 관리 권한을 승인할 경우에는 매우 주의를 기울여야 한다:


  • FILE 권한은 MySQL 서버가 서버 호스트에 있는 파일을 데이터 베이스 테이블 속으로 읽어 들이는 용도로 자칫 남용될 수가 있다. 이것은 서버 데이터 디렉토리에 있는 모든 파일을 읽을 수가 있다는 의미이다. 이렇게 되면, 파일을 읽은 후에 SELECT를 사용해서 테이블에 접근해서 테이블 내용을 클라이언트 호스트에 전달할 수가 있게 된다.
  • GRANT는 사용자가 자신의 권한을 다른 사용자에게 전달할 때 필요한 권한이다. 서로 다른 권한을 가지고 있는 두 명의 사용자는 GRANT 권한을 가지고 권한을 조합할 수가 있다.
  • ALTER 권한은 테이블의 이름을 바꾸어 줌으로서 권한 시스템을 없애 버리는데 사용할 수가 있다.
  • SHUTDOWN 권한은 서버를 종료 시킴으로서 다른 사용자에 대한 모든 서비스를 거부하도록 만들 수가 있다.
  • PROCESS 권한은 패스워드 설정 또는 변경을 실행하는 명령문을 포함해서, 현재 실행 중에 있는 명령문의 텍스트를 보기 위해 사용될 수 있다.
  • SUPER 권한은 다른 클라이언트를 종료시키거나 또는 서버의 동작을 변경시키는데 사용할 수 있다.
  • mysql 데이터 베이스 자체에 대해 승인된 권한은 패스워드와 다른 접근 권한 정보를 변경시키는데 사용될 수 있다. 패스워드는 암호로 저장된다. 하지만, user 테이블의 Password 컬럼에 쓰기 접근을 할 수 있는 사용자는 계정의 패스워드를 변경할 수 있으며, 그 계정을 사용해서 MySQL 서버에 접속을 할 수가 있게 된다.

MySQL 권한 시스템을 가지고서도 할 수 없는 일이 몇 가지가 있다:


  • 여러분은 특정 사용자의 접근을 거부하도록 명확하게 지정할 수는 없다. 즉, 어떤 사용자와 접속 거부를 명백하게 매치 (match)시킬 수가 없다.
  • 여러분은 사용자가 데이터 베이스에 들어 있는 테이블을 생성 또는 삭제할 수 있는 권한은 있지만 데이터베이스 자체를 생성 또는 삭제할 수는 없도록 지정할 수는 없다.
  • 패스워드는 글로벌하게 하나의 계정에 적용된다. 여러분은 패스워드를 데이터 베이스, 테이블, 또는 루틴과 같은 특정 오브젝트에만 연관 시킬 수는 없다.
MySQL 서버에 접속하기

일반적으로, MySQL 클라이언트 프로그램은 여러분이 MySQL 서버에 접속을 할 때 특정 연결 파라미터를 지정하기를 기대한다:


  • MySQL 서버가 구동되고 있는 호스트 이름
  • 사용자 이름
  • 패스워드

예를 들면, mysql 클라이언트는 명령어 라인 프롬프트에서 아래와 같이 시작될 수 있다:



shell> mysql -h host_name -u user_name -pyour_pass

-h, -u, 그리고 -p 옵션은 --host=host_name, --user=user_name, 그리고 --password=your_pass를 대신 사용할 수 있다. -p 또는 --password= 와 뒤에 나오는 패스워드 간에는 스페이스가 없어야 한다.

만약에 여러분이 -p 또는 --password 옵션을 사용하면서 패스워드 값을 지정하지 않으면, 클라이언트 프로그램은 패스워드를 입력하도록 프롬프트를 내 보내게 된다. 이 방법이 명령어 라인에 패스워드를 표시하는 것보다 더 안전한 방법이다. 어떤 사용자라도 명령어 라인에서 ps auxww와 같은 명령어를 실행하면 여러분이 명령어 라인에 지정했던 패스워드를 볼 수가 있다. Section 5.9.6, “패스워드 보안 유지하기”를 참조.

MySQL 클라이언트 프로그램은 여러분이 연결 파라미터 옵션을 지정하지 않으면 해당 디폴트 값을 사용한다:


  • 디폴트 호스트 이름은 localhost.
  • 디폴트 사용자 이름은 윈도우에서는 ODBC이고 유닉스에서는 여러분의 유닉스 로그인 이름이 된다.
  • -p 또는 -password 중에 아무것도 지정하지 않으면, 패스워드는 지정되지 않는다.

따라서, jake라는 로그인 이름을 가지고 있는 유닉스 사용자에 대해서는, 아래의 모든 명령어가 동일한 것이 된다:



shell> mysql -h localhost -u jake
shell> mysql -h localhost
shell> mysql -u jake
shell> mysql


다른 MySQL 클라이언트도 비슷하게 동작을 한다.

여러분은 클라이언트 프로그램을 호출할 때마다 명령어 라인에 매번 입력하는 수고를 피하기 위해 서버에 접속할 때 사용되는 디폴트 값을 달리 지정할 수가 있다. 이것은 여러 가지 방법으로 실행할 수가 있다:


  • 여러분은 옵션 파일의 [client] 섹션에 접속 파라미터를 지정할 수가 있다. 이 파일에 관련된 섹션은 아래와 같다:
    [client]
    host=host_name
    user=user_name
    password=your_pass

    Section 4.3.2, “옵션 파일 사용하기”를 참조 할 것.
  • 여러분은 환경 변수를 사용해서 몇몇 접속 파라미터를 지정할 수가 있다. mysql에 대한 호스트는 MYSQL_HOST를 사용해서 지정할 수가 있다. MySQL 사용자 이름은 USER를 사용해서 지정할 수가 있다 (이것은 윈도우와 NetWare에만 해당함). 비록 보안에 문제가 있기는 하지만, 패스워드는 MYSQL_PWD를 사용할 수가 있다; Section 5.9.6, “패스워드 보안 유지하기”를 참조.
접근 제어, Stage 1: 접속 검증

여러분이 MySQL 서버에 접속을 시도할 때, 서버는 여러분의 ID와 패스워드를 근거로 접속을 허용하거나 거부를 하게 된다. 여러분의 ID와 패스워드가 올바른 것으로 판명되면, 서버는 Stage 2 로 들어가고 여러분의 요청 사항을 기다리게 된다.

여러분의 ID는 다음의 두 가지 정보를 기초로 한다:


  • 여러분이 접속하는 클라이언트 호스트
  • 여러분의 MySQL 사용자 이름

ID 검사는 세 가지의 user 테이블 범위 컬럼을 사용해서 한다 (Host, User, 그리고 Password). 서버는 user 테이블에 있는 Host 와 User 컬럼의 열이 클라이언트의 호스트 이름 및 사용자 이름과 일치할 경우에만 접속을 허용하고, 클라이언트는 그 열에서 지정한 패스워드를 주게 된다.

user 테이블에 있는 Host 값은 아래와 같이 지정될 수 있다:


  • Host 값은 호스트 이름 또는 IP 번호, 또는 로컬 호스트를 가리키는 'localhost'가 될 수 있다.
  • Host 컬럼 값에 와일드카드 문자 ‘%’ 및 ‘_’를 사용할 수 있다. 이 문자들은 LIKE 연산자를 사용하는 패턴-매칭 (pattern-matching) 동작과 동일한 의미를 갖는다. 예를 들면, '%' 의 Host 값은 모든 호스트 이름과 매치가 되는데 비해서, '%.mysql.com' 값은 mysql.com 도메인에 있는 모든 호스트와 매치가 된다.
  • IP 번호로 지정된 Host 값에 대해서는, 네트워크 번호를 위해서 얼마나 많은 주소 비트 (bit)를 사용하고 있는지를 가리키는 넷마스크 (netmask)를 지정할 수가 있다. 예를 들면:
    GRANT ALL PRIVILEGES ON db.* TO jake@'192.58.197.0/255.255.255.0';
    위의 예에서 보면, jake는 아래의 조건이 일치하는 경우에 IP 번호 client_ip를 가지고 있는 어떤 호스트에서도 접속을 할 수가 있게 된다:
    client_ip & netmask = host_ip
    즉, GRANT 명령문은 아래와 같이 보인다:
    client_ip & 255.255.255.0 = 192.58.197.0
    이 조건을 만족하면서 MySQL 서버에 접속을 할 수 있는 IP 번호는 192.58.197.0 에서 192.58.197.255 사이 범위 내에 있는 것들이다. Note: 넷마스크 (netmask)는 서버가 8, 16, 24, 또는 32 비트의 주소를 사용할 때에만 사용될 수 있다. 예를 들면:
    • 192.0.0.0/255.0.0.0: 192 클래스 A 네트워크에 있는 호스트
    • 192.168.0.0/255.255.0.0: 192.168 클래스 B 네트워크에 있는 호스트
    • 192.168.1.0/255.255.255.0: 192.168.1 클래스 C 네트워크에 있는 호스트
    • 192.168.1.1: 이 IP에만 한정
    아래의 넷마스크는 (28 비트) 동작하지 않는다:
    192.168.0.1/255.255.255.240
  • db 테이블 열의 빈 Host 값은, 그 값의 권한을 host 테이블에 있는 열 중에서 클라이언트의 호스트 이름과 일치하는 열의 권한과 조합을 해야 한다는 것을 의미한다. 권한은 AND (intersection) 연산을 사용해서 조합 되며, OR (union)를 통해서 만들어지지는 않는다.
    다른 그랜트 테이블에 있는 빈 Host 값은 '%'과 동일하다.

Host 컬럼에서는 IP 와일드카드 값을 사용할 수 있기 때문에 (예를 들면, 서브넷 상에 있는 모든 호스트를 매치하기 위한 '144.155.166.%'), 어떤 사람들은 호스트의 이름을 144.155.166.somewhere.com로 해서 이러한 기능을 활용하고자 할 수도 있다. 이러한 시도를 하지 못하게 하기 위해서, MySQL은 숫자 및 점 (dot)으로 시작하는 호스트 이름에서는 매칭을 허용하지 않는다. 따라서, 만약에 여러분이 1.2.foo.com과 같은 이름의 호스트를 가지고 있다면, 이 이름은 그랜트 테이블의 Host 컬럼과는 결코 매칭이 되지 않게 된다. IP 와일드카드 값은 IP 번호에만 매치되며, 호스트 이름에는 매치되지 않는다.

User 컬럼에서는, 비록 와일드카드 문자는 허용되지 않지만, 비어있는 값 (blank value)을 지정해서 모든 이름을 매칭시킬 수가 있다. 만약에 인커밍 (incomming) 접속과 매치되는 user 테이블 열이 빈 (blank) 사용자 이름이라면, 사용자는 이름이 없는 익명의 사용자로 간주되며, 클라이언트가 실제로 지정한 이름을 갖는 사용자로 간주되지 않는다. 이것은 접속이 되어 있는 동안 (즉, Stage 2 동안)에 모든 다른 접근을 검사할 목적으로 빈 사용자 이름을 사용한다는 의미이다

Password 컬럼은 비워둘 수가 있다. 이것은 와일드카드 문자가 아니며 모든 패스워드가 매칭을 한다는 것을 의미하는 것은 아니다. 이것은 사용자가 반드시 패스워드를 지정하지 않고 접속을 해야 한다는 것을 의미한다.

user 테이블에 있는 비어 있지 않는 (Non-Blank) Password 값은 암호화 되어 있게 된다. MySQL은 모든 사람이 볼 수 있는 평범한 문장으로 패스워드를 저장하지는 않는다. 반면에, 접속을 시도하는 사용자가 입력한 패스워드는 암호화가 된다 (PASSWORD() 함수를 사용한다). 암호화된 패스워드는 접속이 이루어지는 동안 계속 사용된다. 암호화된 패스워드는 관리자 이외에는 절대로 알려 주지 말도록 한다.

MySQL 5.0은 접속 프로세스가 진행되는 동안 패스워드를 보호하기 위해 이전 버전에 비해 보다 강력한 인증 방식을 구현하였다. 이 방식은 TCP/IP 패킷 또는 mysql 데이터 베이스가 해킹을 당하더라도 안전을 보장한다. Section 5.8.9, “MySQL 4.1 이후의 패스워드 해싱”을 참조할 것.

아래의 테이블은 user 테이블에 있는 Host 와 User 값의 조합이 인커밍 (incomming) 접속에 대해 얼마나 다양하게 적용될 수 있는지를 보여준다.



Host Value User Value Allowable Connections
'thomas.loc.gov' 'fred' fred, connecting from thomas.loc.gov
'thomas.loc.gov' '' Any user, connecting from thomas.loc.gov
'%' 'fred' fred, connecting from any host
'%' '' Any user, connecting from any host
'%.loc.gov' 'fred' fred, connecting from any host in the loc.gov domain
'x.y.%' 'fred' fred, connecting from x.y.net, x.y.com, x.y.edu, and so on (this is probably not useful)
'144.155.166.177' 'fred' fred, connecting from the host with IP address 144.155.166.177
'144.155.166.%' 'fred' fred, connecting from any host in the 144.155.166 class C subnet
'144.155.166.0/255.255.255.0' 'fred' Same as previous example

다중 매치가 가능할 경우, 서버는 반드시 어떤 것을 사용할지를 결정해야 한다. 서버는 이 문제를 다음과 같이 해결한다:


  • 서버가 user 테이블을 메모리로 읽어 올 때마다, 서버는 열을 정렬한다.
  • 클라이언트가 접속을 시도할 때, 서버는 정렬된 순서로 열을 검사한다.
  • 서버는 클라이언트의 호스트 이름과 사용자 이름이 일치하는 맨 처음의 열을 사용한다.

위의 동작이 진행되는 것을 보기 위해서, user 테이블이 아래와 같이 되어 있다고 가정하자:



+-----------+----------+-
| Host | User | ...
+-----------+----------+-
| % | root | ...
| % | jeffrey | ...
| localhost | root | ...
| localhost | | ...
+-----------+----------+-


서버가 테이블의 내용을 메모리로 읽어 올 때, 서버는 Host 값 중에서 가장 명확하게 사용되고 있는 것을 가지고 열을 정렬한다. 문자로 된 호스트 이름과 IP 번호가 가장 명확한 것이다. 패턴 '%' 는 “모든 호스트 (any host)”를 의미하며 가장 일반적인 것이 된다. 동일한 Host 값을 가지는 열은 가장 명확한 User 값을 가지고 우선 정렬이 된다 (빈 User 값은 “모든 사용자 (any user)”를 의미하며 가장 일반적인 것이 된다). user 테이블에서 보듯이, 정렬의 결과는 다음과 같이 보이게 된다:



+-----------+----------+-
| Host | User | ...
+-----------+----------+-
| localhost | root | ...
| localhost | | ...
| % | jeffrey | ...
| % | root | ...
+-----------+----------+-


클라이언트가 접속을 시도할 때, 서버는 정렬된 열을 검사하고 처음으로 매치되는 값을 사용한다. jeffrey가 localhost에서 한 접속의 경우, 테이블 열 중에 두 개가 일치를 한다: 하나는 'localhost' 와 ''의 Host 와 User 열이고, 다른 하나는 '%' 와 'jeffrey'의 열이다. 정렬된 순서에서 'localhost' 열이 처음으로 나타나며, 따라서 서버는 이것을 사용한다.

아래에 다른 예가 있다. user 테이블이 아래와 같다고 가정하자:



+----------------+----------+-
| Host | User | ...
+----------------+----------+-
| % | jeffrey | ...
| thomas.loc.gov | | ...
+----------------+----------+-


정렬된 테이블은 다음과 같다:



+----------------+----------+-
| Host | User | ...
+----------------+----------+-
| thomas.loc.gov | | ...
| % | jeffrey | ...
+----------------+----------+-

jeffrey가 thomas.loc.gov에서 한 접속에서는 처음의 열이 일치를 하고, 반면에 jeffrey가 whitehouse.gov에서 한 접속에서는 두 번째가 일치를 하게 된다.

만약에 서버에는 접속할 수 있으나 하고자 하는 일에 대해서는 권한을 가지고 있지 않다면, 여러분은 다른 계정으로 인증을 받아야 한다. 서버가 여러분을 인증하는데 사용하는 계정이 어떤 것인지를 알기 위해서는, CURRENT_USER() 함수를 사용한다. 이 함수는 일치하는 user 테이블 열에서 User 와 Host 값을 가리키는 user_name@host_name 형태의 값을 리턴한다. Jeffrey가 접속을 해서 아래의 쿼리를 입력한다고 가정하자:



mysql> SELECT CURRENT_USER();
+----------------+
| CURRENT_USER() |
+----------------+
| @localhost |
+----------------+



여기에 나타나 있는 결과는 매칭된 user 테이블 열이 빈 User 컬럼 값을 가지고 있다는 것을 가리킨다. 달리 표현하면, 서버는 jeffrey를 익명의 사용자로 취급하고 있다는 것이다.

여러분이 인증 문제를 진단하기 위해 할 수 있는 방법 중의 하나는 user 테이블을 출력해서 일일이 첫 번째 매칭되는 것을 찾는 것이다.


접근 제어, Stage 2: 요청 검증

서버에 접속을 하고 나면, 서버는 접근 제어: Stage 2를 진행한다. 여러분이 접속 상태에서 입력하는 각각의 요청에 대해서, 여러분이 원하는 서버 동작이 무엇인지를 판단하고, 여러분이 그러한 요청을 할 만한 충분한 권한을 가지고 있는지를 검사한다. 이러한 일련의 동작은 그랜트 테이블의 권한 컬럼을 사용해서 진행 한다. 이러한 권한은 user, db, host, tables_priv, columns_priv, 또는 procs_priv 테이블로부터 가져 온다. (Section 5.8.2, “권한 시스템이 어떻게 동작하는가”를 참조 할 것.)

user 테이블은 디폴트 데이터 베이스와는 상관 없이 권한을 글로벌 기반으로 승인한다. 예를 들면, 만약에 user 테이블이 여러분의 DELETE 권한을 승인한다면, 여러분은 서버 호스트에 있는 데이터 베이스의 어떤 테이블 열도 삭제할 수가 있게 된다! 달리 말하면, user 테이블 권한은 superuser 권한인 것이다. user 테이블에 대한 권한은 데이터 베이스 관리자와 같은 사람에게만 부여하는 것이 현명하??스-관련 권한을 승인한다. 이러한 테이블에 있는 범위 컬럼 값은 값은 다음과 같은 형태를 가진다:


  • 와일드카드 문자 ‘%’ 와 ‘_’ 는 각 테이블의 Host 와 Db 컬럼에서 사용할 수 있다. 이 문자들은 LIKE 연산자와 함께 실행되는 패턴-매칭 동작과 동일한 의미를 가진다. 만약에 여러분이 권한을 승인할 때 이들 문자를 사용하고자 한다면, 백슬레시를 가지고 문자를 종료 시켜야 한다. 예를 들면, 데이터 베이스 이름에 (‘_’) 문자를 포함 시키고자 한다면, GRANT 명령문에서 이름을 ‘\_’형태로 지정한다.
  • db 테이블에 있는 '%' Host 값은 “모든 호스트 ( any host)”를 의미한다. Host 값을 비워 두면 “host 테이블을 나중에 참조”한다는 의미가 된다.
  • host 테이블의 '%' 또는 빈 Host 값은 “모든 호스트 (any host)”를 의미한다.
  • db 또는 host 테이블의 값이 '%' 또는 비어 있는 Db 값이 되면 “모든 데이터 베이스 (any database)”를 의미하게 된다.
  • 두 테이블에서 User 값이 비게 되면 익명의 사용자를 매치한다.

서버는 db 와 host 테이블을 메모리로 읽어 오고 서버가 user 테이블을 읽으면서 동시에 정렬한다. 서버는 db 테이블을 Host, Db, 그리고 User 범위 컬럼을 근거로 정렬하며, host 테이블은 Host 및 Db 범위 컬럼을 근거로 정렬한다. user 테이블을 사용해서 정렬을 하기 때문에, 정렬은 가장 특징적인 값을 우선 사용하고 가장 일반적인 값을 맨 나중에 사용하며, 서버가 매칭된 엔트리를 검사할 때에는 가장 먼저 매칭된 것을 사용하게 된다.

tables_priv, columns_priv, 그리고 proc_priv 테이블은 테이블-관련 (table-specific), 컬럼-관련 (column-specific), 그리고 루틴-관련 (routine-specific) 권한을 승인한다. 이러한 테이블의 범위 컬럼에 있는 값은 아래의 형태를 따르게 된다:


  • 와일드카드 문자 ‘%’ 와 ‘_’ 는 Host 컬럼에서 사용할 수 있다. 이 문자들은 LIKE 연산자와 함께 실행되는 패턴-매칭 동작과 동일한 의미를 가진다.
  • '%' 또는 비어 있는 Host 값은 “모든 호스트 (any host)”를 의미한다.
  • Db, Table_name, 그리고 Column_name 컬럼은 와일드 카드 또는 비어있는 값을 가질 수가 없다

서버는 Host, Db, 그리고 User 컬럼을 근거로 tables_priv, columns_priv, 그리고 procs_priv 테이블을 정렬한다. 이것은 db 테이블을 정렬하는 것과 비슷하지만, Host 컬럼만이 와일드 카드 문자를 가질 수 있기 때문에 보다 단순하게 진행된다.

서버는 각각의 인커밍 (incomming) 요청을 검증하기 위해 정렬된 테이블을 사용한다. SHUTDOWN 또는 RELOAD와 같은 관리적인 권한을 요구하는 요청에 대해서, 서버는 user 테이블 열만을 검사하는데, 그 이유는 이 테이블만이 관리적인 권한을 지정하기 때문이다. 서버는 그 열이 요청된 동작을 허용할 경우에 접근을 승인하며, 그 반대일 경우에는 거절을 한다. 예를 들면, 만일 여러분이 mysqladmin shutdown을 실행하길 원하지만 user 테이블 열이 여러분의 SHUTDOWN 권한을 승인하지 않는다면, 서버는 db 또는 host 테이블에 대한 검사를 하지도 않고 거절을 하게 된다. (이 러한 테이블에는 Shutdown_priv 컬럼이 없으므로, 이것들을 검사할 필요가 없게 된다.)

데이터 베이스에 관련된 요청 (INSERT, UPDATE, 등등)에 대해서는, 서버는 우선 user 테이블 열을 사용해서 사용자 글로벌 (superuser) 권한을 검사한다. 만일 그 열이 요청된 동작을 허용할 경우, 접근이 승인된다. 만약에 이 테이블에 있는 글로벌 권한이 충분하지 않다면, 서버는 db 와 host 테이블을 검사해서 사용자의 데이터 베이스 관련 권한을 판단한다:


  1. 서버는 Host, Db, 그리고 User 컬럼 매치를 위해 db 테이블을 검사한다. Host 와 User 컬럼은 사용자의 호스트 이름과 MySQL 사용자 이름간 연결에 매치된다. Db 컬럼은 사용자가 접근하고자 하는 데이터 베이스와 매치가 된다. 만약에 Host 와 User용 열이 없다면, 접근은 거부된다.
  2. 만약에 매칭되는 db 테이블 열이 있고 그 열의 Host 컬럼이 비어 있지 않다면, 그 열은 사용자의 데이터 베이스-특성 권한을 정의하는 것이다.
  3. 만약에 매칭되는 db 테이블 열의 Host 컬럼이 비어 있다면, 이것은 host 테이블이 데이터 베이스에 접근이 허용된 호스트를 모두 열거한다는 것을 의미한다. 이와 같은 경우, Host 와 Db 컬럼에 매치되는 것을 host 테이블에서 찾는 연산이 진행된다. host 테이블 열 중에 어떤 것도 매치가 되지 않으면, 접근은 거부된다. 만약에 매치되는 것이 있으면, 사용자 데이터 베이스-관련 권한은 db 와 host 테이블 엔트리에 있는 권한의 교집합 (intersection) 형태로 계산된다 (합집합 (union)이 아님); 즉, 양쪽 엔트리에서 'Y' 인 권한.

db 와 host 테이블 엔트리가 승인한 데이터베이스-관련 권한을 확인한 후에, 서버는 이 권한들을 user 테이블이 승인하는 글로벌 권한에 추가한다. 만일 그 결과가 요청 받은 동작을 허용하면, 접근이 승인된다. 그렇지 않으면, 서버는 tables_priv 와 columns_priv 테이블에 있는 사용자 테이블과 컬럼 권한을 계속해서 검사하며, 그것들을 사용자의 권한에 추가하고, 그리고 그 결과를 가지고 승인 또는 거절을 한다. 스토어드 루틴 동작의 경우, 서버는 tables_priv 와 columns_priv가 아닌 procs_priv 테이블을 사용한다.

불리안 형식의 수식을 사용하면, 위에서 설명한 사용자 권한을 계산하는 동작 방식은 아래와 같이 정리할 수가 있다:



global privileges
OR (database privileges AND host privileges)
OR table privileges
OR column privileges
OR routine privileges


처음부터 글로벌 user 열 권한이 요청 받은 동작을 처리하기에 부족하다면, 서버가 그러한 권한을 데이터 베이스, 테이블, 그리고 컬럼 권한을 나중에 추가하는 이유에 대해서는 분명하지 않을 수도 있다. 그 이유는 요청 동작이 하나 이상의 권한을 요구하기 때문이다. 예를 들면, 만약에 여러분이 INSERT INTO ... SELECT 명령문을 실행한다면, 여러분은 INSERT SELECT에 대한 권한이 필요하게 된다. 여러분의 권한은 user 테이블 열과 db 테이블 열이 서로 다른 권한을 승인하는 형태가 될 것이다. 이와 같은 경우, 여러분은 요청 받은 동작을 수행할 수 있는 충분한 권한을 가지게 되지만, 서버는 양 쪽 테이블에 이러한 것을 알려줄 수가 없게 된다; 양쪽 테이블의 엔트리가 승인한 권한들은 반드시 서로 연결 되어야 한다.

GRANT 또는 REVOKE 명령문은 host 테이블에 영향을 주지 못하기 때문에, 대부분의 MySQL 설치에서는 사용되지 않는다. 만약에 여러분이 이것을 직접 수정한다면, 이것을 보안 서버 리스트 관리와 같은 몇몇 특별한 목적으로 사용할 수가 있다. 예를 들면, TcX에서, host 테이블은 로컬 네트워크에 있는 모든 머신의 리스트를/P>

또한 host 테이블을 사용해서 안전하지 못한 호스트를 가리킬 수도 있다. public.my.domain라는 머신이 안전성이 검증되지 않은 망에 있다고 가정하자. 여러분은 아래와 같은 host 테이블을 사용하여 그 머신을 제외한 모든 호스트가 접근을 할 수 있도록 만들 수가 있다:



+--------------------+----+-
| Host | Db | ...
+--------------------+----+-
| public.my.domain | % | ... (all privileges set to 'N')
| %.my.domain | % | ... (all privileges set to 'Y')
+--------------------+----+-


권한 변경이 적용되는 시점

mysqld가 시작이 될 때, 서버는 모든 그랜트 테이블 내용을 메모리로 읽어 온다. 메모리에 있는 테이블은 그 시점부터 접근 제어에 적용된다.

서버가 그랜트 테이블을 다시 읽어 올 때, 현재 존재하는 클라이언트 접속에 대한 권한은 아래와 같이 영향을 받는다:


  • 테이블과 컬럼의 권한 변경은 클라이언트의 다음 요청부터 적용된다.
  • 데이터 베이스 권한 변경은 다음에 실행되는 USE db_name 명령문부터 적용된다.
  • 글로벌 권한 및 패스워드의 변경은 클라이언트가 다음에 접속을 할 때 적용된다.

만약에 여러분이 GRANT, REVOKE, 또는 SET PASSWORD와 같은 명령문을 사용해서 간접적으로 그랜트 테이블을 수정한다면, 서버는 이러한 변경 사항을 인지하게 되고 그랜트 테이블을 메모리로 즉시 다시 읽어 온다.

만약에 INSERT, UPDATE, 또는 DELETE와 같은 명령문을 사용해서 그랜트 테이블을 직접 수정한다면, 여러분이 서버를 다시 시작하거나 또는 서버가 그랜트 테이블을 다시 읽어 오도록 만들 때까지 변경 사항이 적용되지 않는다. 그랜트 테이블을 수동으로 읽어 오기 위해서는 FLUSH PRIVILEGES 명령문을 입력하거나 또는 mysqladmin flush-privileges 또는 mysqladmin reload 명령어를 실행한다.

만약에 그랜트 테이블을 직접 수정하였지만 다시 읽어 오는 것을 잊었을 경우에는, 서버가 재 구동 되기 전까지는 변경 사항이 적용되지 않는다.


Access denied 에러의 원인

만약에 여러분이 MySQL 서버에 접속을 시도할 때 문제가 발생한다면, 아래의 과정 중에 하나를 가지고 문제를 해결하도록 한다.


  • 서버가 구동되고 있는지를 확인한다. 만약에 아래와 같은 에러가 나오는 원인 중의 하나는, 서버가 구동을 하고 있지 않는 것이다:
    shell> mysql
    ERROR 2003: Can't connect to MySQL server on 'host_name' (111)
    shell> mysql
    ERROR 2002: Can't connect to local MySQL server through socket
    '/tmp/mysql.sock' (111)

    서버는 구동을 하고 있다고 한다면, TCP/IP 포트, 네임드 파이프, 또는 유닉스 소켓 파일등을사용해서 서버에 접속을 다시 시도해 본다. 클라이언트 프로그램을 호출할 때 이 문제를 해결하기 위해서는, --port 옵션을 사용해서 포트 번호를 지정하거나, 또는 --socket 옵션을 사용해서 네임드 파이프 또는 유닉스 소켓 파일의 이름을 지정한다. 소켓 파일이 있는 곳을 알아내기 위해서는, 아래의 명령어를 사용한다:
    shell> netstat -ln | grep mysql


  • 서버가 접근 제어를 올바르게 처리할 수 있도록 그랜트 테이블을 정확히 설정해야 한다. 몇몇 배포판의 경우 (윈도우상의 바이너리 배포판, 또는 리눅스의 RPM 등)에는, 설치 과정에서 그랜트 테이블을 가지고 있는 mysql 데이터 베이스를 초기화 시킨다. 이러한 일을 하지 못하는 배포판의 경우에는, mysql_install_db 스크립트를 사용해서 수동으로 그랜트 테이블을 초기화 해야 한다. Section 2.9.2, “유닉스 설치후 처리 프로세스”를 참조.
    그랜트 테이블을 초기화 시켜야 할지를 판단할 수 있는 한 가지 방법은 데이터 디렉토리 밑에 있는 mysql 디렉토리를 검사하는 것이다. (데이터 디렉토리는 보통 data 또는 var라는 이름으로 되어 있고 MySQL 설치 디렉토리 아래에 있다.) mysql 데이터 디렉토리에 user.MYD라는 파일이 있는지 확인한다. 만약에 없다면, mysql_install_db 스크립트를 실행한다. 이 스크립트를 실행하고 서버를 재 시작한 다음에, 아래의 명령어를 실행해서 초기 권한을 테스트한다:
    shell> mysql -u root test
    이렇게 하면, 여러분은 에러없이 서버에 접속할 수 있게 된다.
  • MySQL 설치를 갱신한 후에는, 서버에 접속을 해서 사용자와 사용자들의 접근 퍼미션 (permission)을 설정한다:
    shell> mysql -u root mysql
  • 만약에 이미 설치되어 있는 MySQL을 새로운 버전으로 업그레이드를 하였다면, 여러분은 mysql_upgrade 스크립트를 다시 실행하였는가? 만약에 하지 않았다면, 실행하도록 한다. 그랜트 테이블의 구조는 새로운 기능이 추가되면 변경이 되기 때문에, 버전 업그레이드를 한 후에는 항상 테이블이 새로운 버전 구조를 가지고 있도록 만들어야 한다. 이렇게 하는 방법은 Section 5.6.2, “mysql_upgrade -MySQL 업그레이드를 위한 테이블 검사하기”를 참조하기 바란다.
  • 만약에 클라이언트 프로그램이 서버에 접속을 할 때 아래와 같은 에러 메시지를 받게 된다면, 이것은 클라이언트가 만들어 내는 포맷이 아닌 새로운 포맷의 패스워드를 서버가 요청한다는 것을 의미하는 것이다:
    shell> mysql
    Client does not support authentication protocol requested
    by server; consider upgrading MySQL client

    이것을 처리하는 방법에 대해서는 Section 5.8.9, “MySQL 4.1 이후의 패스워드 해싱”을 참조하기 바란다.
  • 만약에 여러분이 root 사용자로 접속을 시도할 때 아래와 같은 에러를 받게 되면, 이것은 user 테이블에 'root' 값 User 컬럼을 가지고 있는 열이 없고 mysqld가 클라이언트용 호스트 이름을 해석하지 못하고 있다는 것을 의미한다:
    Access denied for user ''@'unknown' to database mysql
    이와 같은 경우에는, --skip-grant-tables 옵션을 가지고 서버를 재 시작하고 /etc/hosts 파일 또는 \windows\hosts 파일을 편집해서 호스트 엔트리에 클라이언트 호스트를 추가하도록 한다.
  • 클라이언트 프로그램은 옵션 파일 또는 환경 변수에서 지정하는 접속 파라미터를 사용한다는 것을 기억하기 바란다. 만약에 여러분이 명령어 라인에서 접속 파라미터를 지정하지 않을 때 클라이언트 프로그램이 틀린 디폴트 접속 파라미터를 보낸다고 생각되면, 여러분이 지정한 환경 변수와 적용 되는 옵션 파일을 검사하기 바란다. 예를 들면, 만일 여러분이 아무런 옵션 없이 클라이언트를 구동할 때 Access denied라는 에러를 받게 된다면, 여러분의 옵션 파일들 안에 이전의 패스워드 타입을 지정했는지 확인한다!
    클라이언트 프로그램을 호출할 때 --no-defaults 옵션을 사용해서 옵션 파일을 사용하지 못하도록 할 수가 있다. 예를 들면:
    shell> mysqladmin --no-defaults -u root version
  • 만일 아래와 같은 에러가 나온다면, 이것은 root 패스워드를 잘못 사용했다는 것을 의미한다:
    shell> mysqladmin -u root -pxxxx ver
    Access denied for user 'root'@'localhost' (using password: YES)

    만약에 아무런 패스워드도 지정하지 않았는데도 위와 같은 에러가 나온다면, 이것은 옵션 파일들 중 한곳에 잘못된 패스워드를 넣어 두었다는 것을 의미한다. 위에 나온 것을 가지고 --no-defaults 옵션을 사용해서 다시 한번 시도한다. 만약에 root 패스워드를 잊었다면, mysqld를 --skip-grant-tables 옵션으로 시작해서 패스워드를 변경하도록 한다.
  • 만약에 SET PASSWORD, INSERT, 또는 UPDATE를 사용해서 패스워드를 변경한다면, 여러분은 반드시 PASSWORD() 함수를 사용해서 패스워드를 암호화 해야 한다. PASSWORD()를 사용하지 않으면, 패스워드는 동작을 하지 않게 된다. 예를 들면, 아래의 명령문은 패스워드를 설정하기는 하지만, 암호화를 하지 못하기 때문에 사용자는 접속을 할 수가 없게 된다:
    SET PASSWORD FOR 'abe'@'host_name' = 'eagle';
    대신에, 아래와 같이 패스워드를 설정한다:
    SET PASSWORD FOR 'abe'@'host_name' = PASSWORD('eagle');
    GRANT 또는 CREATE USER 명령문, 또는 mysqladmin password 명령어를 사용해서 패스워드를 지정할 때에는 PASSWORD() 함수가 필요 없다. 이러한 것들은 자동으로 PASSWORD()를 사용해서 패스워드를 암호화 시킨다. Section 5.9.5, “계정 패스워드 할당하기”, 그리고 Section 13.5.1.1, “CREATE USER 신텍스”를 참조할 것.
  • localhost는 여러분의 로컬 호스트 이름과 같은 것이며, 이것은 또한 여러분이 호스트를 명확하게 지정하지 않을 경우에 클라이언트가 접속을 시도하는 디폴트 호스트가 된다.
  • 만약에 mysql -u user_name을 사용해서 데이터 베이스에 접속을 시도할 때 Access denied라는 에러가 생긴다면, 그 이유는 user 테이블에 문제가 있기 때문이다. mysql -u root mysql를 실행한 후에 아래의 SQL 명령문을 입력해서 이 테이블을 검사한다:
    SELECT * FROM user;
    이 명령문을 실행하면 시스템 호스트 이름과 MySQL 사용자 이름에 매치되는 Host 와 User 컬럼 열이 결과 값에 나오게 된다.
  • Access denied 에러는 여러분이 어떤 사용자 이름으로 로그인을 시도하고 있는지, 어떤 클라이언트 호스트에서 접속을 하고자 하는지, 그리고 패스워드를 사용하고 있는지를 알려준다. 정상적인 경우라면, 여러분은 에러 메시지에 나와 있는 호스트 이름과 사용자 이름에 정확히 매치되는 열을 user 테이블에 가지고 있어야 한다. 예를 들면, 만약에 여러분이 using password: NO가 포함된 에러 메시지를 받게 된다면, 이것은 여러분이 패스워드 없이 로그인을 시도하였다는 것을 의미한다.
  • 만약에 MySQL 서버가 구동되고 있는 서버가 아닌 다른 호스트에서 접속을 시도할 때 아래와 같은 에러가 발생한다면, 그것은 user 테이블에 클라이언트 호스트와 매치되는 Host 값 열이 존재하지 않는다는 것을 의미한다:
    Host ... is not allowed to connect to this MySQL server
    여러분은 접속을 시도할 때 클라이언트의 호스트 이름과 사용자 이름에 대한 계정을 설정해서 이 문제를 해결할 수가 있다. 만약에 접속을 시도하는 시스템의 IP 번호 또는 호스트 이름을 모른다면, user 테이블의 Host 컬럼에 '%'를 넣는다. 클라이언트 머신에서 접속을 시도한 후에는, SELECT USER() 쿼리를 사용해서 여러분이 실제로 접속을 했는지 확인한다. (그런 다음에 user 테이블 열의 '%'값을 로그에서 찾은 실제 호스트 이름으로 바꾼다. 그렇지 않으면, 서버는 모든 호스트가 접속을 할 수 있도록 허용을 하기 때문에 시스템 보안에 문제가 생기게 된다.) 리눅스에서는, 여러분이 사용하는 버전과는 다른 glibc 라이브러리 버전을 사용해서 컴파일된 MySQL 바이너리 버전을 사용할 경우에도 위와 동일한 문제가 발생하기도 한다. 이와 같은 경우에는, OS 또는 glibc를 업그레이드 하거나, 또는 MySQL 소스 버전을 다운로드해서 스스로 컴파일한 후에 사용하도록 한다.
  • 만약에 접속을 시도할 때 호스트 이름은 지정하였으나, 호스트 이름이 보이지 않고 IP 번호만 나오는 에러를 가지게 되면, 그것은 MySQL 서버가 IP 번호를 호스트 이름으로 해석할 때 에러가 발생했다는 것을 의미하는 것이다:
    shell> mysqladmin -u root -pxxxx -h some_hostname ver
    Access denied for user 'root'@'' (using password: YES)
    이것은 DNS 문제를 가리키는 것이다. 이럴 경우에느, mysqladmin flush-hosts를 실행해서 내부 DNS 호스트 이름 캐시를 리셋 시킨다. Section 7.5.6, “MySQL DNS 사용 방법”을 참조. 몇 가지 영구적인 해결 방법은 다음과 같다:
    • DNS 서버 문제를 알아내서 고친다.
    • MySQL 그랜트 테이블에 호스트 이름이 아닌 IP 번호를 지정한다.
    • 클라이언트 머신 이름 엔트리를 /etc/hosts 또는 \windows\hosts에 넣어 둔다.
    • mysqld를 --skip-name-resolve 옵션으로 구동시킨다.
    • mysqld를 --skip-host-cache 옵션과 함께 구동 시킨다.
    • 유닉스 시스템의 경우, 만약에 서버와 클라이언트를 하나의 머신에서 구동시킨다면, localhost에 접속 하도록 한다. Localhost에 대한 유닉스 접속은 TCP/IP가 아닌 유닉스 소켓 파일을 사용한다.
    • 윈도우 시스템의 경우, 만약에 서버와 클라이언트가 동일한 머신에서 구동이 되고, 서버가 네임드 파이프 접속을 지원 한다면, hostname . (period)에 접속 하도록 한다. . (period)에 대한 접속은 TCP/IP가 아닌 네임드 파이프를 사용한다.
  • 만약에 mysql -u root test가 동작은 하지만 mysql -h your_hostname -u root test로 인해 Access denied (your_hostname은 로컬 호스트의 실제 호스트 이름)가 발생한다면, 이것은 아마도 user 테이블에 정확한 호스트 이름을 가지고 있지 않기 때문일 것이다. 이것이 가지고 있는 일반적인 문제점은 바로, user 테이블 열에 있는 Host 값이 검증되지 않은 호스트 이름을 가리키고 있으나, 시스템 이름 해석 루틴은 완전히 검증된 도메인 이름을 돌려준다는 것이다 (혹은 그 반대). 예를 들면, 만약에 user 테이블에 호스트 'tcx' 엔트리가 있으나, DNS가 MySQL에게 호스트 이름은 'tcx.subnet.se'라고 알려준다면, 그 엔트리는 동작을 하지 않게 된다. Host 컬럼 값을 호스트의 IP 번호로 가지고 있는 user 테이블에 엔트리를 추가하도록 해본다. (다른 방법으로는, Host 값에 와일드 카드가 있는 user 테이블에 엔트리를 추가해 본다; 예를 들면, 'tcx.%'. 하지만, ‘%’로 끝나는 이름을 사용하는 것은 보안에 문제가 생기기 때문에 권장하지는 않는다!)
  • 만약에 mysql -u user_name test가 동작하기는 하지만 mysql -u user_name other_db_name 이 동작을 하지 않는다면, 이것은 지정한 사용자에게 other_db_name에 대한 데이터 베이스 접근 권한을 승인하지 않은 것이다.
  • 만약에 mysql -u user_name가 서버 호스트에서 실행될 때에는 제대로 동작 하지만, 리모트 클라이언트 호스트에서 실행할 때에는 mysql -h host_name -u user_name가 동작하지 않는다면, 리모트 호스트에서 지정한 사용자 이름에 대해서 서버 접근을 활성화 시키지 않은 것이다.
  • 만약에 여러분이 Access denied 에러가 발생한 이유를 모른다면, 와일드 카드를 가지고 있는 모든 Host 엔트리를 (‘%’ 또는 ‘_’를 가지고 있는 엔트리)를 user 테이블에서 삭제를 하도록 한다. 가장 흔히 발생하는 에러는, 여러분이 Host='%' 와 User='some_user’를 가지고 새로운 엔트리를 삽입하면, 동일 머신에서 접속 하기 위한 localhost지정이 가능하다고 생각하기 때문이다. 하지만, 이렇게 지정하면 에러가 발생하는 이유는, 디폴트 권한이 Host='localhost' 와 User='' 엔트리를 가지고 있기 때문이다. 엔트리는 '%' 보다 구체적인 Host 값인 'localhost'를 가지고 있기 때문에, localhost에서 접속을 할 때 새로운 엔트리가 아닌 그것을 우선적으로 사용한다. 따라서, Host='localhost' 와 User='some_user'를 사용해서 두번째 엔트리를 삽입하거나, 또는 Host='localhost' 와 User=''를 가지고 있는 엔트리를 삭제하는 것이 올바른 처리 방법이다. 엔트리를 삭제한 후에는, 그랜트 테이블을 다시 읽어 오기 위해 FLUSH PRIVILEGES 명령문을 입력하는 것을 잊지 말도록 한다.
  • 만약에 아래의 에러가 발생한다면, 그것은 db 또는 host 테이블에 문제가 있기 때문일 것이다:
    Access to database denied
    만약에 db 테이블에서 선택된 엔트리가 Host 컬럼에 빈 값을 가지고 있다면, host 테이블에 db 테이블 엔트리를 적용하는 호스트 지정 엔트리가 하나 이상 존재하는지 확인한다.
  • 만일 여러분이 MySQL 서버에 접속은 할 수 있지만, SELECT ... INTO OUTFILE 또는 LOAD DATA INFILE 명령문을 입력할 때마다 Access denied 에러 메시지가 발생한다면, user 테이블 엔트리가 FILE 권한을 사용할 수 없기 때문이다.
  • 만일 여러분이 직접 그랜트 테이블을 변경하였지만 변경된 내용이 무시된다고 판단되면, FLUSH PRIVILEGES 명령문 또는 mysqladmin flush-privileges 명령어를 실행 시켜서 서버가 권한 테이블을 다시 읽어 오도록 만들어야 한다. 그렇지 않으면, 서버가 재 구동되기까지 변경한 내용이 적용되지 않는다. UPDATE 명령어를 가지고 root 패스워드를 변경한 후에는, 권한을 플러시하기 전까지 새로운 패스워드를 지정할 필요가 없는데, 그 이유는 서버가 변경된 패스워드를 아직 모르고 있기 때문이다!
  • 만약에 여러분의 권한이 세션 도중에 변경되었다고 판단되면, 그것은 관리자가 변경을 한 것으로 생각할 수가 있다. 그랜트 테이블을 다시 읽어 오는 것은 새로운 접속에 적용되기도 하지만, Section 5.8.7, “권한 변경이 적용되는 시점”에서 설명하고 있는 것처럼 현재 존재하고 있는 접속에도 영향을 미치게 된다.
  • 만약에 Perl, PHP, Python, 또는 ODBC 프로그램에 대한 접속에 문제가 있다면, mysql -u user_name db_name 또는 mysql -u user_name -pyour_pass db_name를 사용해서 서버에 접속해 보도록 한다. 만약에 mysql 클라이언트를 사용해서 접속할 수가 있다면, 문제는 접근 권한에 있는 것이 아니라 프로그램 자체에 있는 것이다.
  • 테스트를 하기 위해서, mysqld 서버를 --skip-grant-tables 옵션과 함께 시작 해본다. 그런 다음에 MySQL의 그랜트 테이블을 변경하고 mysqlaccess 스크립트를 사용해서 여러분이 변경시킨 내용이 원하는 형태로 진행되는지를 검사한다. 변경 내용이 제대로 동작되면, mysqladmin flush-privileges를 실행해서 mysqld 서버가 새로운 그랜트 테이블을 사용해서 시작 하도록 만든다.
  • 만약에 모든 것이 실패를 할 경우에는, 디버깅 옵션을 사용해서 mysqld 서버를 구동 시켜본다 (예를 들면, --debug=d,general,query). 이렇게 하면, 접속을 시도한 호스트와 사용자에 대한 정보와 함께 입력된 각 명령어에 대한 정보도 보여 준다.
MySQL 4.1 이후의 패스워드 해싱

MySQL 사용자 계정은 mysql 데이터 베이스의 user 테이블에 목록화 되어 있다. 각 MySQL 계정에는 패스워드가 할당되는데, user 테이블의 Password 컬럼에 저장되는 패스워드는 일반적인 문장이 아닌 해시 (HASH) 값으로 저장된다. 패스워드 해시 값은 PASSWORD() 함수로 계산된다.

MySQL은 클라이언트/서버 통신의 두 단계에서 패스워드를 사용한다:


  • 클라이언트가 서버에 접속을 시도할 때, 클라이언트는 자신이 사용할 계정용 user 테이블 저장 해시 값과 매칭되는 해시 값 패스워드를 초기 인증 절차에서 제공해야 한다.
  • 클라이언트는 접속을 한 후에는, 클라이언트는 user 테이블에 있는 계정 패스워드 해시를 설정 또는 변경할 수가 있게 된다. 클라이언트는 PASSWORD() 함수 또는 GRANT 또는 SET PASSWORD 명령문을 사용해서 이 일을 수행한다.

달리 표현하면, 클라이언트가 처음으로 접속을 시도할 때 서버는 이 해시 값을 인증용으로 사용한다. 서버는 접속된 클라이언트가 PASSWORD() 함수를 실행하거나 또는 GRANT 또는 SET PASSWORD 명령문을 사용해서 명령문을 설정 또는 변경하는 경우에 해시 값을 생성한다.

패스워드 해싱 매커니즘은 MySQL 4.1에서 개선되어 보다 우수한 보안성을 제공해 주었다. 하지만, 이 새로운 매커니즘은 4.1 (그리고 그 이후 버전)의 서버와 클라이언트에서만 사용이 가능하며, 그 결과 이전 버전과의 호환성에 문제가 생기게 되었다. 4.1 또는 그 이후 버전의 클라이언트는 이전 버전의 서버에 접속을 할 수는 있으나, 4.1 이전 버전의 클라이언트가 4.1 이후의 서버에 접속하면 문제가 발생한다. 예를 들면, 5.0 서버에 접속을 시도하는 3.23 mysql 클라이언트는 아래와 같은 에러가 발생할 수 있다:



shell> mysql -h localhost -u root
Client does not support authentication protocol requested
by server; consider upgrading MySQL client

아래에서는 구형과 새로운 패스워드 매커니즘 간의 차이점에 대해서 설명을 하고 있으며, 서버를 업그레이드하는 경우에 4.1 이전 버전과의 호환성을 유지하기 위해서는 어떤 작업이 필요한지를 설명하고 있다.

Note: 여기에서는 4.1 이전 버전과 4.1 버전과의 차이점에 대해 주로 설명을 하는데, 4.1의 특성은 실제로는 4.1.1 이후 버전에 관한 것이다. MySQL 4.1.0은 4.1.1 이후 버전과는 다소 차이가 있는 매커니즘을 사용하고 있기 때문에 “odd” 릴리즈라고 간주된다.

MySQL 4.1 이전 버전의 경우, PASSWORD() 함수가 계산하는 패스워드 해시는 16 바이트이다. 그러한 해시는 다음과 같이 보인다:



mysql> SELECT PASSWORD('myboss');
+--------------------+
| PASSWORD('myboss') |
+--------------------+
| 6f8c114b58f2ce9e |
+--------------------+


user 테이블의 Password 컬럼 역시 4.1 이전에는 16 바이트를 사용했다.

MySQL 4.1 이후에는, PASSWORD() 함수가 41 바이트의 해시 값을 생성하도록 수정되었다:



mysql> SELECT PASSWORD('myboss');
+-------------------------------------------+
| PASSWORD('myboss') |
+-------------------------------------------+
| *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
+-------------------------------------------+


따라서, user 테이블에 있는 Password 컬럼 역시 41바이트의 값을 저장하도록 수정되었다:


  • 만약에 여러분이 5.0을 새롭게 설치한다면, Password 컬럼은 자동적으로 41 바이트 길이로 만들어 진다.
  • MySQL 4.1 (4.1.1 또는 4.1 시리즈의 나중 버전)에서 MySQL 5.0로 업그레이드할 때에는, 두 버전이 모두 동일한 매커니즘을 사용하고 있기 때문에 별도로 해야 할 일이 없다. 하지만, 4.1 이전 버전에서 5.0으로 업그레이드를 하고자 한다면, 우선 4.1로 업그레이드를 한 후에 5.0으로 업그레이드를 해야 한다.

확장된 Password 컬럼은 구형 및 신형 패스워드 해시 포맷 값을 저장할 수가 있다. 지정한 패스워드 해시 값은 두 가지 방법으로 구분할 수 있다:


  • 명백한 길이의 차이 (16 바이트 대 41 바이트).
  • 두 번째 차이는 새로운 패스워드 해시는 항상 ‘*’ 문자로 시작되는 반면에, 구형 해시는 그렇지 않다는 것이다.
출처 : MySQL 코리아