[7/31 TIL] SPRING SECURITY(์‹œ์ž‘)

yumyeonghanยท2023๋…„ 8์›” 1์ผ
0

๐Ÿƒํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐฑ์—”๋“œ ๋ฐ๋ธŒ์ฝ”์Šค 4๊ธฐ ๊ต์œก๊ณผ์ •์„ ๋“ฃ๊ณ  ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.๐Ÿƒ

Spring Security ์‹œ์ž‘

์˜์กด์„ฑ ์ถ”๊ฐ€

  • spring-boot-starter-security: spring security ๋ชจ๋“ˆ ์‚ฌ์šฉ
  • spring-security-test: spring security ํ…Œ์ŠคํŠธ ๋ชจ๋“ˆ ์‚ฌ์šฉ

WebSecurityConfigure

@Configuration
public class WebSecurityConfigure {

    @Bean
    public InMemoryUserDetailsManager userDetailsManager() {
        UserDetails admin = makeUserDetails("admin", "1234", "ADMIN");
        UserDetails user = makeUserDetails("user", "1234", "USER");
        return new InMemoryUserDetailsManager(user, admin);
    }

    private UserDetails makeUserDetails(String name, String password, String role) {
        return User.withUsername(name)
                .password(String.format("{noop}%s", password))
                .roles(role)
                .build();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers(new AntPathRequestMatcher("/me")).hasAnyRole("USER", "ADMIN") //"/me" ๊ฒฝ๋กœ์— ๋Œ€ํ•ด์„œ๋Š” "USER" ๋˜๋Š” "ADMIN" ๊ถŒํ•œ์„ ๊ฐ€์ง„ ์‚ฌ์šฉ์ž๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •
                    	.requestMatchers(new AntPathRequestMatcher("/admin")).hasRole("ADMIN") //"admin" ๊ฒฝ๋กœ์— ๋Œ€ํ•ด์„œ๋Š” "ADMIN" ๊ถŒํ•œ์„ ๊ฐ€์ง„ ์‚ฌ์šฉ์ž๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ • 
                        .requestMatchers(new AntPathRequestMatcher("/admin")).fullyAuthenticated() //๋ช…์‹œ์ ์ธ ๋กœ๊ทธ์ธ ์•„์ด๋””/๋น„๋ฐ€๋ฒˆํ˜ธ ๊ธฐ๋ฐ˜์œผ๋กœ ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ
                        .anyRequest().permitAll()) //"/me" ์ด์™ธ์˜ ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด์„œ๋Š” ๊ถŒํ•œ์— ์ƒ๊ด€์—†์ด ๋ชจ๋“  ์‚ฌ์šฉ์ž์—๊ฒŒ ์ ‘๊ทผ์„ ํ—ˆ์šฉ
                .formLogin(auth -> auth
                		.defaultSuccessUrl("/") //๊ธฐ๋ณธ์ ์œผ๋กœ ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„ '/'๋กœ ์ด๋™ํ•˜๋„๋ก ์„ค์ •
                		//.loginPage("/my-login") ์ง์ ‘ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ์„ค์ •
                        .usernameParameter("my-username") //username input ํƒœ๊ทธ์˜ name ์„ค์ •, default๋Š” username
                        .passwordParameter("my-password") //password input ํƒœ๊ทธ์˜ name ์„ค์ •, default๋Š” password
                        .permitAll()) //๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์— ๋Œ€ํ•ด์„œ๋Š” ๋ชจ๋“  ์‚ฌ์šฉ์ž์—๊ฒŒ ํ—ˆ์šฉ
                .logout(auth -> auth
                		.logoutRequestMatcher(new AntPathRequestMatcher("/logout")) //"/logout" ๊ฒฝ๋กœ๋กœ ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๊ฒฝ์šฐ ๋กœ๊ทธ์•„์›ƒ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰
                        .logoutSuccessUrl("/") //๋กœ๊ทธ์•„์›ƒ์ด ์„ฑ๊ณตํ•˜๋ฉด '/'๋กœ ์ด๋™ํ•˜๋„๋ก ์„ค์ •
                        .invalidateHttpSession(true) //๋กœ๊ทธ์•„์›ƒ ์‹œ ์„ธ์…˜์„ ๋ฌดํšจํ™”
                        .clearAuthentication(true)) //๋กœ๊ทธ์•„์›ƒ ์‹œ ์‚ฌ์šฉ์ž์˜ ์ธ์ฆ ์ •๋ณด๋ฅผ ์ œ๊ฑฐ
                .rememberMe(auth -> auth
                		.key("my-remember-me") //์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋‹ด๊ณ ์žˆ๋Š” ์ฟ ํ‚ค์— ๋Œ€ํ•œ ๊ณ ์œ  ์‹๋ณ„ํ‚ค ์„ค์ • (๋ฏธ์„ค์ •์‹œ ๋žœ๋ค๊ฐ’ ์„ค์ •)
                		.rememberMeParameter("remember-me") //์ฟ ํ‚ค ํŒŒ๋ผ๋ฏธํ„ฐ๋ช… ์„ค์ •, default๋Š” remember-me
                        .tokenValiditySeconds(300)) //์ž๋™ ๋กœ๊ทธ์ธ ์ƒํƒœ์˜ ์œ ํšจ๊ธฐ๊ฐ„์„ 300์ดˆ๋กœ ์ง€์ •
                .build();
    }
}
  • Spring Security๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น ๋ณด์•ˆ์„ ๊ตฌ์„ฑํ•˜๋Š” ์Šคํ”„๋ง ์„ค์ • ํด๋ž˜์Šค
  • userDetailsManager() ๋ฉ”์„œ๋“œ๋Š” ๋ฉ”๋ชจ๋ฆฌ ๊ธฐ๋ฐ˜ ์‚ฌ์šฉ์ž ์ €์žฅ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ธ์ฆ๊ณผ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•จ
    • ์‹ค์ œ ์„œ๋น„์Šค์—์„œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ €์žฅ์†Œ์— ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋„๋ก ๊ตฌ์„ฑํ•ด์•ผํ•จ
    • InMemoryUserDetailsManager ๊ฐ์ฒด๋Š” UserDetailsPasswordService ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์ฒด
    • ์ตœ์ดˆ ๋กœ๊ทธ์ธ 1ํšŒ ์„ฑ๊ณต์‹œ, {noop} ํƒ€์ž…์—์„œ {bcrypt} ํƒ€์ž…์œผ๋กœ PasswordEncoder๊ฐ€ ๋ณ€๊ฒฝ๋˜๊ณ , ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์•”ํ˜ธํ™”๋จ
    • {noop}์€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์•”ํ˜ธํ™”ํ•˜์ง€ ์•Š๊ณ  ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋ฉฐ, ์ด๋Ÿฌํ•œ prefix ๋ถ€๋ถ„์„ ์„ค์ •ํ•ด์•ผํ•จ
  • filterChain() ๋ฉ”์„œ๋“œ๋Š” Spring Security์˜ ํ•„ํ„ฐ ์ฒด์ธ์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ
    • HttpSecurity ๊ฐ์ฒด๋Š” ์›น ๋ณด์•ˆ์— ๋Œ€ํ•œ ์„ค์ •์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค
    • http.authorizeHttpRequests()๋Š” ์š”์ฒญ์— ๋Œ€ํ•œ ์ธ์ฆ ๋ฐ ๊ถŒํ•œ ๋ถ€์—ฌ๋ฅผ ๊ตฌ์„ฑ
    • http.formLogin()๋Š” ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋ฅผ ์ œ๊ณต
    • http.logout()๋Š” ๋กœ๊ทธ์•„์›ƒ ๊ธฐ๋Šฅ์„ ์ œ๊ณต
    • http.rememberMe()๋Š” ์ž๋™ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์„ ์ œ๊ณต

