인증된 사용자에 대해서 서버가 사용자를 신뢰하는 것을 이용한 공격
으로 사용자가 의도하지 않은 위조된 요청을 서버에 보내게 되어 서버가 공격을 받게 됩니다.시큐리티 토큰
을 사용하는 방법과 리퍼러
를 사용하는 방법이 있는데 리퍼러를 체크하는 방법은 요청의 리퍼러와 도메인이 일치하는지를 확인하는 것으로 프로젝트의 settings.py에서 CSRF_TRUSTED_ORIGIN에 허용 도메인을 추가해서 안전하지 않은 요청을 보낼 필요가 있는 도메인의 요청을 에러없이 처리할 수 있다.Cross-Site Request Forgery
특정 웹사이트(서버)가 사용자의 웹 브라우저를 신용하는 상태를 노린 것
로그인한 사용자가 CSRF 코드가 삽입된 페이지를 열면 서버는 위조된 공격 명령이 믿을 수 있는 사용자로부터 발송된 것으로 판단하기때문에 공격에 노출된다
사용자가 자신의 의지와 무관하게 공격자가 의도한 행동을 해서 특정 웹페이지를 보안에 취약하게 한다거나 수정, 삭제 등의 작업을 하게 만드는 공격 방법
웹페이지의 취약점을 이용해서 공개된 게시판이나 메일을 이용해서 사용자가 해당 링크를 열게 만드는 방식(피싱)으로 공격할 수 있다
*authenticated된 request에 대해서만(로그인한 유저의 요청에 대해서만) CSRF토큰을 필요로 하며, anonymous request에 대해서는 CSRF토큰을 검증하는 과정을 거치지 않는다 따라서 로그인한 유저에 대해서 403 CSRF 에러가 발생한다
https://mrclap.github.io/posts/django/2019-05-28-django-auth-with-DRF/
① Referer 체크를 하는 방법
request의 referrer를 검증하여 도메인이 일치하는지 확인한다
② security token 사용하는 방법(CSRF token)
사용자의 요청에 난수값을 포함시켜 세션에 저장된 토큰 값(임의의 난수)과 요청 파라미터에 전달되는 토큰 값이 일치하는지 검증
장고템플릿에서 폼태그를 전송할 때(POST 外) {% csrf_token %}
를 반드시 써줘야한다
①, ②는 xss 공경에 대한 취약점이 있다면 csrf 공격에도 취약해짐
③ Double Submit Cookie
Security Token 검증의 한 종류로 세션을 사용할 수 없는 환경
에서 사용할 수 있는 방법으로 웹브라우저의 Same Origin 정책으로 인해 자바스크립트에서 타 도메인의 쿠키 값을 확인/수정하지 못한다는 것을 이용한 방어 기법
스크립트 단에서 요청 시 난수 값을 생성하여 쿠키에 저장
하고 동일한 난수 값을 요청 파라미터(혹은 헤더)에도 저장하여 서버로 전송합니다. 서버단에서는 쿠키의 토큰 값와 파라미터의 토큰 값이 일치하는지 검사
웹브라우저의 Same Origin 정책
: 자바스크립트에서 타 도메인의 쿠키 값을 확인/수정하지 못한다④ GET/POST를 구분해서 요청하는 방법 △
unsafe method를 사용했을 때 리퍼러/헤더 오리진 체크를 할 수 있어서 그런듯
애초에 로그인한 사용자가 unsafe method로 request를 보낼 때 CSRF 토큰이 없으면 403오류가 남
form에 반드시 붙여 보내는 게 form작성/수정하는 게 모두 unsafe method니까
① settings.py, views.py 수정
settings.py MIDDLEWARE - CSRF 부분 주석처리
views.py from django.views.decorators.csrf import csrf_exempt
데코레이더로 해당 Class 데코레이트
csrf_exempt
<-> csrf_protect
requires_csrf_token : 템플릿태그가 확실하게 작동하는 것을 확인할 수 있는 데코레이터
② settings.py만 수정
MIDDLEWARE - security, csrf, auth 부분 주석처리
①, ②는 안전하지 않은 해결방법
③ 허용 도메인 추가
settings.py CSRF_TRUSTED_ORIGINS
안전하지 않은 요청(POST 外)에 대한 믿을 수 있는 오리진 리스트를 작성
기본값은 빈 리스트
장고의 CSRF 프로텍션
방침에 의해서
- 오리진 헤더를 포함하는 요청은 호스트의 헤더에 있는 오리진과 일치하는 헤더가 있어야 한다 또는 CSRF_TRUSTED_ORIGINS에 있어야한다
- 오리진: 도메인, 프로토콜, 포트로 구성
- 오리진 헤더를 포함하지 않는 보안된(SECURE->HTTPS) 안전하지 않은 요청은 호스트의 헤더에 있는 오리진과 일치하는 Referer 헤더가 있어야한다
CSRF 토큰은 로그인할 때마다 바뀌는데 로그인 이전에 생성된 폼이 있는 페이지는 유효하지 않은 토큰을 가지고 있어서 리로드
가 필요하다
로그인 후 뒤로가기 버튼을 누르거나 다른 브라우저 탭에서 로그인하는 경우 이런 에러가 발생할 수 있다
CsrfViewMiddleware가 응답시 django.middleware.csrf.get_token()이 호출될 때마다 CSRF 쿠키
를 같이 보낸다. 안전을 위해 유저가 로그인할 때마다 값은 변경된다
POST 폼에는 csrfmiddlewaretoken라는 숨겨진 폼필드가 있는데 템플릿 태그 {% csrf_token %} 사용시 get_token()이 호출되면서 mask가 생성되어 response와 섞이면서 이 필드의 값이 보호된다.
모든 요청(HTTP GET, HEAD, OPTIONS or TRACE-safe method-이 아닌)에 대해서 CSRF 쿠키
는 반드시 존재해야하고 csrfmiddlewaretoken 필드
또한 반드시 존재하고 멀쩡해야한다. 아니라면 403 에러를 발생시킨다.
CsrfViewMiddleware는 current host와 CSRF_TRUSTED_ORIGINS 목록에 대해서 Origin 헤더
를 검증해서 cross-subdomain attacks을 예방한다
Origin 헤더가 없는 HTTPS requests에 대해서 CsrfViewMiddleware는 리퍼러 체크를 진행한다.
safe method를 통한 요청은 무시한다
man-in-the-middle attack을 방지할 수 없다.
https://itstory.tk/entry/CSRF-%EA%B3%B5%EA%B2%A9%EC%9D%B4%EB%9E%80-%EA%B7%B8%EB%A6%AC%EA%B3%A0-CSRF-%EB%B0%A9%EC%96%B4-%EB%B0%A9%EB%B2%95
https://dpcalfola.tistory.com/entry/Django-pojc-E5-CSRF-token%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC-%ED%86%A0%ED%81%B0-%EA%B2%80%EC%A6%9D-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%A7%88%EA%B0%90-%EC%B6%94%EA%B0%80%EA%B8%80-2%EB%B2%88
https://namu.wiki/w/CSRF
https://grooveshark.tistory.com/73
https://docs.djangoproject.com/en/4.1/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie
템플릿 양식과 특정 데이터 모델에 따른 입력 자료를 합성하여 결과 문서를 출력하는 소프트웨어(또는 소프트웨어 컴포넌트)
https://gmlwjd9405.github.io/2018/12/21/template-engine.html
DRF의 API View는 FBV와 CBV가 있고 CBV가 class의 장점을 이용해서 코드를 간소화할 수 있음
스마트폰 출시 이후 어플리케이션의 등장으로 더 이상 웹으로만은 서비스를 제공할 수 없었다. 즉, HTML로 렌더링하는 웹 서버가 아닌, JSON 혹은 XML과 같은 형식을 통해 데이터를 다루는 별도의 API 서버가 필요해진 것이다. (생각해보면 웹이나 앱이나 제공하는 기능과 주고받는 데이터가 동일한데 기존의 웹 서버만을 사용하여 매번 HTML을 읽고 --> 해당 태그에 들어있는 정보를 찾아내어 --> 스마트폰 화면에 띄우는 절차를 진행하는 것은 상당히 비효율적인 일이다.)
https://velog.io/@ifyouseeksoomi/DRF-Django-REST-Framework-%EA%B0%84%EB%8B%A8%ED%95%9C-%EC%98%88%EC%8A%B5-Serializer
API는 무엇을 의미하나요?
API는 Application Programming Interface (애플리케이션 프로그램 인터페이스)의 줄임말입니다. API의 맥락에서 애플리케이션이라는 단어는 고유한 기능을 가진 모든 소프트웨어를 나타냅니다. 인터페이스는 두 애플리케이션 간의 서비스 계약이라고 할 수 있습니다. 이 계약은 요청과 응답을 사용하여 두 애플리케이션이 서로
통신하는 방법
을 정의합니다.
API 문서에는 개발자가 이러한요청과 응답을 구성하는 방법
에 대한 정보가 들어 있습니다.
https://aws.amazon.com/ko/what-is/api/
https://blog.naver.com/sw_maestro/222930071929
함축적으로 최소한의 정보만을 가지고 있어 XML 에 비해 용량이 줄어들어
속도가 빠르다
프로그래밍 언어와 플랫폼에 독립적이므로, 서로 다른 시스템간에 객체를 교환하기에 좋다.
대부분의 최신 웹 브라우저는 JSON 전용 parser 기능을 내장하고 있으므로 이런 기능을 사용하는 것이 더 안전할 뿐만 아니라 빠른 방법이다.
DOM을 사용하는 것보다
대용량급의 데이터 송수신에는 부적합한 모습도 있습니다.
무결성을 검증하지 않는다
https://ko.wikipedia.org/wiki/JSON
https://namu.wiki/w/JSON
https://velog.io/@seongguk/JSON-vs-XML
데이터를 필터링해서 검색할 때 검색조건이 복잡할 때 사용하기 좋고 filter 안에서
or연산이 가능합니다.
# filter 외부에서 OR 연산자 사용
Product.objects.filter(id__gt=6) | Product.objects.filter(name__contains = "ooo")
# filter 내부에서 OR 연산자 사용
Products.object.filter(Q(name='velog')|Q(created_at='2022-08-29'))
# 객체 가져오기
Q(Product) # == Product.objects.all()
filter()
, exclude()
메소드에서 사용 가능한 내장 모듈
https://devvvyang.tistory.com/37
# example on CBV
from rest_framework.permissions import IsAuthenticated
class ExampleView(APIView):
permissions_classes = [IsAuthenticated]
def get(self, request, format=None):
content = {'status' : 'request was permitted'}
return Response(content)
두가지 메서드를 사용해서 원하는 permission 구현할 수 있음
*장고의 모든 permission class는 이 두가지 함수로 구현되어있음