[ 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 분석 ④ - 1 : Creating our home page


Creation our home page


지금까지 했던 것은 
단지 프로젝트 생성, Model 생성, 관리자 앱 추가 및 조작을 해봤다.

하지만 
이것 만으로는 우리가 원하는 하나의 홈 페이지
즉, 애플리케이션을 만들었다고는 할 수 없다.

왜냐하면
아직 View와 Template를 생성하지 않았기 때문이다.

단지 Model을 생성해서 데이터를 
추가 수정 및 삭제 했을 뿐이다.

그렇다면 
다음에 해야 될 것은 당연히
View와 Template를 생성한 후에 
우리가 원하는 애플리케이션을 완성하는 것이다.

우선 아래의 데이터의 흐름과 HTTP 요청 및 응답을 처리하는데에
필요한 요소들에 대해 살펴볼 필요가 있다.

블로그 내의 MVC와 MVT비교 글에 대한 이해가 있다면
이해하는데에 큰 문제는 없을 것이다.

① resource URLs 정의하기


이 버전의 LocalLibrary는 
유저들에게는 읽기 전용이기 때문에
사이트의 방문 페이지 그리고 책들과 저자들에 대한 
목록 및 Detail View들을 보여주는 페이지만 제공해주면 된다.

필요한 URL은 아래와 같다.


Index Page 만들기


첫 번째로 만들 페이지는 index page(catalog/)이다.
즉, 해당 앱에 진입했을 때 보여지는 첫번째 페이지를 말한다.

① URL Mapping


이전에 locallibrary/urls.py 파일을 업데이트 했던것을 기억할 것이다.

catalog/로 시작하는 URL을 받았을때,
URLConf 모듈인 catalog.urls가 나머지 문자열을 처리하도록 하기 위해
이전에 업데이트를 했었다.


이전에 했던 부분이 위의 빨간색 박스이다. 

Django는 import 함수 django.urls.include()를 만날 때 마다
지정된 마지막 문자에서 문자열을 나누고,
나머지 부분 문자열을 포함된 URLconf 모듈로 보냅니다.

또한 /catalog/urls.py이라는 URLConf 모듈을 위한 
파일(place holder)도 생성하였다.



1
2
3
urlpatterns = [
    path('', views.index, name='index'),
]
cs

위와 같이 코드를 추가 하자.

path() 함수에 대한 내용은 
이전에 작성했던 아래의 포스팅을 참고하기 바란다.

이 path() 함수는 name 매개 변수를 지정하는데,
URL Mapping을 위한 고유 ID이다.

이 이름의 Mapper를 반전(reverse())시켜 
URL를 동적으로 생성할 수 있다.

URL을 동적으로 생성하면 
홈페이지를 바꿨을 때 따로 수정하지 않아도 되기 때문에
반전된 URL Mapper를 사용하는 것이 훨씬 유연하다.

② (함수 기반의) View


View는 Http Request를 처리하고
DB에서 Request 된 데이터를 가져오고
Html 템플릿을 이용해서 
데이터를 HTML 페이지에 렌더링 하고,

그리고 생성된 HTML을 Http Response로 반환하여
페이지를 보여주는 함수이다.

catalog/views.py를 연 후에


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from django.shortcuts import render
 
# Create your views here.
from catalog.models import Book, Author, BookInstance, Genre
 
def index(request):
    """View function for home page of site."""
 
    # Generate counts of some of the main objects
    num_books = Book.objects.all().count()
    num_instances = BookInstance.objects.all().count()
 
    # Available books (status = 'a')
    num_instances_available = BookInstance.objects.filter(status__exact='a').count()
 
    # The 'all()' is implied by default.
    num_authors = Author.objects.count()
 
    context = {
        'num_books': num_books,
        'num_instances': num_instances,
        'num_instances_available': num_instances_available,
        'num_authors': num_authors,
    }
 
    # Render the HTML template index.html with the data in the context variable
    return render(request, 'index.html', context=context)
 
cs

위와 같이 코드를 추가하자.

③템플릿(Template)


Template는 HTML와 같은 파일의 구조나 
레이아웃을 정의하는 텍스트 파일이다.

Django는 일반적으로 애플리케이션 안에서 
templates라고 이름지어진 경로 안에서 자동적으로 
템플릿을 찾는다.

1) Template 확장 하기


아래의 코드는 base_generic.html 파일의 기본 템플릿 샘플이다.

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html lang="en">
<head>
  {% block title %}<title>Local Library</title>{% endblock %}
</head>
<body>
  {% block sidebar %}<!-- insert default navigation text for every page -->{% endblock %}
  {% block content %}<!-- default content text (typically empty) -->{% endblock %}
</body>
</html>
cs

특정한 View를 위해 템플릿을 정의할 땐
먼저 extends 템플릿 태그를 이용해서 기본 템플릿을 지정해야한다.

