[Spring] Spring Security(1)기본 개념 및 활성화 설정

hyewon jeong·2023년 1월 4일
0

Spring

목록 보기
11/59
post-thumbnail

🍃 1. Spring Security

. Spring Security 란?

  • 개념 👉 'Spring Security' 프레임워크는 스프링 서버에 필요한 인증 및 인가를 위해 많은 기능을 제공해 줌으로써 개발의 수고를 덜어 줍니다. 마치 '스프링' 프레임워크가 웹 서버 구현에 편의를 제공해 주는 것과 같습니다.

Spring Security 기본 설정

🍃Spring Security Documentation

스프링 시큐리티 프레임 워크 추가 build.gradle

// 스프링 시큐리티
implementation 'org.springframework.boot:spring-boot-starter-security'

'스프링 시큐리티' 활성화 하기WebSecurityConfig

🍃참고

import org.springframework.context.annotation.Configuration;
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;

@Configuration
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
                // image 폴더를 login 없이 허용
                .antMatchers("/images/**").permitAll()
                // css 폴더를 login 없이 허용
                .antMatchers("/css/**").permitAll()
                // 어떤 요청이든 '인증'
                .anyRequest().authenticated()
                .and()
                    // 로그인 기능 허용
                    .formLogin()
                    .loginPage("/user/login")
                    .defaultSuccessUrl("/")
                    .failureUrl("/user/login?error")
                    .permitAll()
                .and()
                    // 로그아웃 기능 허용
                    .logout()
                    .permitAll();
    }
}

REST API 기반 일 경우

WebSecurityConfig (springboot 2.7이상)

package com.sparta.springsecurity.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
public class WebSecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // CSRF 설정
        http.csrf().disable();
        
        http.authorizeRequests().anyRequest().authenticated();

        // 로그인 사용
        http.formLogin();
        
        return http.build();
    }

}

🍃 pring security - CSRF란?, http.csrf().disable() ?

SpringBoot 3v 변경된 코드 확인 authorizeRequests() → authorizeHttpRequests()

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // CSRF 설정
        http.csrf().disable();

        http.authorizeHttpRequests().anyRequest().authenticated();

        // 로그인 사용
        http.formLogin();

        return http.build();
    }

리소스(URL)의 권한한 설정

  1. @Bean으로 등록된 webSecurityCustomizer()와 securityFilterChain() 중 우선적으로 위에 있는 webSecurityCustomizer()이 먼저 선언되므로

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        // h2-console 사용
        return (web) -> web.ignoring()
                .requestMatchers(PathRequest.toH2Console())
                .requestMatchers(PathRequest.toStaticResources().atCommonLocations());
    }

requestMatchers

.requestMatchers(PathRequest.toH2Console())
.requestMatchers(PathRequest.toStaticResources().atCommonLocations());

