[ Architecture, Technology ,Web ] SSO(Single Sign On) 그리고 SAML에 대해

이미지
이번 프로젝트 내부에서 어쩌다보니  유저 인증 관련 업무를 담당하게 되었고, 해야하는 업무는 내부에 사용했던 적이 없던  새로운 개발 플랫폼에서  SSO의 프로토콜 중  SAML을 이용해 앱의 인증을 구현해야만 했다. SSO를 생각해본적 조차 없는 상황에 이를 새로운 개발 플랫폼에 도입해야 했기 때문에 많은 시행착오를 겪었으나 구현에 성공하였으며 덕분에 SSO에 대한 전반적인 지식을 쌓을 수 있었다. 이번에는 그러한 과정에서 나온 지식들과 경험을  공유하고자 한다. SSO에 대한 정의 먼저 사전적 정의 부터 살펴보자. 다만, 기술적인 용어다보니 자주 사용하는 옥스포드 사전에 정의를 찾을 수 없기 때문에  검색으로 찾을 수 있는 정의를 몇 가지 살펴보고 교차 검증을 해보자. 첫 번째 정의를 살펴보자. Single sign-on (SSO) is an identification method that enables users to log in to multiple applications and websites with one set of credentials.  SSO는 웹사이트에서 한 번의 인증(one set of credentials)으로 복수의 어플리케이션에 로그인 할 수 있는 인증(identification) 방법(method) 이다. 두 번째는 위키피디아의 정의이다. Single sign-on (SSO) is an authentication scheme that allows a user to log in with a single ID to any of several related, yet independent, software systems. SSO는 독립적이지만 연관되어있는 몇몇 소프트웨어에 대해 하나의 ID로 로그인을 할 수 있도록 하는 인증 구조(scheme) 세부 설명에 조금 차이가 있어 보이지만 전체적인 틀은 매우 비슷해 보인다.  몇 가지 포인트가 되는 단어를 추출해 이를 연결해보자면 아래와 같은 의미를 산출 할 수 있다. 독립적이지만 연관되어 있

[ Django, Python ] mozilla 튜토리얼 예제로 살펴보는 Django 분석 ⑤ - 3 : 도전 과제


사실 한 가지 프로그래밍하지 않은 페이지가 있는데


바로 All authors 페이지를 프로그래밍 하지 않았다.

이번 도전 과제는 
All authors 페이지가 정상적으로 작동하도록
프로그래밍 하는 것이다.

정확히는 All authors를 눌렀을 때
실제 화면에 표시되는 Template
데이터를 Model로 부터 받아오는 View를 프로그래밍하면 된다. 

기능 상으로는 All authors페이지와 똑같기 때문에 
변수 명만 바꿔주면 될 것 같다.

먼저 작가 목록을 보여줄 페이지 부터 해보자.


위의 화면은 All books 하이퍼링크를 누르면 나오는 화면이다.

대충 Book List를 Authors List으로 
아래의 책 이름을 저자 이름으로 
보이게끔 하면 될 것 같다.

대충 그림은 그려졌으니 
실제로 프로그래밍 해보자.


먼저 book_list.html 파일을 복사해 붙여 넣기 후 
author_list.html으로 이름을 바꾸자.

수정할 곳이 몇몇 보일 것 이다.

그 중 가장 중요한 book.get_absolute_url 쪽(9번째 줄)을 보면
이 메소드는 Model을 작성했을 때
동적 url을 리턴하는 메소드였는데 


위와 같이 Author Model에서도 
똑같이 get_absolute_url이라는 메소드를 
작성했던 것을 기억날 것이다. 

똑같이 이것을 사용해 template를 작성해보기 전에
ListView와 DetailView를 먼저 코딩하고,
url을 이어줘야 한다.

먼저 View에 제너릭 뷰를 추가해보자.


class AuthorListView(generic.ListView):
    model = Author
    paginate_by = 5

class AuthorDetailView(generic.DetailView) :
    model = Author
위와 같이 ListViewDetailViwe를 생성하고
녹색 박스와 같이 pagination(페이징)을 해준다.


urlpatterns = [
    path('', views.index, name='index'),
    path('books/', views.BookListView.as_view(), name='books'),
    path('book/<int:pk>', views.BookDetailView.as_view(), name='book-detail'),
    path('author/', views.AuthorListView.as_view(), name='authors'),
    path('author/<int:pk>', views.AuthorDetailView.as_view(), name='author-detail'),
]
그리고 정의했던 
AuthorListViewAuthorDetailViewurl을 정의하자.

다음에는 하이퍼링크를 누르면 이동하게끔 
base_genric.html파일에 코드를 추가해주어야 한다.


여기서 authors라는 이름은 
path() 함수에 정의 했을때
name 인수에 정의했던 데이터를 코딩하면 된다.

나는 위에서 path( ... , ... , name = 'authors')로 했기 때문에
authors로 코딩했다.

그 다음 처음에 복사하고 
이름만 바꿨던 author_list.html 파일을 수정해보자.


{% extends "base_generic.html" %}

{% block content %}
  <h1>author List</h1>
  {% if author_list %}
  <ul>
    {% for author in author_list %}
      <li>
        <a href="{{ author.get_absolute_url }}">{{ author }}</a>
      </li>
    {% endfor %}
  </ul>
  {% else %}
    <p>There are author in the library.</p>
  {% endif %}
{% endblock %}
코드를 보면 알겠지만
놀랍게도 내가 한것이라고는 이름만 바꿨을 뿐이다.

