기본 콘텐츠로 건너뛰기

[Angular] 라이선스 웹페이지 구축

 라이선스 웹페이지 구축에 Angular를 선택한 이유는 나름 최신 기술이고 구글에서 관리하는 프레임워크라 믿을 수 있다는 점 그리고 컴포넌트 기반이라 코드의 재사용이 가능하다는 점 때문이었습니다.
또한 Angular는 TypeScript라는 JavaScript의 상위 언어를 사용하고 있습니다.

Angular외에 React라는 JavaScript 기반의 라이브러리도 있습니다.
둘의 차이점은 아래 표에서 확인해 보세요.


라이선스 웹페이지

구축하려는 웹페이지는 다음과 같은 기능이 필요했습니다.

  1. 만료 기한 설정
  2. 같은 토큰으로 여러 대의 PC에서 사용 불가
  3. 사용자 등록 및 삭제
이러한 요구 사항에 대응하기 위해 JWT(Jason Web Token)을 이용하여 사용자 접근 제한 로직을 구현하였습니다.
JWT의 구조는 다음과 같습니다.
크게 3 부분으로 이루어져있으며 각 부분은 점(.)로 분리됩니다.
header 부분은 토큰 타입과 암호화 해시 알고리즘이 담겨 있고, payload에는 클레임을 담고 있으며 클레임은 "name/value" 형식의 데이타로 구성됩니다. payload는 여러개의 클레임을 담을 수 있습니다. 당연히 클레임이 갯수가 많을수록 토큰의 크기는 커집니다.
signature는 secret key로 암호화 되어 있습니다.
JWT 토큰을 디코딩해보면 header와 payload가 그대로 노출되어 있는 것을 확인할 수 있습니다. 당연히 암호와 같은 민감한 정보는 담지 말아야 합니다.

누군가가 노출된 데이타를 이용하여 JWT 토근을 생성하여 서버에 접근을 요청하면 JWT 토큰을 디코딩 시 아마도 오류가 발생하게 됩니다. 이것은 서버가 가지고 있는 secret key와 새롭게 JWT 토큰 생성할때 사용한 secret key가 다르기 때문입니다.
이렇게 토큰의 위조를 방지할 수 있습니다.
만일 secret key가 노출되었다면 이제껏 발행한 토큰들을 무효화하고 새롭게 토큰들을 발행해야만 하는 불상사가 발생하게 됩니다.

만료 기한은 JWT의 Expired Time을 통하여 구현하였고 "여러 대의 PC에서 사용 불가" 항목은 PC의 랜카드의 맥주소를 등록하여 해결하였습니다.
라이선스 등록 화면

만료 기한을 넘겼을 경우에는 JWT 토큰을 디코딩할때 오류가 발생합니다.

요즘 PC에는 이더넷과 무선 랜 둘 다 가지고 있는 경우가 많기 때문에 라이선스 웹에 접속하는 랜의 맥주소가 바뀔 수 있습니다.
예를 들어 이더넷의 맥주소를 등록하고서 무선랜으로 라이선스 웹에 접속하면 맥주소가 달라 라이선스를 획득할 수 없습니다. 이때는 이더넷과 무선 랜 둘 다 맥주소를 등록해야 합니다.

아래는 클라이언트 프로그램에서 라이선스 인증 절차입니다.
클라이언트에서는 발급받은 토큰의 맥주소와 인터넷에 접근 가능한 랜 카드의 맥주소를 비교하여 프로그램 실행 여부를 결정합니다.
맥주소가 같다면 토큰을 서버로 보내어 인증을 받습니다. 서버에서는 만료 날짜와 등록된 사용자인지(등록 후 삭제되지 않았는지) 확인합니다.

만료 날짜를 넘겼을 경우에는 새로운 토큰을 발행하여 사용자에게 전달해야 합니다.
이 부분이 불편하다면 자동으로 새로운 토큰을 발행하는 방법을 고민해 보는 것도 좋을것 같습니다.

댓글

이 블로그의 인기 게시물

80040154 오류로 인해 CLSID가 {xxxx-...}인 구성 요소의 COM 클래스 팩터리를 검색하지 못했습니다.

