자동 환경 설정과 Spring Environment 및 다른 Spring 프로그래밍 모델 관념의 바인딩을 바탕으로 Spring Boot 어플리케이션을 위한 Netflix OSS(Open Source Software) 통합을 제공합니다. 몇 가지 간단한 어노테이션을 사용하여 어플리케이션 내부의 공통 패턴을 신속하게 사용하고 설정할 수 있습니다. 그리고 battle-tested를 거친 Netflix component를 통해 대규모 분산 시스템을 구축할 수 있습니다.
API를 통해 특정 시스템의 보호된 자원에 접근하기 위해서는 해당 시스템의 사용자 인증 정보(아이디, 패스워드)를 알고 있어야 합니다. 시스템 차원에서 다른 시스템의 보호된 자원에 접근하기 위해 그 시스템의 사용자 인증 정보를 관리하고 이 정보를 사용하는 것은 보안상 많은 문제들을 유발할 수 있습니다. 이런 문제들이 발생하지 않도록 API 접근을 위임하여 인증을 처리하는 방법을 사용할 수 있습니다.
많은 서비스 제공자(Google, Yahoo, AOL 등)들이 이런 인증 방식을 별도로 구현하여 사용하였습니다. 이렇게 구현된 결과들은 서로 조금씩 다르고 서로 호환되지 않았는데 이를 통일하기 위해 OAuth 1.0 표준안을 만들었습니다.
OAuth 1.0 발표 이후 몇 년 동안 사용하면서 커뮤니티는 아래와 같은 단점들에 대해 고민하였고 그 결과 OAuth 2(이후 ‘OAuth’로 명명)를 표준으로 정리하였습니다.
암호화 요구사항의 복잡성
웹 기반 애플리케이션만 지원
성능 확장에 어려움
1. OAuth 역할들(Roles)
OAuth에서 위임 방식의 인가를 처리하기 위해 4 개의 역할들을 정의하고 있으며 이들은 아래 표와 같습니다.
역할설명
자원 서버 (Resource Server)
자원 서버는 보호된 정보를 제공하는 서버로 일반적으로 웹 애플리케이션입니다.
자원 소유자 (Resource Owner)
자원 소유자는 자원 서버에 계정을 가지고 있는 사용자로 클라이언트가 그들의 계정을 통해 자원 서버에 접근하는 것을 인가(authorize)합니다.
클라이언트 (Client)
클라이언트는 자원 소유자를 대신하여 자원 서버의 서비스를 사용하고자 하는 애플리케이션입니다.
인가 서버 (Authorization Server)
인가 서버는 클라이언트가 자원 서버의 서비스를 사용할 때 사용하는 접근 토큰(Access Token)을 발행합니다.
2. 인가 승인 유형(Authorization Grant Types)
클라이언트가 접근 토큰을 요청하기 위해서는 자원 소유자의 인가를 받아야 하는데 OAuth는 서로 다른 용도를 위해 다양한 인가 승인 유형을 제공합니다. OAuth에서 정의한 4가지 인가 승인 유형은 아래와 같습니다.
인가 승인 유형용도비고
인가 코드 승인 (Authorization Code)
웹 서버 상에서 동작하는 애플리케이션
가장 많이 사용되는 유형
암시적 승인 (Implicit)
모바일 앱 또는 단말기에서 동작하는 웹 애플리케이션
자원 소유자 패스워드 승인 (Resource Owner Password)
단말기 OS 또는 높은 신뢰 관계의 애플리케이션
다른 유형들을 사용할 수 없는 경우에만 사용
클라이언트 인증 정보 승인 (Client Credentials)
애플리케이션 API 접근
신뢰하는 클라이언트만 사용
2.1. 인가 코드 승인(Authorization Code Grant)
인가 코드 승인 방식은 HTTP 리다이렉션 기반 흐름이어서 클라이언트는 자원 소유자의 웹 브라우저와 상호작용할 수 있어야 하며 인가 서버로부터의 요청을 처리할 수 있어야 합니다. 승인 흐름은 아래 그림과 같습니다.
클라이언트가 사용자 에이전트를 인가 서버로 리다이렉트 함으로써 흐름을 시작합니다. (상태(State) 값과 인가 서버로부터 응답을 수신할 Redirect URI 포함)
유효한 인증 이력이 없는 인증 요청에 대해 인가 서버는 로그인 페이지로 응답합니다.
자원 소유자는 인가 서버의 인증을 통해 클라이언트를 인가합니다.
인가 서버는 정상적인 자원 소유자의 인증/인가 요청을 클라이언트로 리다이렉트 합니다. (인가 코드, 상태 값 포함)
인가 코드를 포함한 요청을 받은 클라이언트는 인가 서버로 접근 토큰 요청을 전송하여 그 결과로 접근 토큰을 획득합니다. (인가 코드, 클라이언트 인증 정보 포함)
이 방식은 위 그림에서 볼 수 있듯이 클라이언트의 인증 과정을 거치고 인가 서버와 클라이언트 간에만 접근 토큰이 포함된 통신을 수행하는 등 보안 상 많은 이점을 포함하고 있습니다.
3. 로그인 시나리오
SSO 구성 환경에서 SSO 처리 시나리오는 아래 그림과 같습니다.
한 시스템을 통해 로그인한 사용자가 다른 시스템의 인증이 요구되는 페이지를 요청하면 해당 시스템은 이 요청을 SSO 서버로 리다이렉트 합니다.
유효한 인증 이력이 있는 요청에 대해 SSO 서버는 이 요청을 시스템으로 리다이렉트 (인가 코드 포함)합니다.
인가 코드를 포함한 요청을 받은 시스템은 SSO 서버로부터 접근 토큰과 사용자 정보를 획득하여 해당 사용자의 로그인 처리를 한 후 원래 요청의 결과로 응답합니다.
4. 로그아웃 시나리오
로그인한 사용자가 SSO 환경에서 로그아웃 시 처리 과정은 아래 그림과 같습니다.
로그인한 사용자가 한 시스템에게 로그아웃을 요청하면 시스템은 이 요청을 SSO 서버의 로그아웃 페이지로 리다이렉트 합니다.
로그아웃 요청을 받은 SSO 서버는 해당 사용자로 로그인된 모든 시스템에게 로그아웃을 요청합니다.
[스프링부트] jar, war 내에서 ResourceUtil.getFile() 사용시 FileNotFoundException 발생
//XML 파일의 내용을 가져온다.
XmlMapper xmlMapper = new XmlMapper();
File file = ResourceUtils.getFile(replicationXmlFilePath);
if (!file.exists()) {
throw new Exception("replication.xml is Not File..");
}
List<DBInfo> dbInfoList = xmlMapper.readValue(file, xmlMapper.getTypeFactory().constructCollectionType(List.class, DBInfo.class));
[ERROR](org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler:95) Unexpected error occurred in scheduled task.
java.io.FileNotFoundException: class path resource [replication.xml] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/home/service/App.war!/WEB-INF/classes!/replication.xml
at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:215)
at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:53)
at com.MonitoringJob.execute(MonitoringJob.java:69)
at com.JobConfiguration.monitoringJob(JobConfiguration.java:210)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Intellij 에서는 Path의 문제가 없었지만 war 내에서는 문제가 생긴다.
//XML 파일의 내용을 가져온다.
XmlMapper xmlMapper = new XmlMapper();
ClassPathResource classPathResource = new ClassPathResource(replicationXmlFilePath);
List<DBInfo> dbInfoList = xmlMapper.readValue(classPathResource.getInputStream(), xmlMapper.getTypeFactory().constructCollectionType(List.class, DBInfo.class));
Maven Scope 정리 pom.xml에서 상용되는 scope에 대한 정리 ※compile - 아무런 scope를 명시하지 않았을때 사용되는 기본값. - 테스트 및 런타임에도 classpath에포함된다. ※provied - JDK 또는 컨테이너에 의해서 runtime에 제공되는 모듈 - 이 scope는 이미 컨테이너가 해당 라이브러리를 제공하고 있을때 유용 그러므로 실제로 배포시에 제외대상 - 예를 들면 아래 servlet api의 경우 이미 웹서버에서 제공하고 있는 경우에 maven scope를 provied로 기재
※runtime - 런타임시 필요하지만 컴파일시에 필요하지 않는 경우에 사용 - 테스트와 런타임에는 사용 되지만 컴파일시에 사용 되지 않음 - 대표적 예로 JDBC Driver