다만, 빨간색 박스에서 author만 코딩한 이유는 
Model을 정의 했을 때 __str__ 메소드
작가의 first namesecond name을 합쳐서 보이게 끔 
코딩한 적이 있는데
Author Model은 아래와 같다.


이 __str__ 메소드객체만 호출됐을 때 
호출되는 메소드이다.

따라서 객체만 달랑 코딩해놓으면 자동적으로 
__str__ 메소드가 불려오고,
그에 따른 리턴값이 나올 것이다.


왼쪽이 book_list.html 파일이고, 
오른쪽이 author_list.html 파일 이다.

나는 정말로 이름만 바꾸었다.
거짓말이 아니다.


이제 브라우저에 All authors 하이퍼링크를 클릭하면 
작가들의 목록이 나오는 것을 확인해 볼 수 있다.

다음으로 DetailView로 넘어가보자.


ListView때와 마찬가지로 
book_detail.html을 복사해 붙여넣고
이름을 author_detail.html으로 바꿔보자.

우리가 할 일을 크게 2가지 이다.
빨간색 박스 와 같이 Author의 레코드를 나열하고,
녹색 박스와 같이 해당 작가의 책을 출력할 것이다.

그럼 먼저 빨간색 박스부터 해보자.


Author Model을 살펴보면
우리가 표시해야될 레코드는 3가지 인 것을 알 수 있다.

물론 변수는 4개가 정의되어있다.

하지만 이름은 합쳐서 불러올 것이기 때문에 
3가지만 설정하면 될 것이다.


위에서 설명했듯이 
3개의 레코드만 출력하면 되기 때문에 
3줄을 코딩해준다.

{% extends "base_generic.html" %}

{% block content %}
  
  <h1>Name : {{ author }}</h1>

  <p><strong>Birth Date : </strong> {{ author.date_of_birth }}</p>
  <p><strong>Death Date : </strong> {{ author.date_of_death }}</p>

  <div style="margin-left:20px;margin-top:20px">
    <h4>Copies</h4>

    {% for copy in book.bookinstance_set.all %}
      <hr>
      <p class="{% if copy.status == 'a' %}text-success{% elif copy.status == 'm' %}text-danger{% else %}text-warning{% endif %}">{{ copy.get_status_display }}</p>
      {% if copy.status != 'a' %}
        <p><strong>Due to be returned:</strong> {{copy.due_back}}</p>
      {% endif %}
      <p><strong>Imprint:</strong> {{copy.imprint}}</p>
      <p class="text-muted"><strong>Id:</strong> {{copy.id}}</p>
    {% endfor %}
  </div>
{% endblock %}
굵게 표시한 코드가 실제 수정된 코드이다.

이제 저장하고 실제 출력되는 
화면을 확인해보자.



프로그래밍 한 대로 이름, 출생일, 사망일이 표시 된다.

다음은 녹색 박스다.

우리가 하고 싶은것은 위의 Copies아래에 
해당 작가의 책의 레코드를 나타내고 싶다.


  <div style="margin-left:20px;margin-top:20px">
    <h4>Author BookList</h4>

    {% for copy in author.book_set.all  %}
      <hr>
      <p><strong>Title:</strong> {{copy.title }}</p>
      <p><strong>Summary:</strong> {{copy.summary | linebreaks}}</p>
      <p><strong>ISBN:</strong> {{copy.isbn}}</p>
      <p><strong>Genre:</strong> {{copy.genre.all.get}}</p>
      <p><strong>Language:</strong> {{copy.language}}</p>
      <p class="text-muted"><strong>Id:</strong> {{copy.id}}</p>
    {% endfor %}
  </div>
작가의 관련 책들을 나타내는 코드는 위와 같다.

기존 book_dateil.html을 참고하여
author.book_set.all의 객체를 
copy 변수에 집어넣어 데이터들을 출력했다.

다만 하늘색 박스와 같이 처음 나오는 코드들이 있다.

먼저 linebreaks일반 텍스트의 줄 바꿈을 
적절한 HTML로 바꿔주는 태그이다.

book Model의 summary는 


위의 사진과 같이 TextField 타입인데
그대로 표시할 경우 줄바꿈 형태가 없이 출력이 된다.

따라서 linebreaks 태그를 사용해서 줄바꿈을 해주어야 한다.

자세한 사항은 아래의 링크
공식 도큐먼트를 참고하기 바란다.

그 다음으로 
copy.genre.all.get을 하는 이유는 


위의 사진과 같이 genre가 
다대다 타입의 필드(ManyToManyField)이기 때문이다.

copy.genre.all로 불러오게 되면 


위와 같이 QureySet이 표시되기 때문에
get() 메소드를 사용해서 데이터만 불러온다면
깔끔하게 데이터만 가져올 수 있다.

이처럼 올바르게 프로그래밍 했다면 
아래와 같은 화면을 볼 수 있다.


이 정도 했으면 
도전 과제는 무사히 완수했다고 볼 수 있을 것 같다.


이 블로그의 인기 게시물

[ Web ] 웹 애플리케이션 아키텍처 (Web Application Architecture)

[ Web ] 서버 사이드(Sever Side) ? 클라이언트 사이드(Client Side)? 1 [서론, 클라이언트 사이드(Client Side)]

[ Web ] 웹 애플리케이션? 웹 사이트?(Web Application? Web Site?)