나는 REST에 대해 읽고 있었고 그것에 대한 많은 질문과 다른 많은 사이트와 블로그에 대한 질문이 있습니다. 이 특정 질문을 본 적이 없지만 … 어떤 이유로이 개념에 대해 마음을 감쌀 수는 없습니다 …
RESTful API를 구축하고 있고 보안을 유지하고 싶다면 내가 본 방법 중 하나는 보안 토큰을 사용하는 것입니다. 다른 API를 사용했을 때 토큰과 공유 비밀이있었습니다. 내가 이해하지 못하는 것은 나머지 서비스 작업에 대한 요청이 자바 스크립트 (XHR / Ajax)를 통해 이루어지고 있다는 것입니다. 누군가가 FireBug (또는 브라우저에서 “소스보기”)와 같은 간단한 것으로이를 스니핑하는 것을 방지하는 것입니다. API 키를 복사 한 다음 키와 시크릿을 사용하여 그 사람을 가장하는 것입니까?
답변
api 비밀은 명시 적으로 전달되지 않고 비밀은 현재 요청 의 서명 을 생성하는 데 사용됩니다 . 서버 측에서 서버는 동일한 프로세스에 따라 서명을 생성합니다. 두 서명이 일치하면 요청이 성공적으로 인증됩니다. 서명 은 비밀이 아닌 요청을 통해 전달됩니다.
답변
파트너가 등록한 도메인에서만 사용할 수있는 API를 공개하고 있습니다. 콘텐츠는 부분적으로 공개되지만 (하지만 우리가 알고있는 도메인에만 표시되는 것이 바람직 함) 대부분 사용자에게 비공개입니다. 그래서:
-
결정 어떤 표시됩니다, 우리의 사용자는 우리와 함께 로그인해야하지만,이 별도로 처리됩니다.
-
어디 를 결정하려면데이터가 표시 공개 API 키를 사용하여 우리가 알고있는 도메인에 대한 액세스를 제한하고 무엇보다도 개인 사용자 데이터가 CSRF에 취약하지 않도록합니다 .
이 API 키는 실제로 누구나 볼 수 있으며 다른 방법으로 파트너를 인증하지 않습니다. 하지 않으며 REFERER가 필요하지 않습니다 . 그래도 안전합니다.
-
때 우리의
get-csrf-token.js?apiKey=abc123
IS 요청 :-
열쇠를 찾아
abc123
데이터베이스 를 찾고 해당 키에 대한 유효한 도메인 목록을 가져옵니다. -
CSRF 유효성 검사 쿠키를 찾습니다. 존재하지 않는 경우 보안 임의 값을 생성하여 입력하십시오. 하고 HTTP 전용 세션 쿠키 . 쿠키가 존재하는 경우 기존 임의 값을 가져옵니다.
-
API 키에서 CSRF 토큰을 만들고 쿠키에서 임의의 값을 만듭니다. 서명합니다 . (서버에 토큰 목록을 유지하는 대신 값에 서명합니다. 서명 된 토큰에서 두 값을 모두 읽을 수 있습니다. 괜찮습니다.)
-
응답이 캐시되지 않도록 설정하고 쿠키를 추가하고 다음과 같은 스크립트를 반환합니다.
var apiConfig = apiConfig || {}; if(document.domain === 'expected-domain.com' || document.domain === 'www.expected-domain.com') { apiConfig.csrfToken = 'API key, random value, signature'; // Invoke a callback if the partner wants us to if(typeof apiConfig.fnInit !== 'undefined') { apiConfig.fnInit(); } } else { alert('This site is not authorised for this API key.'); }
노트:
-
위의 내용은 서버 측 스크립트가 요청을 위조하는 것을 방지하지 않지만 다음과 같은 경우 에만 도메인이 일치 하는지 확인합니다. 브라우저에서 요청한 합니다.
-
자바 스크립트에 대한 동일 출처 정책은 브라우저가로드 한 후 자바 스크립트 소스를 검사 XHR (아약스)를 사용할 수 없도록합니다. 대신 일반 브라우저는
<script src="https://our-api.com/get-csrf-token.js?apiKey=abc123">
(또는 동적 인 동급)을 사용해서 만로드 할 수 있으며 그런 다음 코드를 실행합니다. 물론 서버가 Cross-Origin 리소스 공유를 지원 해서는 안됩니다. 생성 된 JavaScript에 대해 또는 JSONP를 . -
브라우저 스크립트는
document.domain
위 스크립트를로드하기 전에 의 값을 변경할 수 있습니다 . 그러나 동일한 출처 정책은 just , to 또는 일부 브라우저에서 다시 쓰기와 같은 접두사 를 제거 하여 도메인을 단축하는 것만 허용 합니다.subdomain.example.com
example.com
myblog.wordpress.com
wordpress.com
bbc.co.uk
co.uk
. -
서버 측 스크립트를 사용하여 JavaScript 파일을 가져 오면 서버도 쿠키를 가져옵니다. 그러나 제 3 자 서버는 사용자의 브라우저가 해당 쿠키를 당사 도메인에 연결하도록 할 수 없습니다. 따라서 서버 측 스크립트를 사용하여 가져온 CSRF 토큰 및 유효성 검사 쿠키는 브라우저가 아닌 후속 서버 측 호출에서만 사용할 수 있습니다. 그러나 이러한 서버 측 호출에는 사용자 쿠키가 포함되지 않으므로 공개 데이터 만 가져올 수 있습니다. 이것은 서버 측 스크립트가 파트너의 웹 사이트에서 직접 스크랩 할 수있는 것과 동일한 데이터입니다.
-
-
사용자가 로그인 할 때 원하는 방식으로 사용자 쿠키를 설정하십시오. (사용자는 JavaScript를 요청하기 전에 이미 로그인했을 수 있습니다.)
-
서버에 대한 모든 후속 API 요청 (GET 및 JSONP 요청 포함)에는 CSRF 토큰, CSRF 유효성 검사 쿠키 및 사용자 쿠키 (로그온 한 경우)가 포함되어야합니다. 이제 서버는 요청을 신뢰할 수 있는지 결정할 수 있습니다.
-
유효한 CSRF 토큰이 있으면 브라우저에서로드 한 경우 JavaScript가 예상 도메인에서 로드 되었는지 확인 합니다.
-
유효성 검사 쿠키가 없는 CSRF 토큰의 존재 는 위조임을 나타냅니다.
-
CSRF 토큰과 CSRF 유효성 검사 쿠키가 모두 존재한다고해서 어떤 것도 보장되지 않습니다. 위조 된 서버 측 요청이거나 브라우저의 유효한 요청 일 수 있습니다. (지원되지 않는 도메인에서 만든 브라우저의 요청 일 수 없습니다.)
-
사용자 쿠키의 존재는 사용자가 로그온되었는지 확인하지만 사용자가 주어진 파트너의 구성원인지, 사용자가 올바른 웹 사이트를보고 있는지 확인하지 않습니다.
-
CSRF 유효성 검사 쿠키가 없는 사용자 쿠키의 존재 는 위조임을 나타냅니다.
-
사용자 쿠키가 있으면 브라우저를 통해 현재 요청이 이루어집니다. (사용자가 알 수없는 웹 사이트에 자신의 자격 증명을 입력하지 않는다고 가정하고 사용자가 자신의 자격 증명을 사용하여 서버 측 요청을 수행하는 것을 신경 쓰지 않는다고 가정합니다.) CSRF 유효성 검사 쿠키 도 있는 경우 해당 CSRF 유효성 검사 쿠키는 또한 브라우저를 사용하여 받았습니다. 다음으로 에도 유효한 서명 토큰 CSRF를 가지고, 그리고CSRF 유효성 검사 쿠키의 임의 번호가 해당 CSRF 토큰의 임의 번호와 일치하면 해당 토큰에 대한 JavaScript도 CSRF 쿠키가 설정된 이전 요청 중에 수신되어 브라우저를 사용합니다. 이것은 또한 토큰이 설정되기 전에 위의 JavaScript 코드가 실행되었으며 그 당시 도메인이 주어진 API 키에 대해 유효했음을 의미합니다.
따라서 서버는 이제 서명 된 토큰의 API 키를 안전하게 사용할 수 있습니다.
-
서버가 요청을 신뢰하지 않는 경우 403 Forbidden이 반환됩니다. 위젯은 사용자에게 경고를 표시하여 이에 대응할 수 있습니다.
-
CSRF 유효성 검사 쿠키는 서명 된 CSRF 토큰과 비교하기 때문에 서명 할 필요가 없습니다. 쿠키에 서명하지 않으면 각 HTTP 요청이 더 짧아지고 서버 유효성 검사가 조금 더 빨라집니다.
생성 된 CSRF 토큰은 무기한 유효하지만 유효성 검사 쿠키와 결합해서 만 유효하므로 브라우저가 닫힐 때까지 효과적입니다.
토큰 서명의 수명을 제한 할 수 있습니다. OWASP 권장 사항 을 충족하기 위해 사용자가 로그 아웃 할 때 CSRF 유효성 검사 쿠키를 삭제할 수 있습니다. 그리고 여러 파트너간에 사용자 별 난수를 공유하지 않으려면 쿠키 이름에 API 키를 추가 할 수 있습니다. 그러나 새로운 토큰이 요청되면 CSRF 유효성 검사 쿠키를 쉽게 새로 고칠 수 없습니다. 사용자가 여러 창에서 동일한 사이트를 탐색하고 단일 쿠키를 공유 할 수 있기 때문입니다 (새로 고침 할 때 모든 창에서 업데이트되고 그 후에 다른 창의 JavaScript 토큰은 더 이상 해당 단일 쿠키와 일치하지 않습니다.)
OAuth를 사용하는 사람들 은 JavaScript 아이디어를 얻은 OAuth 및 클라이언트 측 위젯을 참조하십시오 . 를 들어 서버 측 우리가 도메인을 제한하기 위해 자바 스크립트 코드에 의존 할 수있는 API의 사용, 우리는 비밀 키 대신의 공개 API 키를 사용하고 있습니다.
답변
이 질문에는 허용되는 답변이 있지만 명확히하기 위해 공유 비밀 인증은 다음과 같이 작동합니다.
- 클라이언트는 공개 키를 가지고 있으며 누구와도 공유 할 수 있으며 중요하지 않으므로 자바 스크립트에 삽입 할 수 있습니다. 서버에서 사용자를 식별하는 데 사용됩니다.
- 서버에는 비밀 키가 있으며이 비밀은 보호되어야합니다. 따라서 공유 키 인증을 사용하려면 비밀 키를 보호 할 수 있어야합니다. 따라서 비밀을 보호하기 위해 서버 중개자가 필요하기 때문에 다른 서비스에 직접 연결하는 공용 자바 스크립트 클라이언트는 불가능합니다.
- 서버는 비밀 키 (비밀 키는 솔트와 유사 함)를 포함하는 일부 알고리즘을 사용하여 요청에 서명하고 바람직하게는 타임 스탬프가 요청을 서비스에 보냅니다. 타임 스탬프는 “재생”공격을 방지하는 것입니다. 요청의 서명은 약 n 초 동안 만 유효합니다 . 서명에 포함 된 타임 스탬프 값을 포함해야하는 타임 스탬프 헤더를 가져 와서 서버에서 확인할 수 있습니다. 해당 타임 스탬프가 만료되면 요청이 실패합니다.
- 이 서비스는 서명뿐만 아니라 일반 텍스트로 서명 된 모든 필드가 포함 된 요청을받습니다.
- 그런 다음 서비스는 공유 비밀 키를 사용하여 동일한 방식으로 요청에 서명하고 서명을 비교합니다.
답변
API 키가 아닌 세션 키를 의미한다고 생각합니다. 이 문제는 http 프로토콜에서 상속되며 세션 하이재킹으로 알려져 있습니다. 있습니다. 일반적인 “해결 방법”은 모든 웹 사이트에서와 마찬가지로 https로 변경하는 것입니다.
REST 서비스를 안전하게 실행하려면 https 및 클라이언트 인증을 활성화해야합니다. 그러나 결국 이것은 REST 아이디어를 넘어서는 것입니다. REST는 보안에 대해 이야기하지 않습니다.
답변
서버 측에서 원하는 것은 로그인 또는 가입시 클라이언트로 다시 전송되는 만료 세션 ID를 생성하는 것입니다. 그런 다음 클라이언트는 해당 세션 ID를 공유 비밀로 사용하여 후속 요청에 서명 할 수 있습니다.
세션 ID는 한 번만 전달되며 SSL을 통해 전달되어야합니다.
여기에서 예보기
세션 하이재킹을 방지하려면 요청에 서명 할 때 임시 값과 타임 스탬프를 사용하십시오.
답변
원래의 맥락에서 질문에 답하려고 노력할 것입니다. 그래서 질문은 “비밀 (API) 키는 JavaScript에 넣어도 안전합니까?”입니다.
제 생각에는 시스템 간의 인증 목적을 무너 뜨리기 때문에 매우 안전하지 않습니다. 키가 사용자에게 노출되므로 사용자는 권한이없는 정보를 검색 할 수 있습니다. 일반적인 나머지 통신에서 인증은 API 키만을 기반으로하기 때문입니다.
제 생각에 해결책은 JavaScript 호출이 본질적으로 나머지 호출을 담당하는 내부 서버 구성 요소에 요청을 전달한다는 것입니다. 내부 서버 구성 요소는 Servlet이 권한 기반 파일 시스템과 같은 보안 소스에서 API 키를 읽고 HTTP 헤더에 삽입하고 외부 나머지 호출을 수행한다고 가정합니다.
이게 도움이 되길 바란다.
답변
