[rest] RESTful 인증

RESTful 인증이란 무엇이며 어떻게 작동합니까? Google에서 좋은 개요를 찾을 수 없습니다. 내 유일한 이해는 URL에서 세션 키 (반복)를 전달한다는 것입니다. 그러나 이것은 끔찍한 잘못 일 수 있습니다.



답변

RESTful 클라이언트-서버 아키텍처에서 인증을 처리하는 방법은 논쟁의 여지가 있습니다.

일반적으로 SOA over HTTP 세계에서 다음을 통해 달성 할 수 있습니다.

  • HTTPS를 통한 HTTP 기본 인증;
  • 쿠키 및 세션 관리;
  • HTTP 헤더의 토큰 (예 : OAuth 2.0 + JWT);
  • 추가 서명 매개 변수를 사용한 쿼리 인증

소프트웨어 아키텍처를 최상으로 맞추려면 이러한 기술을 조정하거나 더 잘 혼합해야합니다.

각 인증 체계에는 보안 정책 및 소프트웨어 아키텍처의 목적에 따라 고유 한 PRO 및 CON이 있습니다.

HTTPS를 통한 HTTP 기본 인증

표준 HTTPS 프로토콜을 기반으로하는이 첫 번째 솔루션은 대부분의 웹 서비스에서 사용됩니다.

GET /spec.html HTTP/1.1
Host: www.example.org
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

모든 브라우저에서 기본적으로 사용할 수 있지만 구현하기 쉽지만 브라우저에 표시되는 끔찍한 인증 창과 같이 알려진 몇 가지 단점이 있습니다. 그리고 사용자 이름과 비밀번호가 (HTTPS를 통해) 서버로 전송된다는 사실 (키보드 입력 중 클라이언트 측에만 비밀번호를 유지하고 서버에 보안 해시로 저장되도록 더 안전해야 함) .

다이제스트 인증을 사용할 수도 있지만 MiM 또는 재생 공격에 취약 하고 HTTP에만 해당 되므로 HTTPS도 필요합니다 .

쿠키를 통한 세션

솔직히 말해서 서버에서 관리되는 세션은 실제로 Stateless가 아닙니다.

쿠키 콘텐츠 내에서 모든 데이터를 유지 관리하는 것이 가능할 수 있습니다. 그리고 쿠키는 의도적으로 서버 측에서 처리됩니다 (실제로 클라이언트는이 쿠키 데이터를 해석하려고 시도하지 않습니다. 각 요청마다 서버에 다시 전달합니다). 그러나이 쿠키 데이터는 응용 프로그램 상태 데이터이므로 클라이언트는 순수한 Stateless 환경에서 서버가 아니라 관리해야합니다.

GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: theme=light; sessionToken=abc123

쿠키 기술 자체는 HTTP 연결이므로 프로토콜에 독립적 인 IMHO이어야하는 RESTful이 아닙니다. MiM 또는 Replay 공격에 취약합니다 .

토큰을 통해 부여 (OAuth2)

대안은 요청이 인증되도록 HTTP 헤더 내에 토큰을 넣는 것입니다. 이것은 무엇 의 OAuth 2.0 예를 들어, 않습니다. RFC 6749를 참조하십시오 .

 GET /resource/1 HTTP/1.1
 Host: example.com
 Authorization: Bearer mF_9.B5f-4.1JqM

간단히 말해서 쿠키와 매우 유사하며 동일한 문제가 발생합니다. 상태 비 저장, HTTP 전송 세부 정보에 의존하지 않으며 MiM 및 재생을 비롯한 많은 보안 취약점 이 HTTPS를 통해서만 사용되어야합니다. 일반적으로 JWT 는 토큰으로 사용됩니다.

쿼리 인증

쿼리 인증은 URI의 일부 추가 매개 변수를 통해 각 RESTful 요청에 서명하는 것으로 구성됩니다. 참조 이 참조 문서를 .

이 기사에서는 다음과 같이 정의되었습니다.

개인 자격 증명을 서명 토큰으로 사용하여 알파벳 순서로 소문자로 정렬 된 쿼리 매개 변수에 서명하여 모든 REST 쿼리를 인증해야합니다. 쿼리 문자열을 URL 인코딩하기 전에 서명이 이루어져야합니다.

이 기술은 Stateless 아키텍처와 더 호환 될 수 있으며 간단한 세션 관리 (DB 지속성 대신 메모리 내 세션 사용)로 구현할 수도 있습니다.