1
2
3
4
5
6
{% extends "base_generic.html" %}
 
{% block content %}
  <h1>Local Library Home</h1>
  <p>Welcome to LocalLibrary, a website developed by <em>Mozilla Developer Network</em>!</p>
{% endblock %}
cs

예를 들어
위의 코드는 extends 템플릿 태그의 사용과
content 블록(block)을 재정의 하는 방법을 보여준다.

생성된 HTML은 기본 템플릿에서 정의된 코드와 구조를 포함한다.

LocalLibrary 기본 Template


새로운 파일인 base_generic.html파일을
/locallibrary/catalog/templates/ 경로 안에 생성해
아래의 코드를 추가하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html lang="en">
<head>
  {% block title %}<title>Local Library</title>{% endblock %}
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
  <!-- Add additional CSS in static file -->
  {% load static %}
  <link rel="stylesheet" href="{% static 'css/styles.css' %}">
</head>
<body>
  <div class="container-fluid">
    <div class="row">
      <div class="col-sm-2">
      {% block sidebar %}
        <ul class="sidebar-nav">
          <li><a href="{% url 'index' %}">Home</a></li>
          <li><a href="">All books</a></li>
          <li><a href="">All authors</a></li>
        </ul>
     {% endblock %}
      </div>
      <div class="col-sm-10 ">{% block content %}{% endblock %}</div>
    </div>
  </div>
</body>
</html>
cs

또한 /locallibrary/catalog/static/css/
경로에 템플릿의 디자인을 제공하는 styles.css 파일을 생성하고 
위의 코드를 추가하자. 하자.

색인(Index) Template


새로운 HTML 파일 index.html을 
/locallibrary/catalog/templates/ 경로 안에 생성해
아래의 코드를 추가하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{% extends "base_generic.html" %}
 
{% block content %}
  <h1>Local Library Home</h1>
  <p>Welcome to LocalLibrary, a website developed by <em>Mozilla Developer Network</em>!</p>
  <h2>Dynamic content</h2>
  <p>The library has the following record counts:</p>
  <ul>
    <li><strong>Books:</strong> {{ num_books }}</li>
    <li><strong>Copies:</strong> {{ num_instances }}</li>
    <li><strong>Copies available:</strong> {{ num_instances_available }}</li>
    <li><strong>Authors:</strong> {{ num_authors }}</li>
  </ul>
{% endblock %}
cs

{% block content %} ~ {% endlock  %} 사이에 
표시하고 싶은 View의 정보를 코딩한다.
 
위의 코드에서 알 수 있듯이 
변수들은 이중 괄호( {{ }} )로 감싸져있고,
태그들은 ({% %})단일 중괄호와 
퍼센트 기호로 감싸져 있는 것을 알 수 있다.

다만 주의해야 할 것은 
변수들의 이름은 Key로 정해진다는 것이다.

이 Key들은 View의 render()함수 안의 context 
사전형 자료형에 전달하는 Key이다.


변수들은 템플릿이 render()함수에 의해 
렌더링 될 때 연관된 값들로 대체 될 것이다.



Template에 정적 파일 참조하기(Referencing)


결국 이 프로젝트는 자바스크립트, CSS 그리고 이미지를 포함하는
정적 리소스들을 사용할 가능성이 높다.

하지만 Django는 이 위치를 알 수 없기 때문에
STATIC_URL 전역 설정을 기준으로
템플렛에서의 위치를 특정할 수 있도록 한다.

1
2
3
<!-- Add additional CSS in static file --> 
{% load static %} 
<link rel="stylesheet" href="{% static 'css/styles.css' %}">
cs

위의 코드와 같이
템플렛 안에서 먼저 템플릿 라이브러리를 추가하기 위해 
static을 지정하는 load 템플렛 태그를 호출한다.

1
2
{% load static %}
<img src="{% static 'catalog/images/local_library_model_uml.png' %}" alt="UML diagram" style="width:555px;height:540px;">
cs

비슷한 방식으로 위와 같이 
이미지를 페이지에 추가할 수도 있다.

정적 파일들에 대한 자세한 내용은 
아래의 공식 도큐먼트를 참고하길 바란다.


Template을 찾을 수 있는 곳 설정하기



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
TEMPLATES = [
    {
        'BACKEND''django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(BASE_DIR, 'templates'),
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
cs

위의 코드와 같이 settings.py 파일 안에
TEMPLATES 변수에 빨간색 박스와 같이 코드를 추가하자.

그렇다면 이제 실제 Model에 View와 Template를 
그리고 이전 튜토리얼에는 없었던 CSS까지 추가 한
Locallibrary 애플리케이션을 사용해보자.


버그가 없다면 위와같은 화면이 나온다.




이 블로그의 인기 게시물

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

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

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