이 시리즈에 나오는 모든 내용은 인프런 인터넷 강의 - 스프링 시큐리티 - Spring Boot 기반으로 개발하는 Spring Security - 에서 기반된 것입니다. 그리고 여기서 인용되는 PPT 이미지 또한 모두 해당 강의에서 가져왔음을 알립니다.
1. 선언적 방식
http.antMatchers("/users/**").hasRole("USER")
@PreAuthorize("hasRole('USER')")
public void user() {~}
2. 동적 방식(=DB 연동)
일단 간단한 선언적 방식을 이번 게시글에서 알아보고,
동적 방식은 할 게 많으니 추후에 알아보겠다.
메소드 | 동작 |
---|---|
authenticated() | 인증된 사용자의 접근을 허용 |
fullyAuthenticated() | 인증된 사용자의 접근을 허용, rememberMe 인증 제외 |
permitAll() | 무조건 접근을 허용 |
denyAll() | 무조건 접근을 허용하지 않음 |
anonymous() | 익명사용자의 접근을 허용 |
rememberMe() | 기억하기를 통해 인증된 사용자의 접근을 허용 |
access(String) | 주어진 SpEL 표현식의 평가 결과가 true이면 접근을 허용 |
hasRole(String) | 사용자가 주어진 역할이 있다면 접근을 허용 |
hasAuthority(String) | 사용자가 주어진 권한이 있다면 |
hasAnyRole(String...) | 사용자가 주어진 권한이 있다면 접근을 허용 |
hasAnyAuthority(String...) | 사용자가 주어진 권한 중 어떤 것이라도 있다면 접근을 허용 |
hasIpAddress(String) | 주어진 IP로부터 요청이 왔다면 접근을 허용 |
주의할 점
1: 로그인 사용자, 익명 사용자 모두 접근 가능하려면 permitAll().
anonymous() 는 오로지 익명사용자만 가능하다.2: hasRole("USER") , hasAuthority("ROLE_USER") 처럼 사용법이 다름
1. Spring Security 설정 클래스
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@Slf4j
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
// 동적으로 사용자와 동시에 권한도 설정
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("{noop}1111").roles("USER");
auth.inMemoryAuthentication().withUser("sys").password("{noop}1111").roles("SYS");
auth.inMemoryAuthentication().withUser("admin").password("{noop}1111").roles("ADMIN");
// 그런데 만약 admin 에게 USER, SYS 권한도 주고 싶으면 어떡할가?
// auth.inMemoryAuthentication()
// .withUser("admin").password("{noop}1111").roles("ADMIN", "SYS", "USER");
// 하지만 이런 권한 관계가 계층적으로 관리하고 싶을 것이다.
// 또한 동적으로 권한을 줬다 뺏다하는 것도 하고 싶을 것이다.
// 그건 추후에 DB로 권한 관리를 할 때 알아볼 것이다.
// 지금은 선언적 방식의 사용법을 알아가고 넘어가자.
}
// URL 단위로 매핑
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/user").hasRole("USER")
.antMatchers("/api/systemLog").hasRole("SYS")
.antMatchers("/api/admin/**").access("hasRole('ADMIN') or hasRole('SYS')")
.anyRequest().authenticated();
http.formLogin();
}
}
주의할 점이 있다!
만약에 아래처럼 설정했다면 어떻게 됐을까?.antMatchers("/api/admin/**").access("hasRole('ADMIN') or hasRole('SYS')") .antMatchers("/api/systemLog").hasRole("SYS")
이러면
ADMIN
,SYS
권한 모두/api/systemLog
url 에 접근이 된다.
항상 더 자세한 url 이 먼저 나오도록 작성해야 한다는 점을 기억하자.
2. 요청을 받는 예제 RestController 생성
@RestController
public class SecurityController {
@GetMapping("/")
public String index() {
return "home";
}
@GetMapping("/api/user")
public String user() {
return "user";
}
@GetMapping("/api/systemLog")
public String systemLog() {
return "systemLog";
}
@GetMapping("/api/admin/**")
public String admin() {
return "admin";
}
}
사실 선언적 방식은 어떤 자원 경로에 permitAll 해주는 용도로 많이쓰고,
추후에 알아볼 DB 연동 권한 체크에서 더 세세한 관리를 한다.
그러니 이정만 작성하고 그냥 넘어가겠다. 궁금하면 위 코드를 갖고 여러가지 실험하기.