주제 : 모든 API에 로그인 기능을 적용시키기

 

Why?

  • 연구실 데이터를 CRUD하는 API 인데 아무나 접근할 수 있으면 보안상 문제가 많다고 생각
  • 데이터를 사용하는 연구원들도 Read 이외 생성, 수정, 삭제 기능에 접근 제한을 두는 것이 데이터 관리에 있어서 중요하다고 생각

-> 데이터를 사용하는 연구원들은 Read 기능만 접근가능하게 함

-> 디비 관리자만 모든 기능 접근 가능하게 함

 

How?

  • 모든 연구원들이 회원가입하여 아이디 비번을 생성하고 관리자가 슈퍼user, 일반user를 지정해줘도 되지만 개인 유저가 가지는 큰 의미가 없어 슈퍼user와 일반user 두개의 아이디만 필요하다고 생각 -> 나중에 회원가입 기능이 추가되고 개개인이 갖는 위치데이터 입력시 개인 id를 갖는게 더 유리할 수 있음
  • 쿠키, 세션, JWT 중 JWT 사용
    • 쿠키는 쿠키값 그대로 보내 보안의 문제
    • 세션은 서버에 추가적인 저장소가 필요함
    • 토큰방식은 디비 저장소도 필요없고 로그인시 암호화된 문자열을 보내 보안상 안전함
    • 좀 더 고민해보자
  • 서브모듈 적용하여 application.yml 파일에 있는 보안 정보(디비 정보, jwt secretKey 등) 숨김

 

진행

User Table

  • is_super_user 필드로 슈퍼user와 일반user 구분

 

JWT

  • TokenProvider
    • jwt 생성하고 추출하는 기능
  • LoginInterceptor
    • 컨트롤러에 닿기전에 가로채 로그인이 되어 있는지(제대로된 토큰이 넘어왔는지) 확인하는 기능
  • AuthArgumentResolver
    • 인터셉터 작업이 끝난 뒤 컨트롤러로 갔을때 필요한 토큰 값을 원하는 형태로 받고 싶을때 사용
      • Authentication 어노테이션 → 컨트롤러 아규먼트 어노테이션
      • CurrentUser 클래스 → 아규먼트를 담당하는 클래스
  • WebMvcConfig
    • LoginInterceptor 와 AuthArgumentResolver 를 Bean 으로 등록하고
    • 각각 registry 와 resolvers 에 등록한다

 

서브모듈

  • 보안 정보를 담을 private repository 만들고
  • 본 프로젝트의 서브모듈로 설정함
  • processResources.dependsOn('~~~') 를 사용하여 원하는 위치에 파일을 복사하여 옮김
  • application.yml 에 있는 데이터는 @Value 어노테이션을 사용하여 가져올 수 있다

 

결과

import requests
import json

headers = {'Content-Type': 'application/json; chearset=utf-8'}
data = {'name': '일반유저', 'password': ****}
res = requests.post('http://localhost:8080/login/oauth', data=json.dumps(data), headers=headers)
headers = {'Content-Type': 'application/json; chearset=utf-8', 'Authorization': 'Bearer '+res.json()['accessToken']}

res = requests.get('http://localhost:8080/mobility/getData?offset=0&limit=10&name=omg', headers=headers)
print(str(res.status_code) + " | " + res.text)
  • 연구원들이 주로 파이썬 언어를 사용하기 때문에 파이썬 코드에서 데이터를 가져오는 코드
  • 로그인이 되어 있지 않으면 데이터를 받아올 수 없다

고민

  • 프론트엔드에서 헤더를 설정하는데 어떻게 할까
  • 코드에서 데이터를 받아오는게 나을까? 웹페이지에서 데이터를 다운받아서 쓰는게 나을까? 직접 디비에 연결해서 사용하는게 나을까?

+ Recent posts