minlog
article thumbnail

큐리티 설정 파일

시큐리티와 관련된 모든 설정들을 관리하는 config 클래스 이다. 

스프링 부트 버전 2.7.0 이전에는  ' WebSecurityConfigurerAdapter ' 를 상속( * 페이지 이동 )받아서 사용해야하며,  이후 부터는 사용되지 않으므로 주의 해야한다.

 

 

📑SecurityConfig.java

package com.example.springsecurity.config;

import lombok.extern.log4j.Log4j2;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@Log4j2
public class SecurityConfig {


}

 

 


 

01 ) 패스워드 암호화 - PasswordEncoder

인증을 위해 반드시 PasswordEncoder 를 지정해야한다.  스프링 시큐리티에서 여러 종류의 PasswordEncoder를 제공하는데 그중 BCryptPasswordEncoder 클래스를 가장 많이 사용한다.

 

 

BCryptPasswordEncoder 

다시 원래대로 복구가 불가능하며, 매번 암호화된 값도 다르게 출력된다.

원본을 확인 불가능하므로 최근 가장 많이 사용된다. Bean을 이용하여 지정해줄수 있다. 

 

 

 

📑SecurityConfig.java

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

 

 

 

🍫 암호화된 패스워드 확인하기 

📑PsswordTests.java

package com.example.springsecurity;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.crypto.password.PasswordEncoder;

@SpringBootTest
public class PasswordTests {
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Test
    public void testEncoder(){
        String password = "1111";
        String enPw = passwordEncoder.encode(password);
        System.out.println("enPw : " +  enPw);

        // 일치 불일치 확인
        boolean matchResult = passwordEncoder.matches(password,enPw);

        System.out.println("matchResult : " + matchResult);
    }

}

 

 

 

🍫 임의의 사용자 계정 생성하여 암호화된 패스워드로 로그인

📑SecurityConfig.java

//사용자 계정 생성
@Bean
public InMemoryUserDetailsManager userDetailsManager(){
    UserDetails user = User.builder()
            .username("user1")
            .password(passwordEncoder().encode("1111"))
            .roles("USER")
            .build();
    log.info("user details service ===============");
    log.info(user);

    return new InMemoryUserDetailsManager(user);
}

 

 


 

02 ) 특정 URL 접근 제한 방법 -  2가지

1번. " SecurityConfig "  설정을 통한 패턴

2번. 어노테이션 사용

 

 

SecurityFilterChain

.permitAll() : 모든 사용자 가능

.hasRole("권한명") : 해당 권한을 가지고 있는 사용자만 접속 가능

* USER = ROLE_USER : 상수 처럼 인증된 사용자를 의미.( 로그인에 성공하면 권한을 가지게 된다. )

 

 

1번. " SecurityConfig "  설정을 통한 패턴

  •  antMatchers  : 어떤 리퀘스트에 대해서 필터체인이 동작할 것인지 설정
ex ) 모든 요청 : http.antMatchers("/**") 
       특정 경로 : http.antMatchers("/api/**") 

 

📑SecurityConfig.java

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
    http.authorizeHttpRequests()
            .antMatchers("/sample/all").permitAll()
            .antMatchers("/sample/member").hasRole("USER");

    http.formLogin(); //로그인폼 사용
    http.logout(); //로그아웃폼 사용

    return http.build();
}

 

 

2번. 어노테이션 사용

  • '📑SecurityConfig' 파일에 @EnableGlobalMethodSecurity 적용.
    • prePostEnabled = true  :  @PreAuthorize (컨트롤러에서 속성 지정 * 아래  설명 참조) 를 사용하기 위해 속성 필요하다.
    • securedEnabled = true  :  @Secure (좀더 유연한 설정이 가능) 를 사용하기 위해 속성 필요하다.
    • 기존 접근 제안 걸어 주었던 내용은 주석처리 해주었다.

📑SecurityConfig.java

package com.example.springsecurity.config;

@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
@Configuration
@Log4j2
public class SecurityConfig {

 	...
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
        // http.authorizeHttpRequests((auth)->{
        //     auth.antMatchers("/sample/all").permitAll();
        //     auth.antMatchers("/sample/member").hasRole("USER");
        // });
      
     	 ...

        return http.build();
    }



}

 

  • '📑SampleController ' 파일에서 각 매핑부분에 접근 권한을 설정해줄 수 있다.
    •  @PreAuthorize("permitAll()")  :  전체 접근가능
    •  @PreAuthorize("hasRole('권한명')")  :  해당 권한을 가지고 있는 사용자만 접근가능

 

📑SampleController.java

package com.example.springsecurity.controller;

...

@Controller
@Log4j2
@RequestMapping("/sample/")
public class SampleController {
    @PreAuthorize("permitAll()")
    @GetMapping("/all")
    public void exAll(){
        log.info("all page");
    }

    @PreAuthorize("hasRole('USER')")
    @GetMapping("/member")
    public void exMember(){
        log.info("member page");
    }

    @PreAuthorize("hasRole('ADMIN')")
    @GetMapping("/admin")
    public void exAdmin(){
        log.info("admin page");
    }



}

 

@PreAuthorize
value 표현식은 '#'과 같은 특별한 기호나 authentication 같은 내장 변수를 이용할 수 있다. 
ex) 로그인한 사용자 중에서 특정 사용자만 접근이 가능하도록 설정
@PreAuthorize("#clubAuthMember != null && #clubAuthMember.username eq \"user95@gmail.com"")
@GetMapping("/admin")
public void exAdmin(){
    log.info("admin page");
}

 

 


 

03 ) CSRF 설정 -  외부 공격방어

CSRF 토큰

사이트간 요청위조를 방지하는 것으로

GET 방식의 요청을 제외한 모든 요청에 임의의 'CSRF 토큰' 을 포함시켜야만 정삭 동작이 가능하다.

하지만 매번 CSRF 토큰 발행을 하지 않아도 되는 경우가 있다.

이때 토큰을 발행하지 않도록 하는 방법은  " http.csrf().disable(); "를 설정에 추가해주면된다.

 

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
    http.authorizeHttpRequests()
        ...
    http.csrf().disable();
    return http.build();
}

 

 

 

 

profile

minlog

@jimin-log

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!