원문보기 .NET 으로 만든 응용프로그램에서 com 객체를 호출한 경우 Windows7 64bit 에서 제목과 같은 에러가 발생했다. Win32 COM 과 .NET 프로그램간의 호환성 때문에 생긴 문제였다. 원인은 .NET 실행시 JIT 컴파일러에 의해 최적화된 기계어로 변환되기 때문.. Win32 COM은 컴파일시.. Win32 COM에 맞춰 빌드 속성에서 하위버전으로 맞춰 컴파일을 다시하는 방법도 있지만 메인 프로젝트가 .NET이라면 참조되는 모든 프로젝트를 다 바꿔야할 노릇.. 또 다른 방법은 COM+를 이용하여 독립적으로 만드는 것이다. 분리시키는 방법은 아래 주소해서 확인할 수 있다. http://support.microsoft.com/kb/281335 나의 경우는 Win32 COM DLL을 64비트 .NET 프로그램에서 참조하니 COM 객체를 제대로 호출하지 못하였습니다. 그래서 .NET 프로그램의 Target Machine을 x86으로 설정하니 제대로 COM 객체를 호출하였습니다.

[Pyinstaller] 실행 파일 관리자 권한 획득하기

고객사에서 일부 사용자에게서 프로그램 오류가 발생한다며 아래와 같이 에러 캡처를 보내왔습니다. 프로그램에서 로그를 남기기 위해 로그 파일을 생성하는데 권한의 문제로 로그 파일을 생성하지 못해 프로그램 오류가 발생한 것 같습니다. 처음에는 Python 코드에서 관리자 권한을 요청하는 코드를 넣으려고 했는데, 실제로 Stackoverflow를 찾아보면 이런 내용이 나옵니다. 프로그램이 관리자 권한으로 실행되지 않았다면 관리자 권한으로 다시 프로그램을 실행시키는 코드입니다. import os import sys import win32com.shell.shell as shell ASADMIN = 'asadmin' if sys.argv[-1] != ASADMIN: script = os.path.abspath(sys.argv[0]) params = ' '.join([script] + sys.argv[1:] + [ASADMIN]) shell.ShellExecuteEx(lpVerb='runas', lpFile=sys.executable, lpParameters=params) sys.exit(0) 하지만 개인적으로 이런 방식은 마음에 들지 않았고 조금 더 찾아보니 Pyinstaller로 exe 파일을 만들 때 옵션을 설정하여 관리자 권한을 요청하도록 할 수 있다고 합니다. --uac-admin을 옵션에 추가하면 프로그램 실행 시 관리자 권한을 요청할 수 있습니다. pyinstaller.exe --uac-admin sample.py 하지만 안타깝게도 이 방식은 원하는 대로 동작하지 않았습니다. 마지막으로 manifest 파일을 이용하여 시도해보았습니다. spec 파일을 이용하여 pyinstaller로 빌드하면 <실행 파일 이름>.manifest 라는 파일이 생성됩니다. 파일에서 아랫부분을 찾아볼 수 있습니다. <security> <re

초간단 프로그램 락 걸기

프로그램에 락을 걸 일이 생겨났다. 하드웨어 락을 걸면 쉬울텐데 그 정도는 아니고 프로그램의 실행 날짜를 제한 해 달라고 한다. 그래서 파일(license.lic)을 가지고 락을 걸리고 결정을 했다. 요구 사항은 아래와 같다. 1. license.lic 파일이 없으면 프로그램을 실행 할수 없게 한다. 2. 지정한 날짜를 넘어서는 프로그램을 실행 할수 없게 한다. 3. 사용자가 시스템 날짜를 되돌렸을때 인식하여 프로그램을 실행 할수 없게 한다. 음.... 1.번 문제는 사용자가 프로그램을 실행하기 위해서 license.lic 파일을 받아야만 한다. license.lic 파일에는 최근 실행 날짜/종료날짜 이런식으로 적도록 한다.(물론 내용은 암호화 한다.) 최근 실행날짜는 프로그램이 실행때마다 업데이트 하도록 하고 시스템 날짜와 비교하여 시스템 날짜가 최근 실행 날짜보다 이전의 날짜면 시스템 날짜를 되돌렸다고 인식하도록 한다.(3.번 문제 해결) 시스템 날짜와 종료 날짜를 비교하여 시스템 날짜가 종료 날짜를 넘으면 프로그램을 실행 할수 없도록 한다.(2.번 문제 해결)