아카이브

[스프링 기반 REST API 개발] 시큐리티 OAuth2 리소스 서버 설정하기 본문

Spring/스프링 기반 REST API 개발

[스프링 기반 REST API 개발] 시큐리티 OAuth2 리소스 서버 설정하기

주멘이 2021. 1. 9. 21:09

리소스 서버

  • OAuth2 인증 서버와 연동해서 사용한다.
  • 리소스 인증 서버는 리소스를 제공하는 서버와 같이 두고, OAuth2 인증 서버는 따로 분리하는 게 맞다.
  • 리소스에 대한 요청이 들어오면, OAuth2 서버에 access_token이 존재하는지 확인하고 없으면 접근을 제한한다.

ResourceServer 설정

  •  @EnableResourceServer
  •  extends ResourceServerConfigurerAdapter
  •  configure(ResourceServerSecurityConfigurer resources)
    • resource_id
  •  configure(HttpSecurity http)
    •  anonymous
    •  GET /api/** : permit all
    •  POST /api/**: authenticated
    •  PUT /api/**: authenticated
    •  에러 처리
      • accessDeniedHandler(OAuth2AccessDeniedHandler())

ResourceServiceConfig 클래스 추가

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("event");
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .anonymous().and()
                .authorizeRequests().mvcMatchers(HttpMethod.GET, "/api/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler())
        ;
    }
}

 

getBearerToken(), getAccessToken(), 모든 POST /api/** 요청 Test 코드에 token을 넣어주는 코드 작성

    private String getBearerToken(boolean needToCreateAccount) throws Exception {
        return "Bearer " + getAccessToken(needToCreateAccount);
    }

    private String getAccessToken(boolean needToCreateAccount) throws Exception {
        //    Given
        if (needToCreateAccount) {
            createAccount();
        }

        ResultActions perform = this.mockMvc.perform(post("/oauth/token")
                .with(httpBasic(appProperties.getClientId(), appProperties.getClientSecret()))
                .param("username", appProperties.getUserUsername())
                .param("password", appProperties.getUserPassword())
                .param("grant_type", "password")
        );
        return (String) new Jackson2JsonParser().parseMap(perform.andReturn().getResponse().getContentAsString()).get("access_token");

    }
    
    @Test
    @DisplayName("이벤트를 정상적으로 수정하기")
    void updateEvent() throws Exception {
        // Given
        Account account = this.createAccount();
        Event event = this.generateEvent(200, account);

        EventDto eventDto = this.modelMapper.map(event, EventDto.class);
        String eventName = "Updated Event";
        eventDto.setName(eventName);

        // When & Then
        this.mockMvc.perform(put("/api/events/{id}", event.getId())
                .header(HttpHeaders.AUTHORIZATION, getBearerToken(false))
                .contentType(MediaType.APPLICATION_JSON)
                .content(this.objectMapper.writeValueAsString(eventDto))
        )
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(jsonPath("name").value(eventName))
                .andExpect(jsonPath("_links.self").exists())
        ;
    }