[SPRING] 스프링 보안 OAuth2에서 커스텀 userDetailsService 주입 문제
SPRING스프링 보안 OAuth2에서 커스텀 userDetailsService 주입 문제
나는 봄 보안 OAuth2 2.0.7.RELEASE를 사용하고있다. ORM을 사용하여 데이터베이스에 연결하고 기본 JdbcUserDetailsManager는 jdbc를 사용하므로 내 자신의 UserDetailsService를 구현하려고했습니다.
@Service
public class UserService
implements UserDetailsService {
@Override
public UserDetailsService loadUserByUsername(String username) throws UsernameNotFoundException {
// I tested this logic and works fine so i avoid this lines
return userDetailsService;
}
}
게다가, 나는 다음과 같이 권한 스키마를 수정했다 :
mysql> describe authorities;
+--------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------------+------+-----+---------+----------------+
| authority_id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| user_id | bigint(20) unsigned | NO | MUL | NULL | |
| authority | varchar(256) | NO | | NULL | |
+--------------+---------------------+------+-----+---------+----------------+
다음 나는이 같은 사용자 지정 userDetailsService 주입 오전 :
@Configuration
@Import(OAuth2SupportConfig.class)
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends
AuthorizationServerConfigurerAdapter {
...
@Autowired
private UserDetailsService userDetailsService
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore).tokenServices(tokenService);
endpoints.userDetailsService(userDetailsService); // Inject custom
endpoints.authorizationCodeServices(authorizationCodeServices);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients)
throws Exception {
clients.jdbc(dataSource);
}
}
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public class AuthenticationManagerConfiguration
extends GlobalAuthenticationConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
private UserDetailsService userService;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(this.dataSource).and().userDetailsService(this.userService);// Inject custom
}
}
grant_type = password로 / oauth / token 요청을 보내면이 오류가 발생합니다.
POST /oauth/token HTTP/1.1
Host: localhost:8080
Authorization: Basic aW5kaXJhOnNlY3JldA==
Cache-Control: no-cache
Postman-Token: c89baf37-8ad2-4270-5251-9715bfab470a
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=user&password=pass
(여기서 clientId 및 clientSecret은 인코딩 됨)
{
"error": "unauthorized",
"error_description": "PreparedStatementCallback; bad SQL grammar [select username,authority from authorities where username = ?]; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'username' in 'field list'"
}
분명히 여전히 기본 JdbcDaoImpl을 사용하고 있습니다. 사실, 내가 디버깅을 시작했을 때, 나는 다음 단계를 따르고 있음을 발견했다.
왜 이런 일이 일어나는지 모르겠습니다. 나에게 벌레처럼 들린다. 뭐가 잘못 됐니?
해결법
-
==============================
1.userDetailsService (this.userService); // 사용자 정의를 삽입하고 여기서 두 개의 인증 관리자를 작성합니다. 하나는 기본 JdbcDaoImpl 및 dataSource를 가리키는 속성입니다. this.dataSource 및 사용자 정의 userService를 사용하여 다른. auth.userDetailsService (this.userService)를 넣으십시오. (userService가 이미 autowired 된 jdbc를 가지고 있기를 바랍니다.)
userDetailsService (this.userService); // 사용자 정의를 삽입하고 여기서 두 개의 인증 관리자를 작성합니다. 하나는 기본 JdbcDaoImpl 및 dataSource를 가리키는 속성입니다. this.dataSource 및 사용자 정의 userService를 사용하여 다른. auth.userDetailsService (this.userService)를 넣으십시오. (userService가 이미 autowired 된 jdbc를 가지고 있기를 바랍니다.)
여기에서 .and ()는 jdbcAuthentication ()을 구성하지 않고 인증 관리자에 다른 인증 구성을 추가하는 데 사용됩니다.
-
==============================
2.2.0.7에서 권한 부여 유형이 / oauth / token 인 POST / GET 요청을 암호로 사용하면 실제로는 ClientDetailsUserDetailsService를 제외하고 UserDetailsService는 제외됩니다.
2.0.7에서 권한 부여 유형이 / oauth / token 인 POST / GET 요청을 암호로 사용하면 실제로는 ClientDetailsUserDetailsService를 제외하고 UserDetailsService는 제외됩니다.
나는 비슷한 문제가 있었는데 이것이 어떻게 해결 했는가?
public class AppClientDetailsUserDetailsService extends ClientDetailsUserDetailsService { public AppClientDetailsUserDetailsService(ClientDetailsService clientDetailsService) { super(clientDetailsService); } } public class AppConsumerDetailsService implements ClientDetailsService { public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { //some logic } } <http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="authenticationManager" entry-point-ref="entryPoint" xmlns="http://www.springframework.org/schema/security" > <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" /> <anonymous enabled="false" /> <http-basic entry-point-ref="entryPoint" /> <custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" /> </http> <bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter"> <property name="authenticationManager" ref="authenticationManager" /> </bean>
authenticationManager는 생성자 인수가 AppConsumerDetailsService 인 AppClientDetailsUserDetailsService에 대한 bean입니다.
-
==============================
3.문제는 기본 JdbcDaoImpl을 사용하고 있다는 것입니다. 문제를 일으키는 검색어는
문제는 기본 JdbcDaoImpl을 사용하고 있다는 것입니다. 문제를 일으키는 검색어는
public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY = "select username,authority " + "from authorities " + "where username = ?";
이것은 JdbcDaoImpl 내부의 userName에 의해 사용자에 대한 모든 권한을로드하는 기본 조회로 사용됩니다. 따라서 여전히 기본 JdbcDaoImpl을 사용하려는 경우 - 테이블을 사용하여 작업을 수행하는 사용자 정의 쿼리를 매개 변수로 설정할 수 있습니다.
사용자의 스키마가 무엇인지 잘 모르겠지만 다음과 같이해야합니다 (프로그래밍 방식으로 JdbcDaoImpl bean을 구성하는 경우).
String query = "select username,authority " + "from authorities join users on users.id = authorities.user_id " + "where users.username = ?"; jdbcDaoImpl.setAuthoritiesByUsernameQuery(query);
또는 XML에서 JdbcDaoImpl을 생성하는 경우 :
<bean id="userDetailsService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl"> <property name="authoritiesByUsernameQuery" value="select username,authority from authorities join users on users.id = authorities.user_id where users.username = ?"/> </bean>
스키마에 맞게 다른 기본 쿼리가있을 수도 있습니다. JdbcDaoImpl 내부에서 살펴보십시오.
기본 JdbcDaoImpl에서 너무 멀어지기 시작하면 UserDetailsService 구현을 직접 작성할 수도 있습니다.
from https://stackoverflow.com/questions/31683166/problems-injecting-custom-userdetailsservice-in-spring-security-oauth2 by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] WebSphere 7의 Spring (JSR 330 annotations)에 대한 종속성 삽입이 작동하지 않습니다. (0) | 2019.05.18 |
---|---|
[SPRING] CXF 내의 JAX-RS REST 리소스에서 CXF 메시지 교환에 액세스하는 방법이 있습니까? (0) | 2019.05.18 |
[SPRING] 스프링에서 인스턴스화에 대한 자동 와이어 링 (0) | 2019.05.17 |
[SPRING] JerseyTest에서 Spring-Jersey 응용 프로그램에 대한 자원 모델 유효성 검증 실패 (0) | 2019.05.17 |
[SPRING] Jpa 및 Hibernate는 DB에서 비동기 적으로 변경되는 데이터를로드합니까? (0) | 2019.05.17 |