https://jwt.io/introduction

  • 로그인 시 Token 발급
  • 발급된 Token으로 서비스 이용 가능
  • JWT Web Token의 구조는 다음과 같다.
    • Header.Payload.Signature

Header

  • Header에는 Token의 type과 알고리즘(SHA256이나 RSA)으로 구성
    • Base64Url 방식으로 인코딩되어 있다.

Payload

  • 개체(유저 등)의 상태나 부가 정보가 포함된 여러개의 claim으로 구성

  • registered, public, privated claim이 존재한다.

    Registered claims

    • (iss)issuer, (exp)expiration time, (sub)subject, (aud)audience 등 유용한 정보 제공

    • claim의 이름은 3글자

      Public claims

    • 마음대로 정의 가능하나 충돌 방지하기 위해서는 IANA JSON 웹 토큰 레지스트리에 정의하거나 충돌 방지를 포함하는 URI 정의

      Private claims

    • 정보 공유를 위해 생성된 사용자 지정 claim

Signature

  • 인코딩된 Header, 인코딩된 payload, 키(secret), 알고리즘을 가져와서 서명한 부분
  • 메세지가 도중에 변경되지 않았는지 확인하는데 사용

  • JWT Token : Header, Payload, Signature을 모두 합침.

Django에서 JWT 사용


  1. DjangoRestFramework-jwt 설치

     pip install djangorestframework-jwt
  1. Settings.py에 다음 내용 추가

     REST_FRAMEWORK = {
         'DEFAULT_PERMISSION_CLASSES': (
             'rest_framework.permissions.IsAuthenticated',
         ),
         'DEFAULT_AUTHENTICATION_CLASSES': (
             'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
             'rest_framework.authentication.SessionAuthentication',
             'rest_framework.authentication.BasicAuthentication',
         ),
     }
  1. urls.py에 다음 내용 추가

    • url명은 자유로이 변경 가능

    • obtain_jwt_token ⇒ jwt token 획득

      • POST 메서드, data로 username, password 주면 token 획득
    • refresh_jwt_token ⇒ jwt token 갱신

      • POST 메서드, data로 기존 token 주면 새로운 토큰을 response
    • verify_jwt_token ⇒ jwt token 검증

      • POST 메서드, data로 token 주어야 함.
      path('apitokenauth/', obtain_jwt_token),
      path('apitokenrefresh/', refresh_jwt_token),
      path('apitokenverify/', verify_jwt_token),
  1. Token 생성 / 사용 테스트

    • 간단한 api를 만들어 주는데, authentication을 JSONWebTokenAuthentication으로 해주어야 JWT를 사용하여 인증이 진행된다.

      path('api/', APITest.as_view())
      
      class APITest(APIView):
        authentication = [JSONWebTokenAuthentication]
      
        def get(self, request, format=None):
            return Response({'message': 'success call api'})
    • JavaScript로 테스트

      • cors 문제가 발생하여 API 호출이 잘 안되는 문제점이 있었음.

      • django-cors-headers 라이브러리 추가

          pip install django-cors-headers
      • 현재는 API 접근 제한을 따로 걸 필요가 없으므로 전체 허용(CORS_ALLOW_ALL_ORIGINS)

        # INSTALLED_APPS에 추가
        INSTALLED_APPS = [
          ...,
          "corsheaders",
          ...,
        ]
        
        # Settings.py의 맨 아래에 추가
        CORS_ALLOW_ALL_ORIGINS=True
        
        # MIDDLEWARE에 추가, 적어도 CommonMiddleware보다는 위에 가도록
        MIDDLEWARE = [
          ...,
          "corsheaders.middleware.CorsMiddleware",
          "django.middleware.common.CommonMiddleware",
          ...,
        ]
      • 자세한 점은 https://github.com/adamchainz/django-cors-headers

        let userdata = {
          username : 'admin',
          password : 1234,
        };
        
        async function get_JWT_token() {
          try {
              const response = await fetch('http://127.0.0.1:8000/apitokenauth/', {
                  method: "POST",
                  headers: {
                      "Content-Type": "application/json"
                  },
                  body: JSON.stringify(userdata)
              });
              const data = await response.json();
              const token = data["token"];
              console.log(token);
              return token;
          } catch (error) {
              console.log('error');
          }
        };
        
        async function call_api() {
          let api_token = await get_JWT_token();
          const token = api_token;
          const called_api = await fetch('http://127.0.0.1:8000/test/api/', {
                  method: "GET",
                  headers: {
                      "Content-Type": "application/json",
                      "Authorization": "JWT " + token
                  }
              });
          const api_result = await called_api.json();
          return api_result;
        };
      • 오랜만에 async / await 써보니까 많이 헷갈림..

      • 소스를 전체적으로 설명하자면 username이 'admin', password가 1234인 유저의 JWT Token을 얻은 다음, 토큰을 가지고 API를 호출하는 소스이다.

      • API 호출 시에는 headers에 Authorization을 추가해주어야 한다. 값은 JWT + " " + 토큰

      • 유저 데이터가 서버에 없는 경우 JWT 토큰이 발급되지 않으며 당연히 API 호출 시에도 unauthorized가 나타난다.

      • 크롬 개발자 도구에서 console.log가 잘 출력되지 않는다면 필터에 뭐가 입력되어 있는지, 아니면 정보 부분이 체크가 잘 되어있는지 확인해야 한다.

      • 토큰을 로컬 저장소에 저장하거나, 쿠키에 저장할 수 있다는데.. JS를 통해 로컬 저장소에 있는 토큰을 가져올 수 있어서 XSS 공격에 취약하고, 쿠키같은 경우는 secure, httpOnly 속성을 활용하여 막을 수 있다고 한다. 쿠키에 저장하는 방법이 그나마 나아보이긴 하지만, CSRF 문제가 있을 수 있다고 한다.

