HttpOnly 쿠키 기반 인증 및 세션 관리를 지원하는 단일 페이지 응용 프로그램
지금까지 며칠 동안 나는 내 단일 페이지 응용프로그램을 위한 안전한 인증 및 세션 관리 메커니즘을 찾고 있었다.SPA와 인증에 대한 수많은 튜토리얼과 블로그 게시물로 미루어 볼 때, JWT를 localStorage나 일반 쿠키에 저장하는 것이 가장 일반적인 방법인 것 같지만, 세션에 JWT를 사용하는 것은 좋은 생각이 아니기 때문에 이 앱의 선택사항은 아니다.
요구 사항들
- 로그인은 재복구가 가능해야 한다.예를 들어 사용자 계정에서 의심스러운 활동이 감지되면 즉시 해당 사용자의 액세스를 취소하고 새로운 로그인을 요구할 수 있어야 한다.마찬가지로, 비밀번호 재설정과 같은 것들은 기존의 모든 로그인을 취소해야 한다.
- 인증은 Ajax를 통해 이루어져야 한다.브라우저 리디렉션("하드" 리디렉션)은 이후에 수행되지 않아야 한다.모든 내비게이션은 SPA 내부에서 이루어져야 한다.
- 모든 것이 교차 도메인에서 작동해야 한다.SPA는 www.domain1.com에, 서버는 www.domain2.com에 있을 것이다.
- JavaScript는 세션 ID와 같이 서버가 전송하는 중요한 데이터에 액세스하지 않아야 한다.이는 악성 스크립트가 일반 쿠키, localStorage 또는 sessionStorage에서 토큰 또는 세션 ID를 도용할 수 있는 XSS 공격을 방지하기 위한 것이다.
이상적인 메커니즘은 다음과 같은 쿠키 기반 인증인 것 같다.HttpOnly
세션 ID를 포함하는 쿠키.이 흐름은 다음과 같이 작동할 것이다.
- 사용자는 로그인 페이지에 도착하여 사용자 이름과 비밀번호를 제출한다.
- 를 한다.
HttpOnly
반응 쿠키 - SPA는 서버에 대한 후속 XHR 요청에 이 쿠키를 포함한다.이는 다음 기능을 사용하여 가능한 것으로 보인다.
withCredentials
옵션의 - 보호된 엔드포인트에 대한 요청이 있을 때 서버는 쿠키를 찾는다.검색된 경우 세션 ID를 데이터베이스 테이블과 비교하여 세션이 여전히 유효한지 확인하십시오.
- 사용자가 로그아웃하면 세션이 데이터베이스에서 삭제된다.다음에 사용자가 사이트에 도착할 때 SPA는 (세션 만료 이후) 401/403 응답을 받은 후 사용자를 로그인 화면으로 이동시킨다.
왜냐하면 쿠키에는HttpOnly
플래그, 자바스크립트는 내용을 읽을 수 없기 때문에 HTTPS를 통해 전송되는 한 공격으로부터 안전할 것이다.
과제들
여기 내가 마주친 구체적인 문제가 있다.내 서버는 CORS 요청을 처리하도록 구성되었다.사용자를 인증한 후 다음 응답으로 쿠키를 올바르게 전송한다.
HTTP/1.1 200 OK
server: Cowboy
date: Wed, 15 Mar 2017 22:35:46 GMT
content-length: 59
set-cookie: _myapp_key=SFMyNTYBbQAAABBn; path=/; HttpOnly
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
x-request-id: qi2q2rtt7mpi9u9c703tp7idmfg4qs6o
access-control-allow-origin: http://localhost:8080
access-control-expose-headers:
access-control-allow-credentials: true
vary: Origin
그러나 브라우저는 쿠키를 저장하지 않는다(크롬의 로컬 쿠키를 확인할 때 쿠키는 존재하지 않는다).따라서 다음 코드가 실행될 경우:
context.axios.post(LOGIN_URL, creds).then(response => {
context.$router.push("/api/account")
}
계정 페이지가 생성됨:
created() {
this.axios.get(SERVER_URL + "/api/account/", {withCredentials: true}).then(response => {
//do stuff
}
}
이 호출에는 머리글에 쿠키가 없다.따라서 서버는 이를 거부한다.
GET /api/account/ HTTP/1.1
Host: localhost:4000
Connection: keep-alive
Accept: application/json
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Referer: http://localhost:8080/
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: en-US,en;q=0.8,tr;q=0.6
로그인 응답에 쿠키를 수신한 후 브라우저가 쿠키를 저장하도록 하기 위해 특별한 작업을 수행해야 하는가?내가 읽은 여러 정보원은 사용자가 리디렉션될 때만 브라우저가 응답 쿠키를 저장한다고 말해왔지만, SPA이기 때문에 나는 어떤 "하드" 리디렉션도 원하지 않는다.
해당 SPA는 Vue.js로 표기되어 있지만, 모든 SPA에 적용되는 것 같아.나는 사람들이 이 시나리오를 어떻게 다루는지 궁금하다.
이 주제에 대해 읽은 기타 내용:
- 인증 및 세션 관리를 위한 SPA 모범 사례
- Credentials와 함께 XmlHTTPRequest를 통해 HTTPOnly 쿠키가 제출되었는가?=진짜?
- 세션에 JWT 사용 중지, 2부: 솔루션이 작동하지 않는 이유
Vue.js 2에서 자격 증명 = true로 작업했어.클라이언트 사이트의 자격 증명 설정 사례의 절반만.서버에서도 응답 헤더를 설정해야 함:
header("Access-Control-Allow-Origin: http://localhost:8080");
header("Access-Control-Allow-Credentials: true");
다음과 같이 Access-Control-Allow-Origin에 와일드카드를 사용할 수 없음:
header("Access-Control-Allow-Origin: *");
인증 정보: true 헤더를 지정할 때는 orgin을 지정해야 한다.
보시다시피 PHP 코드인데 노드에 맞게 모델링할 수 있다.JS 또는 사용 중인 서버측 스크립팅 언어
VueJS에서 자격 증명 = true를 main.js:
Vue.http.options.credentials = true
구성 요소에서 ajax를 사용하여 성공적으로 로그인함:
<template>
<div id="userprofile">
<h2>User profile</h2>
{{init()}}
</div>
</template>
<script>
export default {
name: 'UserProfile',
methods: {
init: function() {
// loggin in
console.log('Attempting to login');
this.$http.get('https://localhost/api/login.php')
.then(resource => {
// logging response - Notice I don't send any user or password for testing purposes
});
// check the user profile
console.log('Getting user profile');
this.$http.get('https://localhost/api/userprofile.php')
.then(resource => {
console.log(resource.data);
})
}
}
}
</script>
서버 쪽에서는 간단하다: 로그인.php는 어떤 유효성 검사도 하지 않고 쿠키 세트에서 수행한다(참고: 이것은 테스트 목적으로만 수행됨).유효성 검사 없이 프로덕션에서 이 코드를 사용하는 것이 권장되지 않음)
<?php
header("Access-Control-Allow-Origin: http://localhost:8080");
header("Access-Control-Allow-Credentials: true");
$cookie = setcookie('user', 'student', time()+3600, '/', 'localhost', false , true);
if($cookie){
echo "Logged in";
}else{
echo "Can't set a cookie";
}
마지막으로 사용자 프로필.php는 쿠키 = 사용자가 설정되었는지 확인만 한다.
<?php
header("Access-Control-Allow-Origin: http://localhost:8080");
header("Access-Control-Allow-Credentials: true");
if(isset($_COOKIE['user'])){
echo "Congratulations the user is ". $_COOKIE['user'];
}else{
echo "Not allowed to access";
}
로그인 성공
자격 증명을 사용하여 쿠키 설정 및 전송을 제어할 수 있으므로 반환된 쿠키가 브라우저에 저장되도록 로그인할 때 쿠키를 켜십시오.
'Programing' 카테고리의 다른 글
Vue: 사용자 지정 확인란 구성 요소에서 v-model과의 바인딩이 작동하지 않음 (0) | 2022.04.19 |
---|---|
Vuejs가 어레이에서 데이터를 가져올 수 없음 (0) | 2022.04.19 |
요소-UI 열 필터에서 기본 필터 값을 설정하는 방법 (0) | 2022.04.18 |
요소-UI 열 필터에서 기본 필터 값을 설정하는 방법 (0) | 2022.04.18 |
vue.js 구성 요소 템플릿에 소품이 있는지 확인하십시오. (0) | 2022.04.18 |