예를 들어, 다음은 위 링크의 일반적인 URI 샘플입니다.

GET /object?apiKey=Qwerty2010

다음과 같이 전송되어야합니다.

GET /object?timestamp=1261496500&apiKey=Qwerty2010&signature=abcdef0123456789

서명되는 문자열은 /object?apikey=Qwerty2010&timestamp=1261496500이고 서명은 API 키의 개인 구성 요소를 사용하여 해당 문자열의 SHA256 해시입니다.

서버 측 데이터 캐싱을 항상 사용할 수 있습니다. 예를 들어, 프레임 워크에서 URI 레벨이 아닌 SQL 레벨에서 응답을 캐시합니다. 따라서이 추가 매개 변수를 추가해도 캐시 메커니즘이 손상되지 않습니다.

JSON 및 REST를 기반으로하는 클라이언트 서버 ORM / SOA / MVC 프레임 워크의 RESTful 인증에 대한 세부 사항은 이 기사 를 참조하십시오 . HTTP / 1.1을 통한 통신뿐만 아니라 명명 된 파이프 또는 GDI 메시지 (로컬로)를 통한 통신을 허용하기 때문에 진정으로 RESTful 인증 패턴을 구현하려고 시도했지만 HTTP 고유성 (헤더 또는 쿠키 등)에 의존하지 않았습니다.

나중에 참고 : URI에 서명을 추가하는 것은 나쁜 습관으로 보일 수 있습니다 (예를 들어 http 서버 로그에 표시되기 때문에) 예를 들어 재생을 피하기 위해 적절한 TTL에 의해 완화되어야합니다. 그러나 http 로그가 손상되면 보안 문제가 더 커질 것입니다.

실제로, 다가오는 OAuth 2.0 용 MAC 토큰 인증 은 “Granted by Token”현재 체계와 관련하여 크게 개선 될 수 있습니다. 그러나 이것은 여전히 ​​진행중인 작업이며 HTTP 전송과 관련이 있습니다.

결론

REST는 실제로 HTTP 기반 일뿐 아니라 실제로 HTTP를 통해 구현되는 경우에도 결론을 내릴 가치가 있습니다. REST는 다른 통신 계층을 사용할 수 있습니다. 따라서 RESTful 인증은 Google이 응답하는 모든 HTTP 인증의 동의어가 아닙니다. HTTP 메커니즘을 전혀 사용해서는 안되지만 통신 계층에서 추상화해야합니다. 그리고 HTTP 통신을 사용하는 경우 Let ‘s Encrypt 이니셔티브 덕분에 인증 체계 외에 필요한 적절한 HTTPS를 사용하지 않을 이유가 없습니다.


답변

사람들이 열정적으로 “HTTP 인증”을 외치면서 REST를 사용하여 (M2M 웹 서비스 대신) 브라우저 기반 응용 프로그램을 만들려고했는지 의심하지 않습니다. .

브라우저에서 볼 HTML 페이지를 생성하는 RESTful 서비스에서 HTTP 인증을 사용할 때 발견 한 문제점은 다음과 같습니다.

  • 사용자는 일반적으로 브라우저에서 만든 못생긴 로그인 상자를 얻습니다. 비밀번호 검색, 도움말 상자 등을 추가 할 수 없습니다.
  • 다른 이름으로 로그 아웃하거나 로그인하면 문제가 발생합니다. 브라우저는 창을 닫을 때까지 사이트에 인증 정보를 계속 보냅니다
  • 타임 아웃이 어렵다

이러한 점을 다루는 매우 통찰력있는 기사가 여기 있지만 많은 브라우저 특정 자바 스크립트 해커, 해결 방법에 대한 해결 방법 등이 있습니다. 따라서 순방향과도 호환되지 않으므로 새 브라우저가 출시 될 때 지속적인 유지 관리가 필요합니다. 나는 깨끗하고 깨끗한 디자인을 고려하지 않으며, 여분의 일과 두통이 많이 생겨서 내 친구에게 내 REST 배지를 열정적으로 보여줄 수 있다고 생각합니다.

쿠키가 해결책이라고 생각합니다. 그러나 쿠키는 악하지 않습니까? 아닙니다. 쿠키가 자주 사용되는 방식은 악입니다. 쿠키 자체는 사용자가 탐색하는 동안 브라우저가 추적하는 HTTP 인증 정보와 마찬가지로 클라이언트 측 정보 일뿐입니다. 그리고이 클라이언트 측 정보는 HTTP 인증 정보와 마찬가지로 모든 요청마다 서버로 전송됩니다. 개념적으로, 유일한 차이점은 것입니다 내용 이 클라이언트 쪽 상태 을 서버 가 응답의 일부로 결정할 수 있다는 것 입니다.

