복붙노트

[SPRING] access_token : spring boot Oauth2로 리소스에 액세스 할 수 없습니다.

SPRING

access_token : spring boot Oauth2로 리소스에 액세스 할 수 없습니다.

기존 응용 프로그램에서 Oauth2를 구현하려고합니다. 처음에는 스프링 보안을 추가 한 다음 oauth2를 추가하려고했습니다. 구성을 추가 한 후 access_token을 생성 할 수 있었지만 access_token을 사용하여 리소스에 액세스 할 수 없습니다.

여기 내 코드가 있습니다 :

SecurityConfiguration.java

    @Configuration
    @EnableWebSecurity
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private ClientDetailsService clientDetailsService;

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**");
    }

    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/", "/patients").permitAll()
                .antMatchers("/oauth/token").permitAll()
                .anyRequest().authenticated()
                .and().httpBasic();
        http.csrf().disable();
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource)
                .usersByUsernameQuery("select username, password, 1 as enabled from user where username=?")
                .authoritiesByUsernameQuery("select username, authority from authorities where username=?");
    }

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

    @Bean
    public JdbcTokenStore tokenStore() {
        return new JdbcTokenStore(dataSource);
    }

    @Bean
    @Autowired
    public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore) {
        TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
        handler.setTokenStore(tokenStore);
        handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
        handler.setClientDetailsService(clientDetailsService);
        return handler;
    }

    @Bean
    @Autowired
    public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
        TokenApprovalStore store = new TokenApprovalStore();
        store.setTokenStore(tokenStore);
        return store;
    }
}

SecurityOAuth2Configuration.java

@Configuration
@EnableAuthorizationServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Import(SecurityConfiguration.class)
public class SecurityOAuth2Configuration extends AuthorizationServerConfigurerAdapter {
    private static String REALM = "CRM_REALM";
    private static final int ONE_DAY = 60 * 60 * 24;
    private static final int THIRTY_DAYS = 60 * 60 * 24 * 30;

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private UserApprovalHandler userApprovalHandler;

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

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.realm(REALM);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler)
                .authenticationManager(authenticationManager);
    }
}

ResourceServer.java

@Configuration
@EnableResourceServer
public class ResourceServer extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.anonymous().disable()
                .requestMatchers().antMatchers("/patients/**").and().authorizeRequests()
                .antMatchers("/patient/**").access("hasRole('USER')")
                .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
    }

}

이 튜토리얼을 참조 용으로 사용했다.

기본 인증 정보를 사용하여 액세스 토큰을 얻을 수 있습니다.

하지만 리소스를 얻기 위해 동일한 액세스 토큰을 사용하면 실패합니다.

oauth에 필요한 모든 테이블을 추가했습니다. 내가 누락 된 것이 있습니까?

최신 정보:

.and ()를 삭제했습니다. httpBasic (); 과 WebsecurityConfigurerAdapter에서 @Order (3)를 추가하고 security.oauth2.resource.filter-order = 3으로 업데이트 된 속성 파일을 추가했습니다.

이제 오류 발생 {     "타임 스탬프": 1543500350487,     "상태": 403,     "error": "금지됨",     "message": "Access Denied",     "경로": "/ 환자 / 1 /" }

업데이트 2

내 사용자 및 기관 스키마는 다음과 같습니다.

사용자 + ---------- + ----------------- + ------ + ----- + ------- - + ---------------- + | 필드 | 유형 | Null | 키 | 기본 | 추가 | + ---------- + ----------------- + ------ + ----- + ------- - + ---------------- + | 이드 | int (6) 부호 없음 | 아니요 | PRI | NULL | auto_increment | | 사용자 이름 | varchar (50) | 아니요 | UNI | NULL | | | 비밀 번호 | varchar (100) | 아니요 | | NULL | | + ---------- + ----------------- + ------ + ----- + ------- - + ---------------- +

당국 + ----------- + ----------------- + ------ + ----- + ------ --- + ---------------- + | 필드 | 유형 | Null | 키 | 기본 | 추가 | + ----------- + ----------------- + ------ + ----- + ------ --- + ---------------- + | 이드 | int (6) 부호 없음 | 아니요 | PRI | NULL | auto_increment | | 사용자 이름 | varchar (50) | 아니요 | MUL | NULL | | | 권위 | varchar (50) | 아니요 | | NULL | | + ----------- + ----------------- + ------ + ----- + ------ --- + ---------------- +