'프레임워크 > Django' 카테고리의 다른 글

[ Django ] CSRFToken  (0) 2021.10.16
[ Django ] JWT(djangorestframework-simplejwt)  (0) 2021.10.15
[ Django ] Choice  (0) 2021.09.15
[ Django ] MySQL 연동  (0) 2021.09.14
[ Django ] 게시판에 Summernote 에디터 적용  (0) 2021.09.07

Choice


  • 모델의 속성에 원하는 값들중 하나의 값을 넣고싶은 경우 속성에 Choice를 추가해주면 된다.
  • Choice의 타입은 (실제 저장될 값, 사용자에게 표시할 값) 형식으로 들어간다.
  • 사용자에게 표시할 값은 추후 템플릿에서 사용된다.

모델에 Choice 설정


  • 게시판 모델에 Choice 설정 (자유게시판, 파이썬 게시판, 자바 게시판중 하나)
CHOICES = (
        (0, '자유'),
        (1, '파이썬'),
        (2, '자바'),
    )

posttype = models.IntegerField(default=0, choices=CHOICES)

폼에 모델 속성 추가


class QuestionForm(forms.ModelForm):
    class Meta:
        model = Question
        fields = ['posttype', 'subject', 'content', 'image']
        labels = {
            'posttype': '게시판',
            'subject': '제목',
            'content': '내용',
            'image': '이미지',
        }

템플릿에 게시판 타입 Select 추가


<div class="form-group">
    <label for="posttype">게시판</label>
    <select class="form-select" name="posttype" id="id_posttype">
        <!-- choice에서 (실제값, 유저에게 보여질 내용) 지정해 주었으므로, -->
        {% for v, k in form.fields.posttype.choices %}
            <option value="{{ v }}" {% if form.fields.posttype.value == v %} selected {% endif %}>{{ k }}</option>
        {% endfor %}
    </select>
</div>
  • form.fields.posttype.choices
    • 가져오면 위에서 지정한 (실제값, 유저에게 보여질 내용) 리스트가 넘어옴
    • select의 option을 설정할 때 사용
  • select의 name과 id 속성을 맞추어서 잘 설정해 준다.
    • Bootstrap을 사용하였기 때문에 위와 같은 과정이 필요함.
    • 그냥 쓰려면 {{ form.posttype }} 써주면 된다.

