Microsoft 社는 2022년 6월 15일 Internet Explorer 11의 지원을 종료했습니다.

Apache Tomcat Authentication and curl

제목

Apache Tomcat Authentication and curl

1. 개요

Apache Tomcat의 가장 대표적인 인증 방식은 다음과 같다.

  • BASIC
  • DIGEST
  • FORM

2. 갈 길이 바쁜 사람들을 위해서

2.1. BASIC, DIGEST 인증 통과

curl -s -k --anyauth --user ${USERNAME}:${PASSWORD} --http1.1 -G ${URL}
  • -s : 조용히
  • -k : insecure, HTTPS 연결에서 서버 인증서가 Let's Encrypt 이고, 클라이언트가 오래된 기기인 경우
  • --anyauth : --basic 혹은 --digest 로 지정할 수도 있다.
  • --user ${USERNAME}:${PASSWORD} : 아이디와 패스워드
  • --http1.1 : HTTP 1.1
  • -G : GET 으로 (POST 요청은 -X POST 이다)

2.2. FORM 인증 통과

FORM 인증을 통과하는 방법을 요약하면 로그인 정보를 서버로 보내고 나서 서버에서 받은 cooke 를 이후의 요청마다 붙여 보내면 된다.

#!/bin/bash
IFS=$'\r\n'
USERNAME=
PASSWORD=
PROTECTED_URL=
J_SECURITY_CHECK=$( curl -s -k --http1.1 -G ${PROTECTED_URL} | grep -o "j_security_check.*\" ")
J_SECURITY_CHECK_LENGTH=$( expr length $J_SECURITY_CHECK - 2 )
J_SECURITY_CHECK=${J_SECURITY_CHECK:0:$J_SECURITY_CHECK_LENGTH}
LOGIN_ACTION_URL="${PROTECTED_URL%/*}/${J_SECURITY_CHECK}"
LOGIN_DATA="j_username=${USERNAME}&j_password=${PASSWORD}"
HTTP_RESPONSE=$( curl -s -k --data "${LOGIN_DATA}" -X POST --http1.1 -i -L ${LOGIN_ACTION_URL} )
cookie=""
index=0
for line in $( echo "$HTTP_RESPONSE" | grep "^Set-Cookie" ); do
index=`expr $index + 1`
if (( $index > 1 )); then
cookie="$cookie&${line:12}"
else
cookie="${line:12}"
fi
done
echo $cookie
  • USERNAME : 로그인 ID
  • PASSWORD : 패스워드
  • PROTECTED_URL : 로그인이 필요한 URL (http:// 혹은 https:// 로 시작)

다음부터 curl 명령행 옵션에 --cookie "$cookie" 붙이면 된다.

3. FORM Authentication

3.1. 개요

FORM Authentication 은 Apache Tomcat 이 관리한다는 정도만 다르고, 프로그래머들이 구현하는 일반적인 로그인 프로그램과 유사하다.

몇 가지 차이점은 존재하는데, 첫 번째는 Apache Tomcat 의 access_log에 REMOTE_USER 항목이 출력된다.

그 앞에 세운 Apache HTTPD 서버의 access_log 에는 (Tomcat 과 HTTPD 서버가 Session 정보를 공유하지 않는 한) REMOTE_USER 항목이 출력될 수 없다.

두 번째 차이는 GET 요청의 경우, (로그인 페이지로 이동시키지 않고) 바로 로그인 창이 표시되고, 인증에 성공하면, 원래 접근하려고 했던 웹페이지가 (redirect 되어서) 표시된다.

Servlet Filter 를 이용하면 (access_log는 안되겠지만) FORM Authentication 을 비슷하게 흉내낼 수 있다.

웹브라우저에서 FORM Authentication 통과하는 순서는 다음과 같다.

  1. FORM Authentication 필요한 웹페이지에 접속한다.
  2. 로그인 페이지가 표시된다(redirect 되지 않는다).
  3. 아이디와 패스워드를 입력하여 로그인한다.
  4. (로그인에 성공하면) 1항의 웹페이지가 표시되는데(302 Moved Temporarily 상태를 반환하고, Location 헤더를 따라 1항의 웹페이지를 표시한다),
  5. 이때 서버에서 Session ID를 cookie 에 담아서 보내고,
  6. 웹브라우저는 다음 요청부터 Request Header 에 cookie 를 붙인다.

3.2. Apache Tomcat FORM Authentication 로그인 페이지

Apache Tomcat FORM Authentication 로그인 페이지의 핵심 항목은 다음과 같다.

  • action : j_security_check;jsessionid= (소스코드는 j_security_check 까지이고, ;jsessionid= 는 자동으로 따라 붙는다)
  • method : POST
  • 아이디 : j_username
  • 패스워드 : j_password

action 은 요청한 URL 과 같은 디렉토리의 j_security_check 이다.

3.3. FORM Authentication이 필요한 웹페이지(${PROTECTED_URL})에 접속해서 action 을 가져온다.

J_SECURITY_CHECK=$( curl -s -k --http1.1 -G ${PROTECTED_URL} | grep -o "j_security_check.*\" ")
J_SECURITY_CHECK_LENGTH=$( expr length $J_SECURITY_CHECK - 2 )
J_SECURITY_CHECK=${J_SECURITY_CHECK:0:$J_SECURITY_CHECK_LENGTH}
LOGIN_ACTION_URL="${PROTECTED_URL%/*}/${J_SECURITY_CHECK}"
  • grep -o : 패턴이 일치하는 부분만 출력한다.
  • j_security_check 부터 " 까지 가져와서 마지막 " 는 잘라낸다.
  • PROTECTED_URL 에서 디렉토리 부분만 가져와서, j_security_check 에서 마지막 " 를 잘라낸 문자열을 합친다.

만약 PROTECTED_URL 이 https://graha.kr/protected/list.html 이라면, LOGIN_ACTION_URL 은 https://graha.kr/protected/j_security_check 혹은 j_security_check 뒤에 Session ID 가 붙은 모양이 된다.

어떤 이유로든 curl 명령이 실패하면, $J_SECURITY_CHECK 가 공백이 되고, expr 내지 length 관련한 에러가 발생한다.

3.4. 로그인 정보(아이디와 패스워드)를 서버로 보낸다.

LOGIN_DATA="j_username=${USERNAME}&j_password=${PASSWORD}"
HTTP_RESPONSE=$( curl -s -k --data "${LOGIN_DATA}" -X POST --http1.1 -i -L ${LOGIN_ACTION_URL} )
  • -s : 조용히
  • -k : insecure, HTTPS 연결에서 서버 인증서가 Let's Encrypt 이고, 클라이언트가 오래된 기기인 경우
  • LOGIN_DATA : 아이디와 패스워드
  • --data "${LOGIN_DATA} : 아이디와 패스워드
  • -X POST : POST 방식으로 요청
  • --http1.1 : HTTP 1.1 로 요청
  • -i : Response Header 도 출력
  • -L : Redirect 따라가기

302 Moved Temporarily 상태를 반환하지만, -L 옵션에 따라 Location 헤더의 URL(PROTECTED_URL) 로 이동하므로, FORM Authentication 필요했던 웹페이지가 출력된다.

POST 요청은 위와 같은 방식으로는 안되고, 먼저 GET 요청으로 로그인을 한 후에, cookie 붙여 요청해야 한다.

3.5. 다음 요청에서 보낼 cookie 를 가져온다.

Response Header 에서 Set-Cookie : 로 시작하는 것들을 가져와야 한다.

Apache Tomcat 은 JSESSIONID, JSESSIONIDSSO(SSO 설정을 한 경우) 이다.

cookie=""
index=0
for line in $( echo "$HTTP_RESPONSE" | grep "^Set-Cookie" ); do
index=`expr $index + 1`
if (( $index > 1 )); then
cookie="$cookie&${line:12}"
else
cookie="${line:12}"
fi
done
echo $cookie

어떤 이유로든 curl 명령이 실패하면, $HTTP_RESPONSE 가 공백이 되고, $cookie 값이 출력되지 않는다.

3.6. POST 요청

POST 요청의 일반적인 형태는 다음과 같다.

curl -s -k \
--data-urlencode "title=${TITLE}" \
--data-urlencode "contents=${CONTENTS}" \
--http1.1 \
--cookie "$cookie" \
-X POST \
${POST_URL}

4. 결어

예외처리는 생략했다.

프로그래머들이 HTTP Session 을 이용해서 구현하는 일반적인 로그인 프로그램도 FORM Authentication 과 유사한 방식으로 통과할 수 있다.

제목

첨부파일