DelegatingPasswordEncoder

{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
{noop}password
{pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc
{sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0
  • DelegatingPasswordEncoder ํด๋ž˜์Šค๋Š” ํŒจ์Šค์›Œ๋“œ ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜๋ณ„๋กœ PasswordEncoder๋ฅผ ์ œ๊ณต
  • ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜๋ณ„ PasswordEncoder ์„ ํƒ์„ ์œ„ํ•ด ํŒจ์Šค์›Œ๋“œ ์•ž์— prefix({noop})๋ฅผ ์ถ”๊ฐ€ํ•จ
  • Spring Security์—์„œ๋Š” DelegatingPasswordEncoder ํด๋ž˜์Šค๊ฐ€ ๊ธฐ๋ณธ PasswordEncoder๋กœ ์‚ฌ์šฉ๋จ
  • prfiex ๋ถ€๋ถ„์ด ์ƒ๋žต๋˜๋Š” ๊ฒฝ์šฐ ๊ธฐ๋ณธ PasswordEncoder๋กœ bcrypt๊ฐ€ ์‚ฌ์šฉ๋จ
  • DelegatingPasswordEncoder ๋Œ€์‹  ๋‹ค๋ฅธ ์ธ์ฝ”๋”(BCryptPasswordEncoder)๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด, ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ Bean ์„ ์–ธํ•˜๋ฉด๋จ
profile
์›น ๊ฐœ๋ฐœ์— ๊ด€์‹ฌ ์žˆ์Šต๋‹ˆ๋‹ค.

1๊ฐœ์˜ ๋Œ“๊ธ€

comment-user-thumbnail
2023๋…„ 8์›” 2์ผ

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์ •๋ณด๋ฅผ ๋‚˜๋ˆ ์ฃผ์…”์„œ ์ข‹์•„์š”.

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