'프레임워크 > Django' 카테고리의 다른 글

[ Django ] JWT(djangorestframework-simplejwt)  (0) 2021.10.15
[ Django ] JWT  (0) 2021.10.14
[ Django ] MySQL 연동  (0) 2021.09.14
[ Django ] 게시판에 Summernote 에디터 적용  (0) 2021.09.07
[Django] Rest API 및 Ajax  (0) 2021.07.25

연동 전 필요 라이브러리 설치

mysqlclient 설치


pip install mysqlclient

에러 발생할 경우 자가해결 방법(python3)


sudo apt-get install python3-dev default-libmysqlclient-dev build-essential

Settings.py의 DataBase 수정


  • 우선 기본적으로 설정되어있는 데이터베이스를 수정해 주어야 한다.
  • 찾아보니 OPTIONS에 굳이 파일을 주지 않고 바로 NAME, USER, PASSWORD, HOST, PORT를 줘버려도 되지만, 파일이 훨씬 깔끔해 보여서 파일로 따로 지정

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'OPTIONS':  {
            'read_default_file': os.path.join(BASE_DIR, 'djangoproj.cnf'),
        }
    }
}


djangoproj.cnf


  • db명, db ID, db PW, 기본 문자열셋 지정
  • 호스트, 포트도 지정해주어야 함.. ⇒ 안해주면 에러가 나요..
[client]
database = djangoproject
user = root
password = root
default-character-set = utf8
host: 127.0.0.1
port: 3306


Database 생성


  • 위에서 database = 에 적어준 이름을 가진 데이터베이스를 mysql에서 만들어 두어야 한다.
create database djangoproject character set utf8;

마이그레이션


python manage.py makemigrations
python manage.py migrate
  • 마이그레이션까지 적용되었다면 mysql 연동이 끝남!

'프레임워크 > Django' 카테고리의 다른 글

[ Django ] JWT  (0) 2021.10.14
[ Django ] Choice  (0) 2021.09.15
[ Django ] 게시판에 Summernote 에디터 적용  (0) 2021.09.07
[Django] Rest API 및 Ajax  (0) 2021.07.25
[Django] Django 설치  (0) 2021.07.16

게시판에 어떠한 기능을 추가해볼까 고민하던 중, 글을 쓸 때 글의 작성부분이 밋밋한 점이 마음에 들지 않았다. 직접 구현하기에는 너무 어려울것 같아 구글링을 해보니, Summernote라는 에디터를 사용하면 된다고 하더라. 사용법을 찾아보니 쉬운것 같아 공유해보고자 한다.

출처 : https://summernote.org/getting-started/#include-jscss

1. HTML 헤더


  • Bootstrap으로 구현된 에디터이다 보니, HTML 헤더가 필요하다.
    <!DOCTYPE html>
    <html lang="en">
    ...
    </html>

2. 필요한 파일 추가


<!-- include libraries(jQuery, bootstrap) -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>

<!-- include summernote css/js -->
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.js"></script>    

3. 에디터 불러오기


  • 에디터를 적용할 textarea 만들기
    <textarea class="form-control" name="content" id="content" rows="10">{{ form.content.value|default_if_none:'' }}</textarea>
  • 해당 textarea에 summernote 적용
    <script type="text/javascript"> 
      $(document).ready(function() { $("#content").summernote(); }) 
    </script>

4. Django에서 불러오는 부분 처리


  • Django에서 HTML 텍스트를 그대로 불러올 수 없음.
  • 템플릿 필터중에 safe 필터를 사용
    • 보안상에 문제가 있을수도 있으니 신중히 사용해야 함.
    • 악성 스크립트 삽입 공격에 대한 고려가 필요함.
      • 다행히도 Summernote 에디터에서는 입력한 데이터에 대해서는 이스케이프가 적용되서 HTML 태그를 생성하므로 safe 필터를 사용해도 문제가 없을 것이라고 생각된다.
    • 이스케이프가 적용되지 않음, 기본적으로는 이스케이프 적용 => HTML 태그를 적용.
