복붙노트

[SPRING] 스프링 부트 REST 애플리케이션을 사용하는 OAuth2 - 토큰을 사용하여 리소스에 액세스 할 수 없음

SPRING

스프링 부트 REST 애플리케이션을 사용하는 OAuth2 - 토큰을 사용하여 리소스에 액세스 할 수 없음

내 REST 봄 부팅 프로젝트에 OAuth2를 사용하고 싶습니다. 몇 가지 예제를 사용하여 OAuth2에 대한 구성을 만들었습니다.

@Configuration
public class OAuth2Configuration {

    private static final String RESOURCE_ID = "restservice";

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends
          ResourceServerConfigurerAdapter {

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) {
            // @formatter:off
            resources
                    .resourceId(RESOURCE_ID);
            // @formatter:on
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {
            // @formatter:off
            http
                    .anonymous().disable()
                    .authorizeRequests().anyRequest().authenticated();
            // @formatter:on
        }

    }

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends
             AuthorizationServerConfigurerAdapter {

        private TokenStore tokenStore = new InMemoryTokenStore();

        @Autowired
        @Qualifier("authenticationManagerBean")
        private AuthenticationManager authenticationManager;

        @Autowired
        private UserDetailsServiceImpl userDetailsService;

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints)
            throws Exception {
          // @formatter:off
          endpoints
                  .tokenStore(this.tokenStore)
                  .authenticationManager(this.authenticationManager)
                  .userDetailsService(userDetailsService);
          // @formatter:on
        }

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            // @formatter:off
            clients
                  .inMemory()
                  .withClient("clientapp")
                  .authorizedGrantTypes("password", "refresh_token", "trust")
                  .authorities("USER")
                  .scopes("read", "write")
                  .resourceIds(RESOURCE_ID)
                  .secret("clientsecret")
                  .accessTokenValiditySeconds(1200)
                  .refreshTokenValiditySeconds(3600);
            // @formatter:on
        }

        @Bean
        @Primary
        public DefaultTokenServices tokenServices() {
            DefaultTokenServices tokenServices = new DefaultTokenServices();
            tokenServices.setSupportRefreshToken(true);
            tokenServices.setTokenStore(this.tokenStore);
            return tokenServices;
        }
    }
}

이것은 내 SecurityConfiguration 클래스입니다.

@Configuration
@EnableWebSecurity
@Order(1)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http
                .authorizeRequests().antMatchers("/api/register").permitAll()
                .and()
                .authorizeRequests().antMatchers("/api/free").permitAll()
                .and()
                .authorizeRequests().antMatchers("/oauth/token").permitAll()
                .and()
                .authorizeRequests().antMatchers("/api/secured").hasRole("USER")
                .and()
                .authorizeRequests().anyRequest().authenticated();
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}

2 가지 간단한 요청으로 신청서를 확인하려고했습니다.

@RequestMapping(value = "/api/secured", method = RequestMethod.GET)
public String checkSecured(){
    return "Authorization is ok";
}

@RequestMapping(value = "/api/free", method = RequestMethod.GET)
public String checkFree(){
    return "Free from authorization";
}

먼저 두 가지 요청을 확인했습니다.

/ api / free 리턴 된 코드 200 및 문자열 "Free from authorization"

/ api / secured returned { "timestamp": 1487451065106, "status": 403, "error": "금지됨", "메시지": "액세스가 거부되었습니다", "경로": "/ api / secured"}

그리고 그것은 그들이 잘 작동하는 것 같습니다.

그런 다음 액세스 토큰을 얻습니다 (내 사용자 데이터베이스의 자격 증명 사용).

/ oauth / token? grant_type = password & username = 이메일 비밀번호 = 이메일

응답:

{ "access_token": "3344669f-c66c-4161-9516-d7e2f31a32e8", "token_type": "bearer", "refresh_token": "c71c17e4-45ba-458c-9d98-574de33d1859", "expires_in": 1199, "범위" : "읽기 쓰기"}

그런 다음 인증이 필요한 리소스에 대한 요청 (토큰과 함께)을 보내려고했습니다.

/ api / secured? access_token = 3344669f-c66c-4161-9516-d7e2f31a32e8

응답은 다음과 같습니다.

{ "타임 스탬프": 1487451630224, "상태": 403, "오류": "금지됨", "메시지": "액세스가 거부되었습니다", "경로": "/ api / 보안 됨"}

나는 왜 접근이 거부되는지 이해할 수 없다. 구성에 확신이 없으며 잘못된 것으로 보입니다. 또한 WebSecurityConfigurerAdapter를 확장하는 클래스의 configure (HttpSecurity http) 메서드와 ResourceServerConfigurerAdapter를 확장하는 메서드의 관계를 명확하게 이해하지 못합니다. 어떤 도움을 주셔서 감사합니다!

해결법

  1. ==============================

    1.스프링 부트 1.5.1을 사용하거나 최근에 업데이트 한 경우 스프링 보안 oauth2 (스프링 부트 1.5 릴리스 노트)에 대한 필터 순서가 변경되었습니다.

    스프링 부트 1.5.1을 사용하거나 최근에 업데이트 한 경우 스프링 보안 oauth2 (스프링 부트 1.5 릴리스 노트)에 대한 필터 순서가 변경되었습니다.

    릴리스 정보에 따르면, 다음 필터를 application.properties /yml에 추가하려고하면 다른 필터 다음에 리소스 서버 필터가 대체로 사용됩니다. 이렇게하면 리소스에 들어가기 전에 승인을 받아야합니다 섬기는 사람:

    security.oauth2.resource.filter-order = 3
    

    다른 질문에 대한 답변은 https://stackoverflow.com/questions/28537181에서 확인할 수 있습니다.

  2. from https://stackoverflow.com/questions/42320756/oauth2-with-spring-boot-rest-application-cannot-access-resource-with-token by cc-by-sa and MIT license