다음 규칙만으로 세션을 RESTful 리소스로 만듭니다.

  • 세션은 사용자 ID에 대한 키 (및 시간 제한을위한 마지막 액션 타임 스탬프를) 매핑
  • 만약 세션이 존재하고 키가 유효 그 수단이다.
  • 로그인은 / sessions에 POST를 의미하고 새 키는 쿠키로 설정됩니다.
  • 로그 아웃은 / sessions / {key}를 삭제함을 의미합니다 (오버로드 된 POST를 사용하면 브라우저이며 HTML 5는 아직 갈 길이 멀다는 것을 기억하십시오)
  • 모든 요청에서 키를 쿠키로 전송하고 세션이 존재하고 유효한지 확인하여 인증을 수행합니다.

이제 HTTP 인증과의 유일한 차이점은 인증 키가 서버에 의해 생성되어 클라이언트가 입력 한 자격 증명으로 계산하는 대신 계속 전송하는 클라이언트에게 전송된다는 것입니다.

converter42는 https를 사용해야 할 때 쿠키에 보안 플래그가 설정되어 인증 정보가 비보안 연결을 통해 전송되지 않도록하는 것이 중요하다고 덧붙였습니다. 좋은 지적은 직접 보지 못했습니다.

나는 이것이 잘 작동하는 충분한 솔루션이라고 생각하지만,이 체계의 잠재적 인 취약점을 식별하기에 충분한 보안 전문가가 아니라는 것을 인정해야합니다. 로그인 프로토콜 (PHP의 $ _SESSION, Java EE의 HttpSession 등). 쿠키 헤더 내용은 수락 언어가 번역 리소스 등에 액세스하는 데 사용될 수있는 것처럼 서버 측 리소스를 주소 지정하는 데 사용됩니다. 나는 그것이 같지만 다른 사람들은 그렇지 않다고 생각합니까? 당신은 어떻게 생각하세요?


답변

이 주제에 대해서는 이미 좋은 사람들에 의해 충분히 언급되어 있습니다. 그러나 여기 내 2 센트가 있습니다.

상호 작용에는 두 가지 모드가 있습니다.

  1. 인간 대 기계 (HTM)
  2. 기계 간 (MTM)

머신은 공통 분모로, REST API로 표현되며 액터 / 클라이언트는 사람 또는 머신입니다.

이제 진정 RESTful 아키텍처에서 상태 비 저장 개념은 모든 관련 애플리케이션 상태 (클라이언트 측 상태를 의미)에 각 요청마다 제공되어야 함을 의미합니다. 관련하여 REST API가 요청을 처리하고 적절한 응답을 제공하는 데 필요한 것은 무엇이든 의미합니다.

Skrebbel이 위에서 지적한대로 “브라우저 기반”의 휴먼-투-머신 애플리케이션에서이를 고려할 때, 이는 브라우저에서 실행중인 (웹) 애플리케이션이 각 요청과 함께 해당 상태 및 관련 정보를 보내야 함을 의미합니다. 백엔드 REST API를 만듭니다.

다음 사항을 고려하십시오. REST API의 데이터 / 정보 플랫폼 노출 자산이 있습니다. 아마도 모든 데이터 큐브를 처리하는 셀프 서비스 BI 플랫폼이있을 것입니다. 그러나 (인간적인) 고객이 (1) 웹 앱, (2) 모바일 앱 및 (3) 일부 타사 애플리케이션을 통해 여기에 액세스하기를 원합니다. 결국, MTM 체인조차도 HTM으로 이어집니다. 따라서 인간 사용자는 정보 체인의 정점에 남아 있습니다.

처음 두 경우에는 사람과 사람이 상호 작용하는 경우가 있으며이 정보는 실제로 사용자가 소비합니다. 마지막 경우에는 REST API를 사용하는 머신 프로그램이 있습니다.

인증 개념은 전반적으로 적용됩니다. REST API가 균일하고 안전한 방식으로 액세스되도록이를 어떻게 설계 하시겠습니까? 내가 보는 방식에는 두 가지 방법이 있습니다.