해결법

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

    1.access () 함수 내부의 문자열 대신 antmatcher에서 직접 hasRole을 사용해야합니다. 그러면 hasRole이 올바로 평가되어 사용자가 요청 된 리소스에 액세스 할 수 있는지 제대로 판단됩니다.

    access () 함수 내부의 문자열 대신 antmatcher에서 직접 hasRole을 사용해야합니다. 그러면 hasRole이 올바로 평가되어 사용자가 요청 된 리소스에 액세스 할 수 있는지 제대로 판단됩니다.

    그러면 ResourceServer.java에 대한 다음 코드가 생성됩니다.

    @Configuration
    @EnableResourceServer
    public class ResourceServer extends ResourceServerConfigurerAdapter {
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.anonymous().disable()
                    .requestMatchers().antMatchers("/patients/**").and().authorizeRequests()
                    .antMatchers("/patient/**").hasRole('USER')
                    .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
        }
    
    }
    
  2. ==============================

    2.먼저 AuthenticationManagerBuilder를 수정하는 두 가지 유사한 메소드가 있습니다.

    먼저 AuthenticationManagerBuilder를 수정하는 두 가지 유사한 메소드가 있습니다.

    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
    

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
    

    둘 다 거기에 이유가 있습니까? 내 설정 에서이 없어.

    또한 쿼리가 제대로 작동하지 않을 수도 있습니다. loaduserbyusername 호출을 처리 할 사용자 서비스를 설정하고 auth 객체를 사용하여 auth 객체를 설정하는 방법에 대한 몇 가지 지침을 따라야합니다. 참고로 : 나는 당신과 같은 AuthenticationManagerBuilder를 설정하지 않았고, 광산이 암호 인코더와 함께 userdetails 서비스를 사용하도록 구성했다.

        auth.userDetailsService(securityUserService)
            .passwordEncoder(passwordEncoders.userPasswordEncoder());
    

    도움이되지 않는 경우 구성 방법은 다음과 같습니다.

    WebSecurityConfigurerAdapter를 확장하는 클래스를 토큰 엔드 포인트와 만 관련되도록 변경하십시오.

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .authorizeRequests()
            .antMatchers("/api/oauth/**").permitAll()
            .and()
        .csrf()
            .disable();
    }
    

    이제 ResourceServerConfigurerAdapter에서 리소스 서버의 구성에 대해 걱정할 필요가 없습니다. AuthenticationManagerBuilder 구성에서 역할을 제대로 올바르게로드하는 경우에만 작동합니다. 다른 사람들이 지적했듯이, Spring은 접두사 ROLE_을 가지고있다. 어떤 이유로 당신은 쿼리를 사용하여 검색하고 있으며, 그들은 당국입니다.

    @Override
    public void configure(HttpSecurity http) throws Exception {
    
        http.csrf().disable()
        .requestMatchers()
            .antMatchers("/api/**")
            .and()
        .authorizeRequests()
            .antMatchers("/api/**").access("hasRole('USER')")
            .and()
        .exceptionHandling()
        .accessDeniedHandler(new OAuth2AccessDeniedHandler());
    
    }
    

    내 AuthServerConfig 파일에 다음 주석이 없습니다.

    @EnableGlobalMethodSecurity(prePostEnabled = true)
    @Import(SecurityConfiguration.class)
    

    필자가 따랐던 자습서와는 다른 방식으로 AuthorizationServerSecurityConfigurer를 구성합니다. 내 것이 다음과 같습니다.

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    
        oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
    }
    

    내 ClientDetailsServiceConfigurer는 여전히 메모리에 있으므로 다른 점이 있습니다. 내 AuthorizationServerEndpointsConfigurer도 약간 다릅니다. 토큰 스토어, 확장 체인 (이 점에 대해 걱정하지 마세요. 추가 정보) 및 authenticationManager 만 추가합니다.

        endpoints
            .tokenStore(tokenStore())
            .tokenEnhancer(tokenEnhancerChain)
            .authenticationManager(authenticationManager);
    
  3. ==============================

    3.나는이 문제가 여러분이 저장 /로드하는 방법이 될 수 있다고 생각합니다. 스프링 보안에는 역할에 대한 기본 접두사 ROLE_가 있습니다. 따라서 DB (저장소)에서 ROLE_FOO로 저장할 필요가 있으며 hasRole ( 'FOO')를 사용할 수 있습니다.

    나는이 문제가 여러분이 저장 /로드하는 방법이 될 수 있다고 생각합니다. 스프링 보안에는 역할에 대한 기본 접두사 ROLE_가 있습니다. 따라서 DB (저장소)에서 ROLE_FOO로 저장할 필요가 있으며 hasRole ( 'FOO')를 사용할 수 있습니다.

    나는 같은 문제를 여기에서 발견했다. 그리고 나의 대답은 문제를 해결하는 것처럼 보였다. https://stackoverflow.com/a/43568599/4473822

    문제가있는 사람도 403 - 금지되어 DB에 올바르게 역할을 저장하면 문제가 해결되었습니다.

    당신은 또한 기본 접두어를 변경할 수 있지만 당신이 봄을 조금 혼란시키지 않는 한 나는 그것을 추천하지 않을 것이다.

  4. ==============================

    4.ResourceServer에서 아래와 같이 코드를 변경하십시오.

    ResourceServer에서 아래와 같이 코드를 변경하십시오.

    다음 행을 살펴보십시오.

    http.anonymous().disable()
                    .requestMatchers().antMatchers("/patients/**","/patient/**")
    

    "/ patient /"**가 요청 일치 자의 일부로 추가되지 않았기 때문에 요청은 실제로 다른 구성에 의해 처리되었습니다

    package project.configuration;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
    import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
    import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
    
    
    @Configuration
    @EnableResourceServer
    public class ResourceServer extends ResourceServerConfigurerAdapter {
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.anonymous().disable()
                    .requestMatchers().antMatchers("/patients/**","/patient/**").and().
                    authorizeRequests().antMatchers("*/patient/**").hasRole("USER")
                    .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
        }
    
    }
    
  5. from https://stackoverflow.com/questions/53537133/unable-to-access-resources-with-access-token-spring-boot-oauth2 by cc-by-sa and MIT license