https://github.com/wikibook/spring-security/tree/main/ssia-ch7-ex1
pom.xml에
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
추가
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic();
http.authorizeRequests().anyRequest().access("hasAuthority('WRITE')");
}
WebSecurityConfigurerAdapter를 상속받은 클래스에서 write권한이 있는 사람만 접근가능하도록 설정
//http.authorizeRequests().anyRequest().permitAll();//모든 요청에 대해 엑세스 허용
그냥 호출하면 401에러 떨어짐
C:\Users\user>curl http://localhost:8080/hello
{"timestamp":"2023-07-28T03:54:27.140+00:00","status":401,"error":"Unauthorized","message":"","path":"/hello"}
정상적인 경우
C:\Users\user>curl -u jane:12345 http://localhost:8080/hello
Hello!
참고로 jane은 write권한이 있음
var user2 = User.withUsername("jane")
.password("12345")
.authorities("WRITE")
.build();
manager.createUser(user1);
manager.createUser(user2);
john은 권한이 없기 때문에 접근금지
C:\Users\user>curl -u john:12345 http://localhost:8080/hello
{"timestamp":"2023-07-28T03:56:47.035+00:00","status":403,"error":"Forbidden","message":"","path":"/hello"}
var user1 = User.withUsername("john")
.password("12345")
.authorities("READ")
.build();
참고로 서버 시작시에
가장 먼저 시작되는 것이 메인클래스 그 다음이
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
configuration 부분
@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter {
@Override
@Bean
public UserDetailsService userDetailsService() {
var manager = new InMemoryUserDetailsManager();
그리고 hasAnyAuthority 사용하면 write 혹은 read만 있더라도 접근 허용 가능
http.authorizeRequests().anyRequest().hasAnyAuthority("WRITE", "READ");
expression으로 권한 관리를 할 수 있는건 처음 알음...
String expression = "hasAuthority('READ') and !hasAuthority('DELETE')";
http.authorizeRequests().anyRequest().access(expression);
@Override
@Bean
public UserDetailsService userDetailsService() {
var manager = new InMemoryUserDetailsManager();
var user1 = User.withUsername("john")
.password("12345")
.authorities("READ","WRITE")
.build();
var user2 = User.withUsername("jane")
.password("12345")
.authorities("READ","DELETE")
.build();
manager.createUser(user1);
manager.createUser(user2);
return manager;
}
이런식으로 주고
C:\Users\user>curl -u john:12345 http://localhost:8080/hello
Hello!
C:\Users\user>curl -u jane:12345 http://localhost:8080/hello
{"timestamp":"2023-07-28T04:06:31.867+00:00","status":403,"error":"Forbidden","message":"","path":"/hello"}
각각 존과 제인을 호출했을 경우
제인은 forbidden.
그리고 스프링부트 테스트도 잘만듬.
@SpringBootTest
@AutoConfigureMockMvc
public class MainTests {
@Autowired
private MockMvc mvc;
@Test
@DisplayName("The endpoint cannot be called unauthenticated")
public void testFailedAuthentication() throws Exception {
mvc.perform(get("/hello"))
.andExpect(unauthenticated());
}
@Test
@DisplayName("A user without privileges can authenticate but is not authorized")
@WithUserDetails("john")
public void testSuccessfulAuthentication() throws Exception {
mvc.perform(get("/hello"))
.andExpect(authenticated())
.andExpect(status().isForbidden());
}
@Test
@DisplayName("A user with privileges can authenticate and is authorized")
@WithUserDetails("jane")
public void testSuccessfulAuthorization() throws Exception {
mvc.perform(get("/hello"))
.andExpect(authenticated())
.andExpect(status().isOk());
}
}
.andExpect(unauthenticated());를 써서 만약 인증을 통과하지 못했을 경우를 가정
그리고 아래는 인증 통과하고 정상적으로 권한획득한 경우를 가정해서 테스트.
.andExpect(authenticated())
.andExpect(status().isOk());
그다음 .role()부분 설명이 있는데 이 부분은 .authorities와 크게 차이가 없으므로 패스
그다음 denyAll()에 대한 설명이 나오는데
denyAll()은 말 그대로 전부 허용 거부.
테스트를 위해 hello2 메소드를 컨트롤러에 추가한다.
@GetMapping("/hello")
public String hello() {
return "Hello!";
}
@GetMapping("/hello2")
public String hello2() {
return "Hello2!";
}
그후에 아래 환경설정으로 테스트하면
String expression = "hasAuthority('READ') and !hasAuthority('DELETE')";
http.authorizeRequests().anyRequest().access(expression);
john : read/write 권한보유
jane : read/delete 권한보유
john은 hello / hello2 uri 모두 통과
jane은 모두 실패
근데 아래처럼 테스트하면
String expression = "hasAuthority('READ') and !hasAuthority('DELETE')";
http.authorizeRequests().antMatchers("/hello").access(expression).antMatchers("/**").denyAll();
john은 hello 에 대해서만 통과 / hello2는 denyall로 실패
jane은 모두 실패
원래 생각은 어차피 특정 url만 접근하도록 권한을 주면 굳이 denyall을 안써도 될 것 같다고 생각해서 테스트.
근데 보면 알겠지만 denyall을 걸어버리면 hello만 접근되고 hello2는 접근불가됨.
'IT' 카테고리의 다른 글
스프링 부트 img-src 특정 url 추가방법 Content Security policy directive :"img-src 'self' data: (0) | 2023.07.31 |
---|---|
request-entity-too-large client intended to send too large body (0) | 2023.07.31 |
jquery.filedownload.js 파일 한글깨짐 현상 (0) | 2023.07.28 |
자바스크립트 preventDefault (0) | 2023.07.25 |
RuntimeError: CUDA error: invalid device ordinal (0) | 2023.07.21 |