방법 -1 :

  1. 시작할 로그인이 없습니다. 모든 요청은 로그인을 수행합니다
  2. 클라이언트는 식별 매개 변수 + 요청마다 요청 특정 매개 변수를 보냅니다.
  3. REST API는이를 가져 와서 사용자 저장소를 핑 (ping)하고 인증을 확인합니다.
  4. 인증이 설정되면 요청을 처리합니다. 그렇지 않으면 적절한 HTTP 상태 코드로 거부
  5. 카탈로그의 모든 REST API에서 모든 요청에 ​​대해 위의 단계를 반복하십시오.

방법 -2 :

  1. 클라이언트는 인증 요청으로 시작
  2. 로그인 REST API는 이러한 모든 요청을 처리합니다.
  3. 인증 매개 변수 (API 키, uid / pwd 또는 선택한 항목)를 사용하고 사용자 저장소 (LDAP, AD 또는 MySQL DB 등)에 대한 인증을 확인합니다.
  4. 확인되면 인증 토큰을 생성하여 클라이언트 / 호출자에게 전달
  5. 그런 다음 호출자는 로그 아웃 할 때까지 또는 임대가 만료 될 때까지 이후의 모든 요청과 함께이 인증 토큰 + 요청 특정 매개 변수를 다른 비즈니스 REST API로 보냅니다.

Way-2에서 REST API는 토큰을 유효한 것으로 인식하고 신뢰하는 방법이 필요합니다. 로그인 API는 인증 확인을 수행 했으므로 카탈로그의 다른 REST API가 “valet key”를 신뢰해야합니다.

물론 이것은 인증 키 / 토큰이 REST API간에 저장 및 공유되어야 함을 의미합니다. 이 신뢰할 수있는 공유 토큰 리포지토리는 로컬 / 페더레이션에 관계없이 다른 조직의 REST API가 서로를 신뢰할 수 있도록합니다.

그러나 나는 산만하다.

요점은 모든 REST API가 신뢰 범위를 만들 수 있도록 “클라이언트의 인증 된 상태에 대한”상태를 유지하고 공유해야한다는 것입니다. Way-1 인이 작업을 수행하지 않으면 들어오는 모든 / 모든 요청에 ​​대해 인증 작업을 수행해야합니다.

인증 수행은 자원 집약적 인 프로세스입니다. 들어오는 모든 요청에 ​​대해 uid / pwd 일치를 확인하기 위해 사용자 저장소에 대해 SQL 쿼리를 실행한다고 상상해보십시오. 또는 해시 일치 (AWS 스타일)를 암호화하고 수행합니다. 아키텍처 상 모든 REST API는 일반적인 백엔드 로그인 서비스를 사용하여이를 수행해야한다고 생각합니다. 그렇지 않은 경우 인증 코드를 모든 곳에서 처리해야합니다. 큰 혼란.

레이어가 많을수록 대기 시간이 길어집니다.

이제 Way-1을 타고 HTM에 적용하십시오. (인간적인) 사용자는 uid / pwd / hash 또는 모든 요청에 ​​대해 무엇을 보내야합니까? 아니오, 매번 인증 / 로그인 페이지를 던져서 귀찮게하지 않는 한. 고객이 있으면 행운을 빕니다. 따라서, 로그인 정보는 클라이언트 측, 브라우저, 시작 부분에 저장하고 요청이있을 때마다 전송해야합니다. (인간) 사용자의 경우, 이미 로그인했으며 “세션”을 사용할 수 있습니다. 그러나 실제로 그녀는 모든 요청에 ​​대해 인증됩니다.

Way-2와 동일합니다. 귀하의 (인간적인) 사용자는 절대 눈치 채지 못할 것입니다. 그래서 아무런 해가 없었습니다.

Way-1을 MTM에 적용하면 어떻게됩니까? 이 경우 컴퓨터이기 때문에 모든 요청에 ​​인증 정보를 제출하도록 요청하여이 사람을 쫓아 낼 수 있습니다. 아무도 신경 쓰지 않는다! MTM에서 Way-2를 수행해도 특별한 반응이 나타나지 않습니다. 그 빌어 먹을 기계. 신경 쓰지 않아도됩니다!

실제로 질문은 당신의 필요에 맞는 것입니다. 무국적자는 지불 할 대가가 있습니다. 가격을 지불하고 계속 진행하십시오. 당신이 순수 주의자가되고 싶다면, 그것의 가격도 지불하고 계속하십시오.

결국 철학은 중요하지 않습니다. 실제로 중요한 것은 정보 발견, 프리젠 테이션 및 소비 경험입니다. 사람들이 당신의 API를 좋아한다면, 당신은 일을 한 것입니다.