<div class="card-text" style="white-space: pre-line;">
  {{ question.content|safe}}
</div>

이스케이프 적용 / 미적용 차이점


  • 이스케이프가 적용되지 않음
    <b>
  • 이스케이프가 적용됨
    &lt;b&gt;

'프레임워크 > Django' 카테고리의 다른 글

[ Django ] Choice  (0) 2021.09.15
[ Django ] MySQL 연동  (0) 2021.09.14
[Django] Rest API 및 Ajax  (0) 2021.07.25
[Django] Django 설치  (0) 2021.07.16
[Django] pyenv  (0) 2021.07.16

1. 추가 설치

pip install djangorestframework

2. serializer 생성

from rest_framework import serializers
from .models import InterestCompany

class InterestCompanySerializer(serializers.ModelSerializer):
    class Meta:
        model = InterestCompany
        fields = "__all__" # Tuple 형식으로 나열해주어도 된다.

3. ViewSet 생성

  • CRUD를 1개의 View로 구현
    • [GET] api/{pk}/ : detail
    • [PUT] api/{pk}/ : 수정
    • [DELETE] api/{pk}/ : 삭제
    • [GET] api/ : 전체 리스트
    • [POST] api/ : 추가
  • permission_classes 등록이나 생성 시 save 처리 필요(perform_create)
from .serializer import InterestCompanySerializer
from rest_framework import viewsets

class InterestCompanyViewSet(viewsets.ModelViewSet):
    queryset = InterestCompany.objects.all()
    serializer_class = InterestCompanySerializer

4. URL 설정

  • 앱의 urls.py에 다음과 같이 작성
IC_list = InterestCompanyViewSet.as_view({
    'post': 'create',
    'get': 'list'
})

IC_detail = InterestCompanyViewSet.as_view({
    'get': 'retrieve',
    'put': 'update',
    'patch': 'partial_update',
    'delete': 'destroy'
})

path('interest/api/', IC_list, name="api-company-list"),
path('interest/api/<int:pk>/', IC_detail, name="api-company-detail"),

⇒ 보았을 때.. 해당 url로 접근하였을 때, post/get/put/patch/delete 등 접근 방식에 따라 취하는 행동 정의하는 거 같음.

5. 테스트

  • TemplateDoesNotExist(rest_framework/api.html) 에러 등장
    • 구글링 결과 .. INSTALLED_APPS에 등록을 안함.

image

  • Settings.py → INSTALLED_APPS → rest_framework 등록
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework'
    'Interest'
]

Ajax 설정


  • jquery load
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
  • Ajax Script 작성
<!--버튼-->
<a class="btn btn-success" id="success" onclick="clickevent(this);" name="{{forloop.counter0}}">관심 기업 등록</a>
<!-- 자기 자신 전달하기 위해선 this로 넘겨주면 된다. -->

function clickevent(self) {
        var idx = $(self).attr('name')
        var name = $('#name'+idx).attr('name')
        var title = $('#title'+idx).attr('name')
        console.log(idx+"//"+name+"//"+title);
        $.ajax({
            type: "POST",
            url: "{% url 'api-company-list' %}",
            data: {
                "company_name" : name,
                "intern_title" : title,
                "duration" : "1900-01-01T12:00"
            },
            dataType: "json",
            success: function(response) {
                window.location.reload()
            },
            error: function(request, status, error) {
                console.log("code:"+request.status+"\n"+"message:"+request.responseText+"\n"+error);

            }
        });
    }
  • Django CSRF 에러시 해결법

    • 인증을 아직 도입하지 않았을 때, 필요 없는경우

      from rest_framework.authentication import SessionAuthentication, BasicAuthentication
      
      class CsrfExemptSessionAuthentication(SessionAuthentication):
        def enforce_csrf(self, request):
            return  # To not perform the csrf check previously happening
      
      #ModelViewSet 맨 윗줄에 추가
      authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)
    • https://stackoverflow.com/questions/30871033/django-rest-framework-remove-csrf