.antMatchers("/h2-console/").permitAll()
.antMatchers("/css/
").permitAll()
.antMatchers("/js/").permitAll()
.antMatchers("/images/
").permitAll()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()

이 경로들을 한 번에 설정을 해줄 수 있는 방법으로

ignoring을 이용 하여
이러한 경로로 들어오는 것들은 인증처리하는 것을 무시하겠다는 의미

antMatchers

 .antMatchers("/api/users/**")

특정 리소스에 대해서 권한을 설정한다.

permitAll

.antMatchers("/api/users/**").permitAll()

antMachers 설정한 리소스의 접근을 인증절차 없이 허용한다는 의미

hasAnyRole

antMatchers("/admin/**").hasAnyRole("ADMIN")

리소스 admin으로 시작하는 모든 URL은 인증 후 ADMIN레벨의 권한을가진 사용자만 접근을 허용한다는 의미입니다.

anyRequest

anyRequest().authenticated()

모든 리소스를 의미하며 접근허용 리소스 및 인증후 특정 레벨의 권한을 가진 사용자만 접근가능한 리소스를 설정하고 그외 나머지 리소스들은 무조건 인증을 완료해야 접근이 가능하다는 의미입니다.

우리가 디폴트 Form Login을 사용한다고 했는데

// 로그인 사용
    http.formLogin();

로그인처리 설정

formLogin 사용시

Security에서 제공하는 디폴트 Form Login을 사용을 하겠다라는 의미로 로그인 페이지와 기타 로그인 처리 및 성공 실패 처리를 사용하겠다는 의미

기본적으로 서버가 시작을 할 때마다 제공하는 디폴트 password가 존재한다.
그리고 username은 user로 고정이 되어 있다.

그래서 username의 user 그리고 패스워드에는 콘솔창에 나와 있는이 값을 사용하면
인증처리가 완료되고 Session ID가 제공이 된다.

url에 localhost:8080/login 요청을 하면 form Login 방식이기 때문에 지금 인증이 되지 않은 요청 이어서 기본 로그인 창이 반환이 된다.

그럼 여기서 제공을 한 패스워드를 복사해서 붙여넣고 user로 로그인 하면 우리가 넣어 놨던 index.html이 막히지 않고 인증이 되어서 나오는 걸 볼 수 있다.

그러면 세션이 잘 넘어왔는지 확인 ~
F12 - 쿠키저장소에 보면 세션이 넘어와 있다.
이 세션이 재로딩이 되도 동일한 값이 들어온다.
근데 만약 이 세션을 삭제를 한다면 -> 다시 로그인 창으로 들어온다.그리고 세션값도 바뀌었다.

세션값을 통해서 인증처리가 된다는 것을 확인 할 수 있다.

👍Spring Security는 기본적으로는 Session방식을 사용을 해서 인증 처리를 한다.

현재 로그인 창이 밋밋하여 우리가 만든 로그인 페이지를 사용

Custom 로그인 페이지 사용

// Custom 로그인 페이지 사용
http.formLogin().loginPage("/api/user/login-page").permitAll();

이러한 폼로그인방식에서 인증이 되지 않는 요청을 로그인 페이지로 보낼 때 기존의 로그인페이지가 아니라
우리가 Custom한 로그인 페이지를 반환을하는 url로 요청이 된다. 그럼 permitAll()로 이 요청은 다 허가해 주겠다라는 의미

loginPage

사용자가 따로 만든 로그인 페이지를 사용하려고 할때 설정한다.

loginPage("/api/user/login-page")

따로 설정하지 않으면 디폴트 URL이 “/login”이기 때문에 “/login”로 호출하면 스프링이 제공하는 기본 로그인페이지가 호출된다.

loginProcessingUrl

로그인 즉 인증 처리를 하는 URL을 설정합니다. “/login-process” 가 호출되면 인증처리를 수행하는 필터가 호출된다.

loginProcessingUrl("/login-process") 

로그인 FORM에서 아이디와 비번을 입력하고 확인을 클릭하면 “/login-process” 를 호출 하게 되었들 때 인증처리하는 필터가 호출되어 아이디 비번을 받아와 인증처리가 수행되게 된다. 즉 UsernamePasswordAuthenticationFilter가 실행 되게 되는 것이다.

defaultSuccessUrl

정상적으로 인증성공 했을 경우 이동하는 페이지를 설정한다.

defaultSuccessUrl("/main")

설정하지 않는경우 디폴트값은 “/”이다.

커스텀 핸들러를 생성하여 등록하면 인증성공 후 사용자가 추가한 로직을 수행하고 성공 페이지로 이동한다.

failureUrl

인증이 실패 했을 경우 이동하는 페이지를 설정한다.

failureUrl("/login-fail")

기존 formlogin 미사용 등 예시

@Configuration
@RequiredArgsConstructor
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig {

    private final JwtUtil jwtUtil;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        // h2-console 사용
        return (web) -> web.ignoring()
                .requestMatchers(PathRequest.toH2Console())
                .requestMatchers(PathRequest.toStaticResources().atCommonLocations());
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .httpBasic().disable() // rest api 이므로 기본 설정 미사용
            .csrf().disable() // rest api 이므로 csrf 보안 미사용
            .formLogin().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // jwt 사용하므로 세션 미사용
            .and()
                .authorizeHttpRequests()
                .antMatchers("/api/users/**").permitAll()
                .anyRequest().authenticated()
            .and()
                .exceptionHandling().authenticationEntryPoint(new CustomAuthenticationEntryPoint())
            .and()
                .exceptionHandling().accessDeniedHandler(new CustomAccessDeniedHandler())
            .and()
                .addFilterBefore(new JwtAuthFilter(jwtUtil), UsernamePasswordAuthenticationFilter.class);

         return http.build();
    }
}
profile
개발자꿈나무

1개의 댓글

comment-user-thumbnail
2023년 5월 18일

도움받고 갑니다. 감사합니다

답글 달기