답변

진정으로 완전한 RESTful 인증 솔루션은 다음과 같습니다.

  1. 인증 서버에서 공개 / 개인 키 쌍을 만듭니다.
  2. 공개 키를 모든 서버에 분배하십시오.
  3. 클라이언트가 인증 할 때 :

    3.1. 다음을 포함하는 토큰을 발행하십시오.

    • 만료 시간
    • 사용자 이름 (선택 사항)
    • 사용자 IP (선택 사항)
    • 비밀번호 해시 (선택 사항)

    3.2. 개인 키로 토큰을 암호화하십시오.

    3.3. 암호화 된 토큰을 사용자에게 다시 보냅니다.

  4. 사용자가 API에 액세스하면 인증 토큰도 전달해야합니다.

  5. 서버는 인증 서버의 공개 키를 사용하여 토큰을 해독하여 토큰이 유효한지 확인할 수 있습니다.

이것은 상태 비 저장 / RESTful 인증입니다.

비밀번호 해시가 포함 된 경우 사용자는 인증 토큰과 함께 암호화되지 않은 비밀번호도 전송합니다. 서버는 해시를 비교하여 비밀번호가 인증 토큰을 작성하는 데 사용 된 비밀번호와 일치하는지 확인할 수 있습니다. HTTPS와 같은 것을 사용하는 안전한 연결이 필요합니다. 클라이언트 측의 Javascript는 사용자 암호를 가져와 메모리 또는 쿠키에 저장하고 서버의 공개 키로 암호화 할 수 있습니다 .


답변

솔직히 말해서 나는 여기에 큰 대답을 보았지만 나를 귀찮게하는 것은 누군가가 Stateless 개념을 독단적이되는 극단으로 가져갈 때입니다. 순수한 OO 만 받아들이고 싶었던 무언가가 객체가 아니라면 잘못하고있는 오래된 스몰 토크 팬을 생각 나게합니다. 휴식 좀 줘

RESTful 접근 방식은 인생을 더 편하게하고 세션의 오버 헤드와 비용을 줄이며 현명한 일이므로 따르십시오. 그러나 분별 징계 (모든 징계 / 지침)를 따르는 순간 더 이상 의도했던 혜택을 제공하지 않으면 잘못하고 있습니다. 오늘날 최고의 언어 중 일부에는 기능적 프로그래밍과 객체 지향이 있습니다.

문제를 해결하는 가장 쉬운 방법은 인증 키를 쿠키에 저장하고이를 HTTP 헤더로 보내는 것입니다. 남용하지 마십시오. 세션이 무겁고 커지면 세션이 나쁘다는 것을 기억하십시오. 모든 세션으로 구성된 키가 키를 포함하는 짧은 문자열이면 큰 문제는 무엇입니까?

나는 의견에 대한 수정을 받아 들일 수 있지만 서버에 큰 해시 사전을 유지하는 것을 피하기 위해 우리 삶을 비참하게 만드는 요점을 알지 못합니다.


답변

무엇보다도 RESTful 웹 서비스는 STATELESS (즉, SESSIONLESS)입니다.). 따라서 RESTful 서비스에는 세션 또는 쿠키 개념이 없으며 포함되어서는 안됩니다. RESTful 서비스에서 인증 또는 권한 부여를 수행하는 방법은 RFC 2616 HTTP 스펙에 정의 된 HTTP 권한 부여 헤더를 사용하는 것입니다. 모든 단일 요청에는 HTTP 권한 부여 헤더가 포함되어야하며 요청은 HTTP (SSL) 연결을 통해 전송되어야합니다. 이는 HTTP RESTful 웹 서비스에서 인증을 수행하고 요청의 권한을 확인하는 올바른 방법입니다. Cisco Systems에서 Cisco PRIME Performance Manager 애플리케이션을위한 RESTful 웹 서비스를 구현했습니다. 그리고 그 웹 서비스의 일부로 인증 / 권한도 구현했습니다.


답변

일반적으로 REST의 모든 제약 조건 내에서 수행되는 세션없는 인증을 참조하는 데 사용되므로 “세션 키”에 관한 것이 아닙니다. 각 요청은 자체 설명이며 서버 측 응용 프로그램 상태없이 요청을 자체적으로 승인하기에 충분한 정보를 전달합니다.

이에 접근하는 가장 쉬운 방법은 RFC 2617 에서 HTTP의 내장 인증 메커니즘으로 시작하는 것 입니다.