'프레임워크 > Django' 카테고리의 다른 글

[ Django ] MySQL 연동  (0) 2021.09.14
[ Django ] 게시판에 Summernote 에디터 적용  (0) 2021.09.07
[Django] Django 설치  (0) 2021.07.16
[Django] pyenv  (0) 2021.07.16
[Django] 환경 설정  (0) 2021.07.16

1. Django 설치

pip install django==2.2

2. django 버전 확인

django-admin --version

3. 설치되어 있는 파이썬 패키지 목록 보기

pip list

 

'프레임워크 > Django' 카테고리의 다른 글

[ Django ] MySQL 연동  (0) 2021.09.14
[ Django ] 게시판에 Summernote 에디터 적용  (0) 2021.09.07
[Django] Rest API 및 Ajax  (0) 2021.07.25
[Django] pyenv  (0) 2021.07.16
[Django] 환경 설정  (0) 2021.07.16

1. 설치 가능한 리스트 확인

pyenv install --list

 

2. 파이썬 설치

- pyenv install 버전

pyenv install 3.7.7
pyenv install 3.8.2

3. 설치된 파이썬 버전 확인

pyenv versions

4. 가상 환경 구성

- pyenv virtualenv 설치된 파이썬 버전 가상환경명

pyenv virtualenv 3.7.7 django-envs

5. 가상 환경 삭제

- pyenv uninstall 가상환경명

pyenv uninstall django-envs

6. python 가상 환경 적용

* global: 시스템 전역

* local: 특정 디렉토리 내부(하위 디렉토리도 모두 local 적용)

 

global 적용

pyenv global 3.8.2

- global 적용 확인은 pyenv versions 실행 후 * 표시로 확인

- 현재 디렉토리의 버전 확인은 pyenv version

 

local 적용

pyenv local 가상환경명

 

'프레임워크 > Django' 카테고리의 다른 글

[ Django ] MySQL 연동  (0) 2021.09.14
[ Django ] 게시판에 Summernote 에디터 적용  (0) 2021.09.07
[Django] Rest API 및 Ajax  (0) 2021.07.25
[Django] Django 설치  (0) 2021.07.16
[Django] 환경 설정  (0) 2021.07.16

1. 시스템 요구사항 확인

- 64bit, window10 빌드 1607 이상

 

2. VSCODE 설치

- https://code.visualstudio.com/

 

Visual Studio Code - Code Editing. Redefined

Visual Studio Code is a code editor redefined and optimized for building and debugging modern web and cloud applications.  Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows.

code.visualstudio.com

- Download for Windows 클릭하여 다운로드

3. WSL 다운로드

- Windows 기능 켜기/끄기에서 리눅스용 Windows 하위 시스템 체크

- Microsoft store에서 ubuntu 18.04 LTS 설치

- 설치 후 userid / password 설정

 

- 기본 패키지 설치

sudo apt-get update

sudo apt-get install -y make build-essential \
 libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \
 wget curl llvm libncurses5-dev libncursesw5-dev \
 xz-utils tk-dev git python-pip

- WSL 내에서 VSCODE 실행(현재 디렉토리)

code .

 

- pyenv 설치

curl https://pyenv.run | bash

0. pyenv 설치한 후 나타나는 export 따로 확인

1. 홈 디렉토리(~) 에서 vscode 실행

2. .bashrc 선택 후 맨 마지막 줄에 다음 행 추가

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv virtualenv-init -)"

3. 이후 pyenv --version 사용하여 버전 잘 나오면 설치 완료

 

 

4. 기타 사항

- Font : D2Coding 사용

- VSCode 확장프로그램 설치

 Python Extension

 Django Extension

 vscode-icons

 

 

'프레임워크 > Django' 카테고리의 다른 글

[ Django ] MySQL 연동  (0) 2021.09.14
[ Django ] 게시판에 Summernote 에디터 적용  (0) 2021.09.07
[Django] Rest API 및 Ajax  (0) 2021.07.25
[Django] Django 설치  (0) 2021.07.16
[Django] pyenv  (0) 2021.07.16

+ Recent posts