[Spring Authorization Server Sample 따라 구현하기] Resource Server

2024. 9. 23. 00:07Spring Security/Spring Authorization Server

반응형
작년 이맘때 쯤 지금은 운영하지 않는 velog 블로그에 게시글을 옮겨온 글

개요

Resource Server 를 구현한다.

리소스 서버는 OAuth2 프로토콜의 구성 요소 중 하나로, 사용자가 요청한 자원(정보)을 갖고 있는 서버이다.

DB와 통신하는 API 서버 정도로 생각할 수 있을 것 같다.

방법과 구현

구조

실제 API 서버는 이것보다 훨씬 복잡한 구조로 되어 있겠지만, 샘플은 설정 파일 하나와 컨트롤러로 구성된 간단한 모습을 하고 있다.

의존성 관리 - build.gradle

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' 
    implementation 'org.springframework.boot:spring-boot-starter-security' 
    implementation 'org.springframework.boot:spring-boot-starter-web' 
        compileOnly 'org.projectlombok:lombok' 
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' 
    annotationProcessor 'org.projectlombok:lombok' 
}

implementation - 코드 작성부터 런타임까지 계속 관여하겠다.

  • spring-boot-starter-oauth2-resource-server 리소스 서버 구축에 필요한 설정을 담고 있는 스프링 시큐리티 하위 패키지
  • spring-boot-starter-security 스프링 시큐리티 기본 패키지
  • spring-boot-starter-web 웹 서비스 구축을 위한 스프링 부트 기본 패키지

compileOnly - 컴파일 까지만 관여하겠다. (코드만 만들어 주겠다)

  • lombok 스프링 개발에 필요한 각종 툴들을 어노테이션 형태로 제공하는 패지키 (스프링 부트 공식 지원)

developmentOnly - 코스 작성하는 것만 보겠다. (실제 빌드에는 영향을 미치지 않는다)

  • spring-boot-devtools 코드 변경사항이 생기면 자동으로 빌드와 환경을 다시 세팅해주는 툴

annotationProcessor - 그 밖에 어노테이션으로 도움을 주는 것들

  • spring-boot-configuration-processor yml 파일 설정에 자동완성 등을 도와주는 툴 (프로젝트 만들다가 좋아보여서 넣음)
  • lombok compileOnly 에 들어간 롬복과 세트로 들어있는 패키지

어플리케이션 설정 - application.yml

server:
  port: 8090

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: http://localhost:9000
  • server.port: 8090 서버의 포트번호를 8090 으로 설정
  • spring.security.oauth2.resourceserver.jwt.issuer-uri: http://localhost:9000 이 서버는 리소스 서버이며, 인증에 필요한 jwt 토큰은 localhost:9000 에서 받을 것이다.

보안 설정 - SecurityConfig.java

@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
public class SecurityConfig {
    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .authorizeHttpRequests(request -> request
                    .requestMatchers("/messages/**").hasAuthority("SCOPE_message.read"))
                .oauth2ResourceServer(resource -> resource.jwt(Customizer.withDefaults()));
        return httpSecurity.build();
    }
}

Annotation

  • @EnableWebSecurity 스프링 mvc 의 보안 설정을 켜겠다.
  • @Configuration 설정 파일임을 명시한다. Bean 을 등록할 예정이다.
  • @Bean 이것은 빈이다. 스프링 부트에 제어권을 넘길 것이고, 나는 가져다 쓸 수 있다.

SecurityFilterChain

  • authorizeHttpRequests() .. /messages 이하 경로로 들어오는 요청에 대하여는 message.read 권한이 있어야만 한다.
  • oauth2ResourceServer() .. 리소스 서버의 설정을 스프링 부트가 제공하는 기본값으로 둔다.

정보 제공 - MessageController.java

@RestController
public class MessageController {
    @GetMapping("/messages")
    public String[] getMessages() {
        return new String[] {"Message 1", "Message 2", "Message 3"};
    }
}

Annotation

  • @RestController 이것은 Restful API 를 제공하기 위한 컨트롤러이다.
  • @GetMapping 해당 Request 를 Get으로 지정한다.

Method

  • getMessages() Message 1, 2, 3 이 담긴 배열을 반환한다.
    • 리소스 서버에서 얻고자 하는 정보 이다.
    • 실제 리소스는 이것보다 훨씬 다양할 수 있다. 내 정보 보기, 게시판 게시글 조회, 쇼핑몰 상품 조회 등등

실행

Run

application.yml 에서 설정한 8090번 포트로 실행되었다.

Request, Response

Browser

  • http://localhost:8090 연결을 거부하였다는 메시지가 출력된다.

  • http://localhost:8090/messages 401 에러가 발생한다.

Postman

8090, 8090/messages 경로 모두 401 Unauthorized 가 발생한다.

)

Why?

샘플이랑 동일하게 구현했는데 왜 message 1, 2, 3 을 얻을 수 없는가.

그것은 리소스 서버에 구현한 각종 보안 설정들 때문이다.

  • SecurityConfig 에서는
    • 웹 보안 설정을 켰다. 따라서 모든 요청에 대해 인증된(로그인 한) 사용자만 응답을 얻을 수 있다.
    • /messages 로 들어오는 요청에 대해 권한을 요구했다. 따라서 권한이 없으면 응답을 없을 수 없다.
  • application.yml 에서는
    • jwt 토큰의 발급자를 9000 번 포트로 지정했다. 향후 인증 서버의 포트가 될 것이지만, 아직 설정한 것이 없다.

따라서 현재의 리소스 서버는 어떤 요청을 받던 전부 401 을 응답한다.

결론

샘플 중 가장 간단하게 구현된 리소스 서버를 정리하는 데도 시간이 꽤 소비되었다.

Client Server 와 Authorization Server 를 모두 구현한 후에 실행 결과를 볼 수 있을 것이다.

Repository

https://github.com/gigyesik/spring-authorization-server-sample-connect-db/tree/clone

반응형