Spring Boot Project에 OauthServer를 설정해보았다.
소스는 https://github.com/blusky10/study_spring 의 simple-spring-oauth 브랜치를 다운로드 받으면 된다.
Client 는 private이라는 api에 접근하기 위해서 oauthserver 에 token 발급 요청을 한다.
발급된 token을 가지고 private이라는 api에 접근한다.
(Client 는 미리 등록되어있다고 가정한다. 따라서 Client를 Oauth서버에 등록하는 과정은 생략된다.)
1. 먼저 ResourceServer를 설정한다. ResourceServer는 Resource Owner의 정보를 가지고 있는 서버를 의미한다.
1
2
3
4
5
6
7
8
9
10
11
|
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter{
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/private").authenticated();
}
}
|
cs |
"/" 주소로 오는 url은 모두 허용하게 되지만 "/private"으로 접근 되는 url은 인증이 필요하다.
2. 두번째로 Authserver를 설정한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("myclient")
.authorizedGrantTypes("client_credentials", "password")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read", "write", "trust")
.resourceIds("oauth2-resource")
.accessTokenValiditySeconds(500)
.secret("secret");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
|
cs |
중간에 보이는 client를 설정하는 부분을 보면 "myclient"는 client의 이름을 나타낸다. 그리고 secret은 client에게 발급되는 비밀번호이다. Facebook 과 같은 곳에서 인증을 하게 되면 client를 따로 등록하게 되는데 이때 등록을 하게 되면 Client 고유의 비밀번호를 발급받게 된다. 이 번호는 절대로 노출되어서는 안된다. 지금 내가 만드는 서버는 myclient라는 client가 등록되어있고 그 client 에게 발급된 비밀번호는 secret이라고 생각하면 된다.
접근할수 있는 client의 role은 "client" 이다.
3. AuthenticationManager를 이용해서 userDetailService를 재정의 해준다.
1
2
3
4
5
6
7
8
9
10
|
@Autowired
public void authenticationManager(AuthenticationManagerBuilder builder, AccountService accountService) throws Exception{
builder.userDetailsService(new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return new CustomUserDetails(accountService.get(username));
}
});
}
|
cs |
여기에 Parameter로 받는 AccoutService는 사용자를 조회하는 서비스이다. 그런데 여기에서 UserDetailServiced의 loadUserByUsername 메소드는 UserDetails 를 리턴해야 하기 때문에 UserDetails를 재정의 해줘야 한다. 그게 바로 CustomUserDetails 이다. accountService.get(username) 하면 Account 객체를 리턴해주고 그 Account 객체가 가지고 있는 정보를 UserDatails 에 셋팅해준다.
4. CustomUserDetails
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public class CustomUserDetails implements UserDetails {
private String username;
private String password;
Collection<? extends GrantedAuthority> authorities;
public CustomUserDetails(Account account) {
this.username = account.getLoingId();
this.password = account.getPassword();
List<GrantedAuthority> authorityList = new ArrayList<>();
for (Role role : account.getRoles()){
authorityList.add(new SimpleGrantedAuthority(role.getName().toUpperCase()));
}
this.authorities = authorityList;
}
// Getter, Setter 생략
}
|
cs |
Custom UserDetails 생성자에서 받은 Account 객체로 username, password, Role 정보를 설정해준다.
이제 Test를 해보자.
인증이 필요없는 URL
인증이 필요한 URL
인증이 필요없는 URL 은 상관 없지만 /private으로 호출을 하면 error 가 나온다. 인증되지 않은 User가 접근을 했기 때문이다.
/oauth/token URL 로 인증토큰 발급 요청을 한다. 이때 필요한 것이 clientid 와 secret 이다. 내가 위에서 설정한 client id 와 secret을 써준다.
그리고 Body 에는 grant_type, username, password 를 넣어준다.
request를 보내면 이렇게 access_token을 발급 받을 수 있다.
이제 발급 받은 Access_token을 private url 뒤에 넣어서 보내면 위에 그림처럼 private이라는 메세지를 볼수 있다.
간단한 예제를 만들어 봤다. 좀더 자세한 내용을 보려면 좀더 공부를 해야하고 이론적인 부분도 상당히 많이 알아야 할것이다.
이예제는 아래 Youtube 동영상을 보면서 따라서 만들어본 예제이다.
'Development > Java' 카테고리의 다른 글
[Spring Boot]RabbitMQ 연동하기 (0) | 2017.10.27 |
---|---|
[Spring Boot]Rest API 호출을 위한 Client Code (0) | 2017.09.14 |
[OAuth] Oauth의 간략한 흐름. (0) | 2017.07.04 |
[Spring Security]간단 Spring Security (0) | 2017.06.27 |
[Spring]Controller Test 하기 (0) | 2017.06.12 |