implementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '3.0.5'
시큐리티를 구현하기 위해 먼저 MVN Repository에서 위의 코드를 따와 의존성 주입을 하였습니다.
현재 저희가 진행 중인 스프링부트 버전은 3.0.5 버전으로 2.7+ 버전에서부터는 Spring Security의 WebSecurityConfigureAdapter를 통해 security config를 override 할 때 오류가 발생합니다. 따라서 아쉽게도 제가 알고 있던 방식으로는 더 이상 진행할 수 없기에 이참에 새로운 버전인 시큐리티를 공부하며 인증구현을 하도록 하겠습니다.
비교
다음은 HTTP로 모든 엔드포인트를 보호하는 WebSecurityConfigurerAdapter를 사용한 구성 예시입니다.
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated()
)
.httpBasic(withDefaults());
}
}
필터 체인 빈을 등록하는 현재 보안 방식입니다.
@Configuration
public class SecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated()
)
.httpBasic(withDefaults());
return http.build();
}
}
기존의 방식과 다른 점은 SecurityFilterChain을 반환한다는 점과 빈으로 등록함으로써 컴포넌트 기반의 보안 설정이 가능해집니다.
그리고 나머지는 원래 했던 방식으로 하면 됩니다
이 코드를 활용하려고 했지만 이번엔 antMatchers 가 더 이상 사용할 수 없다는 에러가 생깁니다
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.httpBasic().disable()
.csrf().disable()
.cors().and()
.authorizeRequests()
.antMatchers("/api/v1/users/join", "/api/v1/users/login").permitAll() // join, login은 언제나 가능
.antMatchers(HttpMethod.GET, "/api/**").permitAll() // 모든 get요청 허용
.antMatchers(HttpMethod.POST, "/api/**").authenticated() // 모든 post요청을 인증된사용자인지 check
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // jwt사용하는 경우 씀
.and()
.build();
/*.and()
.addFilterBefore(new JwtTokenFilter(userService, secretKey), UsernamePasswordAuthenticationFilter.class) //UserNamePasswordAuthenticationFilter적용하기 전에 JWTTokenFilter를 적용 하라는 뜻 입니다.
.build();*/
}
}
antMatchers()와 mvcMathcers() 및 regexMatchers()는 Spring Security 6.0에서 더 이상 사용되지 않으며 제거되었습니다
https://github.com/spring-projects/spring-framework/issues/28552
변경의 근거는 다음 예시 코드를 보면 알 수가 있습니다.
@Bean
SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.authorizeHttpRequests(requests -> {
requests.antMatchers("/resources").hasRole("admin");
requests.antMatchers("/resources/**").hasRole("user");
requests.anyRequest().denyAll();
})
.httpBasic(Customizer.withDefaults())
.build();
}
기본 사용자(role user)는 GET/resources를 시도하면 403을 받지만 후행 슬래시 일치를 비활성화하면 GET/resources/를 실행하여 보호를 회피할 수 있습니다. 아무튼 antMatchers 역시 사용할 수가 없습니다.
antMatchers 대신에 requestMatchers를 이용하면 됩니다. 아래는 예시입니다.
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception{
httpSecurity.authorizeHttpRequests()
.requestMatchers("/user/**")
.authenticated()
.anyRequest()
.permitAll();
return httpSecurity.build();
}
특정 url에는 권한이 필요하고 로그인, 가입페이지, 메인페이지, 물품페이지 등은 권한을 필요로 하지 않게 하기 위해서는 api작성이 필요해 보입니다. api작성은 다음 글에서 작성해보도록 하겠습니다.
접은 글 출처: https://fenderist.tistory.com/411
- authenticated() ; 인증된 사용자의 접근을 허용
- fullyAuthenticated(): 인증된 사용자의 접근을 허용, rememberMe인증 제외
- permitAll(): 무조건 허용
- denyAll(): 무조건 차단
- anonymous(): 익명사용자 허용
- rememberMe(): rememberMe 인증 사용자 접근 허용
- access(String): 주어진 SpEL표현식의 평가 결과가 true 이면 접근허용
- hasRole(String): 사용자가 주어진 역할이 있다면 접근을 허용
- hasAuthority(String): 사용자가 주어진 권한이 있다면 허용
- hasAnyRole(String...): 사용자가 주어진 어떤권한이라도 있으면 허용
- hasAnyAuthority(String...): 사용자가 주어진 권한중 어떤 것이라도 있다면 허용
- hasIpAddress(String): 주어진 IP로 부터 요청이 왔다면 접근을 허용
이건 곧 지울 글
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 사용자 인증 처리를 위한 UserDetailsService 빈 등록
@Bean
public UserDetailsService userDetailsService() {
// 여기서 사용자 정보를 로딩하는 DAO 등 구현체를 등록
// 예시로 InMemoryUserDetailsManager를 사용합니다.
UserDetails user = User.builder()
.username("user")
.password("{noop}password")
.roles("USER")
.build();
UserDetails admin = User.builder()
.username("admin")
.password("{noop}password")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN") // 관리자 전용 리소스를 특정 역할만 허용하도록 설정
.antMatchers(HttpMethod.PUT, "/orders/**").hasRole("ADMIN") // 관리자만 주문 상태를 수정할 수 있도록 설정
.antMatchers(HttpMethod.DELETE, "/orders/**").hasRole("ADMIN") // 관리자만 주문을 삭제할 수 있도록 설정
.antMatchers(HttpMethod.POST, "/users/**/orders").hasRole("USER") // 회원만 상품을 구매할 수 있도록 설정
.antMatchers("/user/**").authenticated() // 기존 코드대로 /user/** 인증된 사용자만 접근 가능하도록 설정
.anyRequest().permitAll() // 이외의 모든 요청은 누구나 접근을 허용
.and()
.httpBasic(); // HTTP Basic 인증을 사용
return http.build();
}
}
'사이드 프로젝트 > CafeMate프로젝트(SpringBoot)' 카테고리의 다른 글
14주차 CafeMate 주문 관리 프로세스 구현 (0) | 2023.05.26 |
---|---|
11주차 CafeMate 브랜치에서 실수로 다른 기능 구현을 했을때 (0) | 2023.05.12 |
10주차 CafeMate RESTAPI 작성 (0) | 2023.05.09 |
8주차 CafeMate 개발 프로세스 다시 정립 (1) | 2023.04.24 |