Skip to content

Instantly share code, notes, and snippets.

@mrbusche
Forked from jeffsheets/ApiSecurityConfig.groovy
Created September 18, 2017 02:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrbusche/6854a48889eee034331c08dfe6772459 to your computer and use it in GitHub Desktop.
Save mrbusche/6854a48889eee034331c08dfe6772459 to your computer and use it in GitHub Desktop.
Spock Test for Spring Boot Security configuration - showing basic simple examples for unauthenticated users, role based access, and httpBasic logins
@EnableWebSecurity
class ApiSecurityConfig extends WebSecurityConfigurerAdapter {
@Inject
void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication()
.withUser('svc_acct').password('somePassword').roles('FULL_ACCESS')
}
@Override
protected void configure(HttpSecurity http) {
//Enable Basic authentication via http headers
http.httpBasic()
//Allow unauthenticated GET requests
http.authorizeRequests()
.antMatchers(HttpMethod.GET).permitAll()
//Everything else is secured with a login
.and().authorizeRequests()
.antMatchers('/**').hasRole('FULL_ACCESS')
http.csrf().disable()
}
}
import org.springframework.context.annotation.Profile
import org.springframework.http.HttpMethod
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import javax.inject.Inject
@ContextConfiguration(classes = [SecurityTestController, ApiSecurityConfig])
@WebAppConfiguration
class ApiSecurityConfigSpec extends Specification {
@Autowired
WebApplicationContext context
MockMvc mvc
void setup() {
mvc = webAppContextSetup(context).apply(springSecurity()).build()
}
def 'GET is accessible without login'() {
when:
def response = mvc.perform(get('/securityTest/')).andReturn().response
then:
response.status == OK.value()
}
@Unroll
def '#method throws error without login'(HttpMethod method) {
when: 'request tried without login'
def response = mvc.perform(request(method, '/securityTest/')).andReturn().response
then: 'it fails'
response.status == UNAUTHORIZED.value()
where:
method << [POST, PUT, PATCH, DELETE]
}
@WithMockUser(roles = ['FULL_ACCESS'])
@Unroll
def '#method works when logged in for user with FULL_ACCESS'(HttpMethod method) {
when:
def response = mvc.perform(request(method, '/securityTest/')).andReturn().response
then:
response.status == OK.value()
where:
method << [POST, PUT, PATCH, DELETE]
}
def 'Login works with the system account'() {
given:
String user = 'svc_acct'
String pass = 'somePassword'
when:
def response = mvc.perform(post('/securityTest/').with(httpBasic(user, pass))).andReturn().response
then:
response.status == OK.value()
}
def 'Login fails with bad account info'() {
given:
String user = 'svc_acct'
String pass = 'ThisIsNotCorrect'
when:
def response = mvc.perform(post('/securityTest/').with(httpBasic(user, pass))).andReturn().response
then:
response.status == UNAUTHORIZED.value()
}
@RestController
@RequestMapping(value = '/securityTest', produces = MediaType.APPLICATION_JSON_VALUE)
static class SecurityTestController {
@GetMapping('/')
ResponseEntity<String> get() {
ok('Saul Goodman')
}
@PostMapping('/')
ResponseEntity post() {
ok('Saul Goodman')
}
@PutMapping('/')
ResponseEntity put() {
ok('Saul Goodman')
}
@PatchMapping('/')
ResponseEntity patch() {
ok('Saul Goodman')
}
@DeleteMapping('/')
ResponseEntity delete() {
ok('Saul Goodman')
}
}
}
//Yeah, imports at the bottom look weird but they work and make the gist look cleaner...
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.HttpMethod
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.security.test.context.support.WithMockUser
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.web.WebAppConfiguration
import org.springframework.test.web.servlet.MockMvc
import org.springframework.web.bind.annotation.*
import org.springframework.web.context.WebApplicationContext
import spock.lang.Specification
import spock.lang.Unroll
import static org.springframework.http.HttpMethod.*
import static org.springframework.http.HttpStatus.OK
import static org.springframework.http.HttpStatus.UNAUTHORIZED
import static org.springframework.http.ResponseEntity.ok
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment