Authentication Filter

WebSecurityConfigurerAdapter

WebSecurityCongigurer(SecurityCongigurer)์˜ ๊ตฌํ˜„์ฒด๋กœ ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์˜ ์›น ๋ณด์•ˆ ๊ธฐ๋Šฅ ์ดˆ๊ธฐํ™”, ์„ค์ •์„ ์ •์˜ํ•˜๋Š” ์ถ”์ƒํด๋ž˜์Šค์ด๋‹ค.

Custom์œผ๋กœ ๋ณด์•ˆ์„ค์ •์„ ํ• ๋•Œ ์ด๋ฅผ ์ƒ์†๋ฐ›์•„ ์ •์˜ํ•˜๋ฉด๋œ๋‹ค.

์ด ์ถ”์ƒ ํด๋ž˜์Šค์—์„œ๋Š” ์„ธ๋ถ€ ๋ณด์•ˆ๊ธฐ๋Šฅ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” API์ธ HttpSecuriy๋ฅผ ํ†ตํ•ด ์ธ์ฆ/์ธ๊ฐ€ API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•œ ํด๋ž˜์Šค๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ๋ผ๋ฉด ๋ณด์•ˆ๊ธฐ๋Šฅ์€ ๊ฐ๊ฐ ๋™์ž‘ํ•˜๊ณ  ์„ค์ • ํด๋ž˜์Šค ๋ณ„๋กœ ํ•„ํ„ฐ๊ฐ€ ๊ฐ๊ฐ ์ƒ์„ฑํ•œ๋‹ค. FilterChainProxy๊ฐ€ ๊ฐ ํ•„ํ„ฐ๋“ค๋„ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•˜๋ฉฐ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ  ์š”์ฒญ์— ๋Œ€ํ•œ url์— ๋งค์นญ๋˜๋Š” RequestMathcer์™€ ๋งค์นญ๋˜๋Š” ํ•„ํ„ฐ๊ฐ€ ์ž‘๋™ํ•œ๋‹ค.

์ธ์ฆ API

  • http.formLogin()

  • http.logout()

  • http.csrf()

  • http.SesseionManagement()

  • http.RememberMe()

  • http.ExceptionHandling()

  • http.addFilter()

์ธ๊ฐ€ API

  • http.authorizeRequests()

  • http.andtMathcers(/domain)

  • http.hasRole(ADMIN)

  • http.permitAll()

  • http.authenticated()

  • http.fullyAuthentication()

  • http.access(hasRole(USER))

  • http.denyAll()

@EnableWebSecurity
public class CustomConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .anyRequest().authenticated();
        http
                .formLogin();
    }
}

//application.properties
spring.security.user.name=gowoo
spring.security.user.password=1234

application.propertiesํŒŒ์ผ์„ ํ†ตํ•ด ์ดˆ๊ธฐ ์ƒ์„ฑ๋˜๋Š” ๊ณ„์ •์˜ name๊ณผ password๋ฅผ ๋ณ€๊ฒฝ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

Form Login ์ธ์ฆ

HttpSecurity์˜ API๋ฅผ ์ด์šฉํ•ด ๋กœ๊ทธ์ธํŽ˜์ด์ง€/์„ฑ๊ณต,์‹คํŒจ์— ๋”ฐ๋ฅธ ํŽ˜์ด์ง€ ๋“ฑ ํ•ธ๋“ค๋งํ•  ์ˆ˜ ์žˆ๋Š” api๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

  • http.loginPage("/login") : ์‚ฌ์šฉ์ž ์ •์˜ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€

  • http.defaultSuccessUrl("/home") : ์„ฑ๊ณตํ›„ ์ด๋™ ํŽ˜์ด์ง€

  • http.failureUrl("/login") : ์‹คํŒจ ์ด๋™ ํŽ˜์ด์ง€

  • http.usernameParameter("username") : ์•„์ด๋”” ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค์ • (๊ธฐ๋ณธ ์ œ๊ณตํ•˜๋Š” ํผ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋„ ์ž๋™ ์„ค์ •)

  • http.passwordParameter("passwd") : pw ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค์ • (๊ธฐ๋ณธ ์ œ๊ณตํ•˜๋Š” ํผ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋„ ์ž๋™ ์„ค์ •)

  • http.loginProcessUrl("/login") : ๋กœ๊ทธ์ธ ํผ

  • http.successHandler() : ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„ ํ•ธ๋“ค๋Ÿฌ

  • http.failureHandler() : ๋กœ๊ทธ์ธ ์‹คํŒจ ํ›„ ํ•ธ๋“ค๋Ÿฌ

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
        .anyRequest().authenticated();
    http
        .formLogin()
        .loginPage("/loginPage")
        .defaultSuccessUrl("/")
        .failureUrl("/loginPage")
        .usernameParameter("id")
        .passwordParameter("pw")
        .loginProcessingUrl("/login_proc")
        .successHandler((request, response, authentication) -> {
            System.out.println("authentication : " + authentication.getName());
            response.sendRedirect("/");
        })
        .failureHandler((request, response, exception) -> {
            System.out.println("exception : " + exception.getMessage());
            response.sendRedirect("/login");
        });
}

UsernamePasswordAuthenticationFilter

LoginForm์ธ์ฆ์€ ํ•ด๋‹น filter๋ฅผ ๊ฑฐ์น˜๊ฒŒ ๋˜๊ณ  ํ•ด๋‹น filter์— ์˜ํ•ด ์š”์ฒญ ์ •๋ณด๊ฐ€ AntPathRequestMatcher(/login)์— ๋งค์นญ๋˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ๋งค์นญ์ด ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ๋‹ค๋ฅธ filter๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค. ๋งค์นญ์ด ๋œ๋‹ค๋ฉด id์™€ password๋ฅผ ๋‹ด์€ Authentication๊ฐ์ฒด๋ฅผ ์ด์šฉํ•ด์„œ AuthenticationManager๊ฐ€ AuthenticationProvider๋ฅผ ์—๊ฒŒ ์ธ์ฆ์„ ์œ„์ž„ํ•ด์„œ ์ธ์ฆ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ์„ฑ๊ณตํ•œ๋‹ค๋ฉด Authentication์— ์ ‘๊ทผ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•ด SecurityContext์— ์ €์žฅํ•˜๊ฒŒ ๋œ๋‹ค.

UsernamePasswordAuthentication์—์„œ์˜ Authentication ์ถ”์ƒ ๊ฐ์ฒด๋Š” UsernamePasswordAuthenticationToken๋ผ๋Š” ๊ตฌํ˜„์ฒด๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„์„ ํ•˜๊ณ  ์žˆ๊ณ , AuthenticationMager์˜ ๊ตฌํ˜„์ฒด๋กœ๋Š” ProviderManger๊ฐ€ ๋œ๋‹ค. Provider๊ฐ์ฒด์˜ authenticate()๋ฉ”์„œ๋“œ๋‚ด๋ถ€์˜ while()/provider.supports()๋ฅผ ํ†ตํ•ด ์ ํ•ฉํ•œ Provider๋ฅผ ์ฐพ๊ณ  result = provider.authenticate(authentication);๋ถ€๋ถ„์—์„œ Provider์—๊ฒŒ ์ธ์ฆ์„ ์œ„์ž„ํ•œ๋‹ค.

RememberMe

์„ธ์…˜์ด ๋งŒ๋ฃŒ๋˜๊ณ  ์›น ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ข…๋ฃŒ๋˜์–ด๋„ ์‚ฌ์šฉ์ž๋ฅผ ๊ธฐ์–ตํ•˜๊ฑฐ๋‚˜ Remember-Me์ฟ ํ‚ค์— ๋Œ€ํ•œ ์š”์ฒญ์„ ํ™•์ธํ•œ ํ›„ ํ† ํฐ ๊ธฐ๋ฐ˜ ์ธ์ฆ์„ ์‚ฌ์šฉํ•ด ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•ด ๋กœ๊ทธ์ธ ์‹œํ‚ค๋Š” ๊ธฐ๋Šฅ

SecurityContextHolder์— Authentication์ด null์ผ๋•Œ ์ด ํ•„ํ„ฐ๋ฅผ ๊ฑฐ์ณ ๊ธฐ๋ก๋œ ์ธ์ฆ์ •๋ณด๊ฐ€ ์žˆ๋Š”์ง€ ํŒ๋ณ„

@Autowired
UserDetailsService userDetailsService

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
        .anyRequest().authenticated();
    http
        .formLogin()
        .loginPage("/loginPage")
        .defaultSuccessUrl("/")
        .failureUrl("/loginPage")
        .usernameParameter("id")
        .passwordParameter("pw")
        .loginProcessingUrl("/login_proc")
        .successHandler((request, response, authentication) -> {
            System.out.println("authentication : " + authentication.getName());
            response.sendRedirect("/");
        })
        .failureHandler((request, response, exception) -> {
            System.out.println("exception : " + exception.getMessage());
            response.sendRedirect("/login");
        })
        .and()
        .rememberMe()
        .rememberMeParameter("remember")
        .tokenValidateSeconds(3600)     //default๋Š” 14์ผ์ด๋‹ค.
        .userDetailsService(userDetailsService)
}

Session

http.sessionManageMent()    //session๊ธฐ๋Šฅ ์„ค์ •
    .maximumSession(1)      //์ตœ๋Œ€ ํ—ˆ์šฉ ๊ฐ€๋Šฅ ์„ธ์…˜
    .maxSessionsPreventsLogin(true) //๋™์‹œ ๋กœ๊ทธ์ธ ์ฐจ๋‹จ
    .invalidSessionUrl()
    .expiredUrl()
    .sessionFixation().changeSessionId()  //์ด ๊ฐ’์ด ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ Session์„ ์ƒˆ๋กœ๋ฐœ๊ธ‰๋ฐ›๊ธฐ๋•Œ๋ฌธ์— ๊ณ ์ •Session๋ฌธ์ œ ํ•ด๊ฒฐ
    .sessionCreateionPolicy(SessionCreationPolicy.Stateless) //Session ์ƒ์„ฑํ•˜์ง€๋„์•Š๊ณ  ์‚ฌ์šฉํ•˜์ง€๋„ ์•Š์Œ
                                //Always(ํ•ญ์ƒ ์ƒ์„ฑ) / IfRequired(๊ธฐ๋ณธ ๊ฐ’์œผ๋กœ ํ•„์š”์‹œ ์ƒ์„ฑ) / Never(์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ์กด์žฌํ•˜๋ฉด ์‚ฌ์šฉ)

๋™์‹œ ์ ‘์† ์˜ˆ

  1. UsernamePasswordAuthenticationFilter -> ConcurrentSessionControleAuthenticationStrategy ๋ฅผ ํ†ตํ•ด Session Count ์ฆ๊ฐ€

  2. ChangeSessionIdAuthenticationStrategy์—์„œ session.changeSessionId()๋ฅผ ์ด์šฉํ•ด Session ์ƒ์„ฑ

  3. ResiterSessionAuthenticationStrategy์— ์„ธ์„ ์ •๋ณด ๋“ฑ๋ก

  4. ์ธ์ฆ ์„ฑ๊ณต

  5. ๋‹ค๋ฅธ ๋ธŒ๋ผ์šฐ์ € ์—์„œ ๋™์ผ ์•„์ด๋”” ์ ‘์†

  6. ConcurrentSessionControlAuthenticaionStrategy์—์„œ session count๋ฅผ ์ฆ๊ฐ€ ์‹œํ‚ค๊ณ  maxSession์ˆ˜์™€ ๋น„๊ต

  7. ํ‹€๋ฆด ๊ฒฝ์šฐ

    1. ์ธ์ฆ ์‹คํŒจ ์ „๋žต์ผ ๊ฒฝ์šฐ SessionAuthenticationException

      1. ์ธ์ฆ ์‹คํŒจ

    2. ์„ธ์…˜ ๋งŒ๋ฃŒ ์ „๋žต์ธ ๊ฒฝ์šฐ session.expireNow():์ฒซ๋ฒˆ์งธ ์„ธ์…˜

      1. ์ธ์ฆ ์„ฑ๊ณต

      2. ChangeSessionIdAuthenticationStrategy์—์„œ session.changeSessionId()์ˆ˜ํ–‰

      3. ResiterSessionAuthenticationStrategy์—์„œ sessino์ •๋ณด ๋“ฑ๋ก

  8. ์ฒซ๋ฒˆ์งธ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ ‘์†์‹œ ConcurrentSessionFilter์— ์ ‘์†

  9. session ๋งŒ๋ฃŒ๋กœ ์ ‘์† ์‹คํŒจ

ConcurrentSessionControleAuthenticationStrategy / ChangeSessionIdAuthenticationStrategy / ResiterSessionAuthenticationStrategy๋Š” SessionManagementFilter์—์„œ ์˜์กดํ•˜๋Š” class


Refernece

์ธํ”„๋Ÿฐ - Spring Security(์ •์ˆ˜์›)

Last updated