[SPRING] access_token : spring boot Oauth2로 리소스에 액세스 할 수 없습니다.
SPRINGaccess_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.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.먼저 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.나는이 문제가 여러분이 저장 /로드하는 방법이 될 수 있다고 생각합니다. 스프링 보안에는 역할에 대한 기본 접두사 ROLE_가 있습니다. 따라서 DB (저장소)에서 ROLE_FOO로 저장할 필요가 있으며 hasRole ( 'FOO')를 사용할 수 있습니다.
나는이 문제가 여러분이 저장 /로드하는 방법이 될 수 있다고 생각합니다. 스프링 보안에는 역할에 대한 기본 접두사 ROLE_가 있습니다. 따라서 DB (저장소)에서 ROLE_FOO로 저장할 필요가 있으며 hasRole ( 'FOO')를 사용할 수 있습니다.
나는 같은 문제를 여기에서 발견했다. 그리고 나의 대답은 문제를 해결하는 것처럼 보였다. https://stackoverflow.com/a/43568599/4473822
문제가있는 사람도 403 - 금지되어 DB에 올바르게 역할을 저장하면 문제가 해결되었습니다.
당신은 또한 기본 접두어를 변경할 수 있지만 당신이 봄을 조금 혼란시키지 않는 한 나는 그것을 추천하지 않을 것이다.
-
==============================
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()); } }
from https://stackoverflow.com/questions/53537133/unable-to-access-resources-with-access-token-spring-boot-oauth2 by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 찾을 수없는 'org.hibernate.SessionFactory'유형의 bean이 필요합니다. (0) | 2019.02.23 |
---|---|
[SPRING] 스프링 레스트 컨트롤러 : 유효성을 선택적으로 끄는 방법 (0) | 2019.02.23 |
[SPRING] 하나의 Service 메소드는 Spring 트랜잭션을위한 내부 다중 메소드를 호출한다. (0) | 2019.02.23 |
[SPRING] Spring 컨텍스트에서 Maven settings.xml 속성 사용하기 (0) | 2019.02.23 |
[SPRING] 유닛 테스트 결과 : HsqlException 사용자에게 권한이 없거나 객체를 찾을 수 없음 : ROWNUM (0) | 2019.02.23 |