Spring-boot RestAPI 와 Spring Security OAuth2 연동(spring-boot 1.5.10 기준)

Dependency 추가

Gradle

dependencies {
...
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.security.oauth:spring-security-oauth2')
...
}

Maven

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>

인증URL 설정

ResourceServerConfig.java

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;

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

@Override
public void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().disable().and()
.authorizeRequests()
.antMatchers("/swagger-resources/**","/swagger-ui.html",
"/v2/api-docs", "/webjars/**").permitAll() // Swagger Support
.antMatchers("/", "/api/public-key", "/error").permitAll()
.anyRequest().authenticated()
;
}
}
@EnableResourceServer 어노테이션을 추가한 클래스가 만들어지면 기본적으로 모든요청에 대해 인증을 필요로하게 된다.
특정 url에 대해서 인증을 필요로하지 않을 경우 위와같이하면 permitAll 을 제외한 모든 요청에 인증이 필요하다는 설정이고
또는 특정 url에 대해서만 인증이 필요하다면 permitAll과 authenticated 호출하는 부분의 순서를 바꿔주면 된다.

properties 추가

application.yml

security.oauth2:
client.client-id: foo
client.client-secret: bar
resource.token-info-uri: http://192.168.88.133:8780/oauth/check_token
auth-server-uri: http://192.168.88.133:8780
token요청 및 검증을 위해 인증서버의 tokin-info-uri와 client id/secret 등 설정이 추가되어야함

Swagger 관련 설정

SwaggerConfig.java

@Value("${security.oauth2.auth-server-uri}")
private String authServer;
@Value("${security.oauth2.client.client-id}")
private String clientId;
@Value("${security.oauth2.client.client-secret}")
private String clientSecret;


@Bean
public Docket api(ServletContext servletContext) {
return new Docket(DocumentationType.SWAGGER_2)
....
.securitySchemes(Arrays.asList(securityScheme()))
.securityContexts(securityContexts())
....
;
}

@Bean
public SecurityConfiguration security() {
return SecurityConfigurationBuilder.builder()
.clientId(clientId)
.clientSecret(clientSecret)
.scopeSeparator(",")
.useBasicAuthenticationWithAccessCodeGrant(true)
.build();
}

private SecurityScheme securityScheme() {
GrantType grantType = new AuthorizationCodeGrantBuilder()
.tokenEndpoint(new TokenEndpoint(authServer + "/oauth/token", "oauthtoken"))
.tokenRequestEndpoint(
new TokenRequestEndpoint(authServer + "/oauth/authorize", clientId, clientSecret))
.build();
SecurityScheme oauth = new OAuthBuilder().name("spring_oauth")
.grantTypes(Arrays.asList(grantType))
.scopes(Arrays.asList(scopes()))
.build();
return oauth;
}
private AuthorizationScope[] scopes() {
AuthorizationScope[] scopes = {
new AuthorizationScope("read", "for read operations"),
new AuthorizationScope("write", "for write operations")
};
return scopes;
}

    private List<SecurityContext> securityContexts() {
        List<SecurityContext> securityContexts = new ArrayList<>();
        String paths[] = {
                "/api/dashboard.*",
                "/api/metric-statistics.*"
        };

        for (String path: paths) {
            securityContexts.add(SecurityContext.builder()
                    .securityReferences(Arrays.asList(new SecurityReference("spring_oauth", scopes())))
                    .forPaths(PathSelectors.regex(path))
                    .build());
        }

        return securityContexts;
    }
Oauth서버의 해당클라이언트에 허용가능한 scope와 인증이 필요한 API Path등을 Swagger에 적용한다


블로그 이미지

B급 감성

,