Back-End ์ž‘์—…์‹ค/Spring Framework

[Spring Boot] Spring Security Basic - ๊ธฐ๋ณธ API ๋ฐ Filter ์ดํ•ดํŽธ

์ฃผ๋‹ˆ์“ฐ๐Ÿง‘‍๐Ÿ’ป 2022. 8. 10. 02:30
728x90
๋ฐ˜์‘ํ˜•

์ด ๊ธ€์€ ์ธํ”„๋Ÿฐ -  Spring Boot ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐœ๋ฐœํ•˜๋Š” Spring Security๋ฅผ ํ•™์Šตํ•˜๋ฉด์„œ ์ •๋ฆฌํ•œ ๋‚ด์šฉ ์ž…๋‹ˆ๋‹ค.

 

 

GIT HUB ์ฃผ์†Œ : https://github.com/junyharang-coding-study/spring-security

 

 

 

 

๐Ÿ—‚ ๋ชฉ์ฐจ

โ— [Spring Boot] Spring Security Basic - ๊ธฐ๋ณธ API ๋ฐ Filter ์ดํ•ดํŽธ 
โ— [Stpring Boot] Spring Security Basic - Spring Security ์ฃผ์š” ์•„ํ‚คํ…์ฒ˜ ์ดํ•ดํŽธ
โ— [Stpring Boot] Spring Security ์‹ค์ „ ํ”„๋กœ์ ํŠธ - ์ธ์ฆ ํ”„๋กœ์„ธ์Šค Form ์ธ์ฆ ๊ตฌํ˜„(1)   
โ— [Stpring Boot] Spring Security ์‹ค์ „ ํ”„๋กœ์ ํŠธ - ์ธ์ฆ ํ”„๋กœ์„ธ์Šค Form ์ธ์ฆ ๊ตฌํ˜„(2)
โ— [Stpring Boot] Spring Security ์‹ค์ „ ํ”„๋กœ์ ํŠธ - ์ธ์ฆ ํ”„๋กœ์„ธ์Šค Ajax ์ธ์ฆ ๊ตฌํ˜„

 

 

 

 

 

๐Ÿš€ Spring Security ์ด๋ก 

    ๐Ÿ”ฝ  ์ค€๋น„ํ•˜๊ธฐ

        ๐Ÿ“ฆ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ

• JDK 1.8 ์ด์ƒ
Maven
DB - H2 DB
IDE - InteliJ




        ๐Ÿ“ฆ ํ”„๋กœ์ ํŠธ ๊ตฌ์„ฑ ๋ฐ ์˜์กด์„ฑ ์ถ”๊ฐ€

์ตœ์ดˆ Project ๊ตฌ์„ฑ ์‹œ ์˜์กด์„ฑ์€ Spring Boot Web๋งŒ ์ถ”๊ฐ€ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>security</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>junyharang-spring-secutiry</name>
    <description>junyharang-spring-secutiry</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Spring Security Dependency ์ถ”๊ฐ€ -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <!-- Slf4J Dependency ์ถ”๊ฐ€ -->
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

pom.xml


๊ทธ๋Ÿฐ ๋’ค ์œ„์™€ ๊ฐ™์ด Spring Security Dependency์™€ Log ์ถœ๋ ฅ์„ ์œ„ํ•œ Slf4J Dependency๋ฅผ ์ถ”๊ฐ€ํ•ด ์ฃผ์—ˆ์–ด์š”!




    ๐Ÿ”ฝ  Spring Security Basic API & Filter ์ดํ•ดํ•˜๊ธฐ

        ๐Ÿ“ฆ ์ธ์ฆ API - Spring Security ์˜์กด์„ฑ ์ถ”๊ฐ€ ์‹œ ์ผ์–ด๋‚˜๋Š” ์ผ

Spring Boot Server๋ฅผ ๊ธฐ๋™์‹œํ‚ค๋ฉด Spring Security์˜ ์ดˆ๊ธฐํ™” ์ž‘์—… ๋ฐ ๋ณด์•ˆ ์„ค์ •์ด ์ด๋ฃจ์–ด์ง€๊ฒŒ ๋˜์š”.
๋ณ„๋„์˜ ์„ค์ •, ๊ตฌํ˜„์„ ํ•˜์ง€ ์•Š์•„๋„ ๊ธฐ๋ณธ์ ์ธ ์›น ๋ณด์•ˆ ๊ธฐ๋Šฅ์ด ์ž‘๋™ํ•˜๊ฒŒ ๋œ๋‹ต๋‹ˆ๋‹ค.

 ๋ชจ๋“  ์š”์ฒญ์€ ์ธ์ฆ์ด ๋˜์–ด์•ผ ์ž์› ์ ‘๊ทผ ๊ฐ€๋Šฅ
์ธ์ฆ ๋ฐฉ์‹์€ Form Login ๋ฐฉ์‹, Http Basic Login ๋ฐฉ์‹ ์ œ๊ณต
๊ธฐ๋ณธ Login Page ์ œ๊ณต
๊ธฐ๋ณธ ๊ณ„์ • ํ•œ ๊ฐœ ์ œ๊ณต - username(ID) : user / password : ๋žœ๋ค ๋ฌธ์ž์—ด (Spring Boot ๊ธฐ๋™ ์‹œ ์•„๋ž˜์™€ ๊ฐ™์ด ํ‘œ์‹œ)

Spring Security ๊ธฐ๋ณธ Password


ํ•˜์ง€๋งŒ, Spring Security ์ดˆ๊ธฐ์—๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฌธ์ œ์ ์ด ์žˆ๋Š” ๊ฒƒ์ด์—์š”.

• ๊ณ„์ • ์ถ”๊ฐ€
• Data Base ์ถ”๊ฐ€ ๋ฐ ์—ฐ๋™
• ๊ธฐ๋ณธ ๋ณด์•ˆ ๊ธฐ๋Šฅ ์™ธ ์„ธ๋ถ€์  ์ถ”๊ฐ€์  ๋ณด์•ˆ ๊ธฐ๋Šฅ ๊ตฌํ˜„ ํ•„์š”

 

 

 

 

        ๐Ÿ“ฆ ์ธ์ฆ API - ์ด์šฉ์ž ์ •์˜ ๋ณด์•ˆ ๊ธฐ๋Šฅ ๊ตฌํ˜„

์ตœ์ดˆ Spring Security๋ฅผ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฐฉ์‹์„ ์ด์šฉํ•ด์„œ ์„ค์ •์„ ํ•ด ์ฃผ์–ด์•ผ ํ•ด์š”.


1. ์ธ์ฆ API ์ œ๊ณต ๊ธฐ๋Šฅ
http.formLogin()
http.logout()
http.csrf()
http.httpBasic()
http.SessionManagement()
http.RememberMe()
http.ExceptionHandling()
http.addFilter()


2. ์ธ๊ฐ€ API ์ œ๊ณต ๊ธฐ๋Šฅ
http.authorizeRequests()
.antMatchers("/{URI}")
.hasRole({๊ณ„์ • ๊ถŒํ•œ๋ช…})
.permitAll()
authenticated()
fullyAuthentication()
access(hasRole({๊ณ„์ • ๊ถŒํ•œ๋ช…})
 . denyAll()

 

 

 

 

        ๐Ÿ“ฆ ์ธ์ฆ API - SecurityConfig ๊ตฌํ˜„

 

package com.junyharang.spring.security.config;

import lombok.extern.slf4j.Slf4j;
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;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Spring Security Config Class
 * <b>History:</b>
 * @author ์ฃผ๋‹ˆํ•˜๋ž‘
 * @version 1.0.0, 2022.06.14 ์ตœ์ดˆ ์ž‘์„ฑ
 */

@Slf4j
@Configuration @EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * Spring Security ์„ค์ • Method
     * @param http - ์„ธ๋ถ€ ๋ณด์•ˆ ๊ธฐ๋Šฅ ์„ค์ • API ์ œ๊ณต ๊ฐ์ฒด
     */

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                    .authorizeRequests()                                    // Client๊ฐ€ http ๋ฐฉ์‹์œผ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด
                    .anyRequest().authenticated()                           // ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด ์ธ์ฆ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.
                .and()                                                      // ๊ทธ๋ฆฌ๊ณ ,
                    .formLogin()                                            // ์ธ์ฆ ๋ฐฉ์‹์€ formLogin ๋ฐฉ์‹
    } // configure(HttpSecurity http) ๋
} // class ๋


์ตœ์ดˆ ์œ„์™€ ๊ฐ™์ด ์„ค์ •์„ ํ•ด ์ฃผ์—ˆ๊ณ , Client๊ฐ€ http ๋ฐฉ์‹์œผ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด ์ธ์ฆ ํ™•์ธ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ณ , ์ธ์ฆ ๋ฐฉ์‹์„ FormLogin ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์„ค์ •ํ•˜์˜€์–ด์š”.





        ๐Ÿ“ฆ ์ธ์ฆ API - Form ์ธ์ฆ

Form ์ธ์ฆ ๋ฐฉ์‹์˜ Login Logic์€ ์•„๋ž˜์™€ ๊ฐ™์ด ์ฒ˜๋ฆฌ๊ฐ€ ๋˜์š”.



http.formLogin()	// Form Login ์ธ์ฆ ๊ธฐ๋Šฅ On

 

 @Override
    protected void configure(HttpSecurity http) throws Exception {
    
    http.formLogin()
    	.loginPage("/signin")					// ๊ฐœ๋ฐœ์ž ์ •์˜ Login Page URI
        .defaultSuccessUrl("/home")				// Login ์„ฑ๊ณต ๋’ค ์ด๋™ํ•˜๊ฒŒ ๋  Page URI
        .failureUrl("/login.html?error=true")	// Login ์‹คํŒจ ๋’ค ์ด๋™ํ•˜๊ฒŒ ๋  Page URI
        .usernameParameter("username")			// ์ด์šฉ์ž ID ๋ณ€์ˆ˜๋ช… ์„ค์ •
        .passwordParameter("password")			// ์ด์šฉ์ž ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€์ˆ˜๋ช… ์„ค์ •
        .loginProcessingUrl("/signin")			// Login Form Action URI
        .successHandler(loginSuccessHandler())	// Login ์„ฑ๊ณต ๋’ค ํ˜ธ์ถœ ๋  Handler
        .failureHandler(loginFailureHandler())	// Login ์‹คํŒจ ๋’ค ํ˜ธ์ถœ ๋  Handler
        
}






 

 

        ๐Ÿ“ฆ ์ธ์ฆ API - UsernamePasswordAuthenticationFilter

 

UsernamePasswordAuthenticationFilter ๋™์ž‘ ๋ฐฉ์‹

 

 

 

 

        ๐Ÿ“ฆ ์ธ์ฆ API - Logout

 

์ด์šฉ์ž๊ฐ€ Logout ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋˜๋ฉด Spring Security ๋‚ด์—์„œ๋Š” ์–ด๋–ค ์ผ์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋ ๊นŒ์š”?
์œ„์˜ ๊ทธ๋ฆผ์—์„œ ๋‚˜์™€ ์žˆ ๋“ฏ Session์„ ๋ฌดํšจํ™”ํ•˜๊ณ , ์ธ์ฆ ํ† ํฐ(์ด์šฉ์ž๊ฐ€ ์ธ์ฆ์„ ํ–ˆ์„ ๋•Œ, ์ƒ์„ฑ๋œ ์ธ์ฆ ๊ฐ์ฒด)์„ ์‚ญ์ œํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด ๋•Œ, ์ธ์ฆ ํ† ํฐ์ด ์ €์žฅ๋˜์–ด ์žˆ๋Š” ๊ฐ์ฒด์ธ Security Context๋ฅผ ํ•จ๊ป˜ ์‚ญ์ œํ•˜๊ฒŒ ๋˜์š”.

๊ทธ๋ฆฌ๊ณ , ์‚ญ์ œํ•ด์•ผ ํ•  ์ฟ ํ‚ค ์ •๋ณด๊ฐ€ ์žˆ๋‹ค๋ฉด ํ•ด๋‹น ์ฟ ํ‚ค๋ฅผ ์‚ญ์ œํ•˜๊ณ , ๋‹ค์‹œ Login Page๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ฃผ๋Š” ๊ฒƒ์ด์—์š”.

Spring Secutiry Config Class์—์„œ http.logout()์„ ์„ค์ •ํ•˜๊ฒŒ ๋˜๋ฉด Logout ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™” ํ•  ์ˆ˜ ์žˆ์–ด์š”.

 

protected void configure(HttpSecurity http) throws Exception {
	http.logout()										// Logout ์ฒ˜๋ฆฌ
    	.logoutUrl("/logout")							// Logout ์ฒ˜๋ฆฌ URI
        .logoutSuccessUrl("/signin")					// Logout ์„ฑ๊ณต ๋’ค ์ด๋™ํ•  Page URI
        .deleteCookies(" JSEESIONID", " remember-me " ) // Logout ๋’ค Cookie ์‚ญ์ œ (๋ฐœ๊ธ‰ ๋œ Cookie ๋ช… ๊ธฐ์žฌ)
        .addLogoutHandler(logoutHandler())				// Logout Handler(Logout ์ด ํ›„ ํ•˜๊ณ ์ž ํ•˜๋Š” ์ž‘์—…์ด ์žˆ๋‹ค๋ฉด Customํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ํ˜ธ์ถœ)
        .logoutSuccessHandler(logoutSuccessHandler())	// Logout ์„ฑ๊ณต ๋’ค Handler
}


์ฐธ๊ณ ๋กœ Spring Security๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ Logout์„ ์ฒ˜๋ฆฌํ•  ๋•Œ, Post ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ต๋‹ˆ๋‹ค.
Get ๋ฐฉ์‹์œผ๋กœ๋„ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” Post ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•„๋‘๋ฉด ์ข‹์„ ๊ฑฐ ๊ฐ™์•„์š”.


Logout ์ฒ˜๋ฆฌ

 


์ตœ์ดˆ ์œ„์™€ ๊ฐ™์ด Login ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•˜๊ณ , Sign in ๋‹จ์ถ”๋ฅผ ๋ˆŒ๋Ÿฌ์ฃผ์—ˆ์–ด์š”.



Logout ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด URI์— logout์„ ์ž…๋ ฅํ•ด ์ค๋‹ˆ๋‹ค.




์ด Page๋Š” Spring Security๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” Page์ž…๋‹ˆ๋‹ค.




๊ฐœ๋ฐœ์ž ๋„๊ตฌ๋ฅผ ํ†ตํ•ด ํ™•์ธ ํ•ด๋ณด๋ฉด Post ๋ฐฉ์‹์„ ์ด์šฉํ•ด์„œ logout ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด์—์š”.



Debug Mode๋กœ ํ™•์ธ ํ•ด ๋ณด๋ฉด Logout Button์„ ๋ˆŒ๋ €์„ ๋•Œ, Session์„ ๋ฌดํšจํ™” ํ•˜๋Š” ๋ถ€๋ถ„์— ์ง„์ž…ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.


๊ทธ๋Ÿฐ ๋’ค Success Handler๋ฅผ ํ†ตํ•ด ๋‹ค์‹œ Sign in Page๋กœ ์ด๋™ ์‹œํ‚ค๋Š” ๊ฒƒ์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ์–ด์š”.







        ๐Ÿ“ฆ ์ธ์ฆ API - LogoutFilter


์ด๋ฒˆ์—๋Š” Logout Filter์— ๋Œ€ํ•ด์„œ ๊ณต๋ถ€ํ•ด ๋ณผ๊ฒŒ์š”.

์ตœ์ดˆ ์ด์šฉ์ž๊ฐ€ Logout์„ ์š”์ฒญ(Post ๋ฐฉ์‹)ํ•˜๊ฒŒ ๋˜๋ฉด LogoutFilter๊ฐ€ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋˜์š”.

๊ทธ๋Ÿฌ๋ฉด AntPathRequestMatcher๊ฐ€ ์š”์ฒญ URI๊ฐ€ Logout ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ URI์ธ์ง€ ๊ฒ€์‚ฌ๋ฅผ ํ•˜๊ฒŒ ๋˜์š”.
๋งŒ์•ฝ URI๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด doFilter๊ฐ€ ๋ฐ›์•„ ๋‹ค์Œ Filter๋กœ ์ด๋™ํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ณ , ์ผ์น˜ํ•˜๊ฒŒ ๋˜๋ฉด
Authentication์ด ํ˜ธ์ถœ๋˜์–ด SecurityContext (ํ˜„์žฌ ์ด์šฉ์ž์˜ ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๊ฐ์ฒด)๋กœ ๋ถ€ํ„ฐ ์ธ์ฆ ๊ฐ์ฒด๋ฅผ ๊บผ๋‚ด ๋ฐ›์•„ SecutiryContextLogoutHandler ์ฆ‰, LogoutHandler์—๊ฒŒ ์ „๋‹ฌ์„ ํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด์—์š”. ํ•ด๋‹น Handler๋Š” Session์„ ๋ฌดํšจํ™”ํ•˜๊ณ , Cookie๋ฅผ ์‚ญ์ œํ•˜๊ณ , SecurityContextHolder.clearContext()์—์„œ SecutiryContext ๊ฐ์ฒด๋ฅผ ์‚ญ์ œํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด์—์š”. ๊ทธ๋ฆฌ๊ณ , ์ธ์ฆ ๊ฐ์ฒด๋„ null๋กœ ์ดˆ๊ธฐํ™” ํ•˜๋Š” ๊ฒƒ์ด์—์š”.

๋งŒ์•ฝ Post๊ฐ€ ์•„๋‹Œ Get ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ ์ž ํ•  ๋•Œ๋„ SecurityContextLogoutHandler๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์–ด์š”.

์œ„์˜ ์ž‘์—…์ด ์™„๋ฃŒ๊ฐ€ ๋˜๋ฉด LogoutFilter๋Š” SimpleUrlLogoutSuccessHandler๋ฅผ ํ˜ธ์ถœํ•ด์„œ Sign in Page๋กœ ์ด๋™ํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด์—์š”.






        ๐Ÿ“ฆ ์ธ์ฆ API - Remember Me ์ธ์ฆ


์œ„์™€ ๊ฐ™์ด Remember Me ๊ธฐ๋Šฅ์„ ์ด์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์–ด๋–ค์ผ์ด ๋ฒŒ์–ด์งˆ๊นŒ์š”?

์œ„์˜ ๊ธฐ๋Šฅ์€ Session์ด ๋งŒ๋ฃŒ๋˜๊ณ , ์›น ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ข…๋ฃŒ๋œ ๋’ค์—๋„ Application์ด ์ด์šฉ์ž๋ฅผ ๊ธฐ์–ตํ•˜๊ฒŒ ํ•˜๋Š” ๊ธฐ๋Šฅ์ด์—์š”.
์ฆ‰, ์ž๋™ Login ๊ธฐ๋Šฅ๊ณผ ์œ ์‚ฌํ•œ ๊ธฐ๋Šฅ์ด๋ผ๊ณ  ๋ณด๋ฉด ๋˜๋Š” ๊ฒƒ์ด์—์š”.


Remember-Me Cookie์— ๋Œ€ํ•œ Http Request๋ฅผ ํ™•์ธํ•˜๊ณ , Token ๊ธฐ๋ฐ˜ ์ธ์ฆ์„ ์ด์šฉํ•ด ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ํ•˜๊ณ , Token์ด ๊ฒ€์ฆ๊ดด๊ฒŒ ๋˜๋ฉด ์ด์šฉ์ž๋Š” Login์„ ํ•  ์ˆ˜ ์žˆ์–ด์š”.

์ด์šฉ์ž์˜ Life Cycle์€ ์•„๋ž˜์™€ ๊ฐ™์•„์š”.

์ธ์ฆ ์„ฑ๊ณต ( Remember-Me Cookie ์„ค์ •)
์ธ์ฆ ์‹คํŒจ ( Cookie ์กด์žฌ ์‹œ Cookie ๋ฌดํšจํ™”)
Logout ( Cookie ์กด์žฌ ์‹œ Cookie ๋ฌดํšจํ™”)



Spring Secutiry Config Class์—์„œ http.rememberMe()์„ ์„ค์ •ํ•˜๊ฒŒ ๋˜๋ฉด RememberMe ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ์–ด์š”.

protected void configure(HttpSecurity http) throws Exception {
	http.rememberMe()
    	.rememberMeParameter("remember")	// ๊ธฐ๋ณธ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ช…์€ remember-me
        .tokenValiditySeconds(3600)			// ๊ธฐ๋ณธ๊ฐ’์€ 14์ผ
        .alwaysRemember(true)				// Remember Me ๊ธฐ๋Šฅ์ด ํ™œ์„ฑํ™” ๋˜์ง€ ์•Š์•„๋„ ํ•ญ์ƒ ์‹คํ–‰ false๋ฅผ ๊ถŒ๊ณ 
        .userDetailsService(userDetailsService)
}



์ตœ์ดˆ userDetailsService๋ฅผ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด @RequiredArgsConstructor Lombok์„ ์ด์šฉํ•˜์—ฌ final member ๋ณ€์ˆ˜ UserDetailsService๋ฅผ ์ฃผ์ž…ํ•ด ์ฃผ์—ˆ์–ด์š”.

๊ฐ•์˜์—์„œ๋Š” @Autowired๋ฅผ ํ†ตํ•ด UserDetailsService๋ฅผ ์ฃผ์ž…ํ•˜๋Š”๋ฐ, Member ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์‚ฝ์ž…์€ ๊ถŒ๊ณ  ์‚ฌํ•ญ์ด ์•„๋‹ˆ๋ฏ€๋กœ ์œ„์™€ ๊ฐ™์ด ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ณ€๊ฒฝ ํ•ด ์ฃผ์—ˆ์–ด์š”.



๊ทธ๋Ÿฐ ๋’ค Logout ์„ค์ • ๋ฐ‘์— ์œ„์™€ ๊ฐ™์ด Remember Me ๊ด€๋ จ ์„ค์ •์„ ํ•ด ์ฃผ์—ˆ์–ด์š”.




Server๋ฅผ ์žฌ ๊ตฌ๋™ํ•˜๊ณ , ๋‹ค์‹œ Root Page์— ์ ‘๊ทผ์„ ํ•˜๋ฉด Login Page๋กœ ์ด๋™ํ•˜๊ฒŒ ๋˜๊ณ , ์œ„์™€ ๊ฐ™์ด Remember Me์— ๊ด€๋ จํ•œ Check Box๊ฐ€ ์ƒ๊ธด๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.




Remember Me Check Box์— Check๋ฅผ ํ•˜๊ณ  Login์„ ํ•ด ๋ณผ๊ฒŒ์š”.


์ด๋ ‡๊ฒŒ ์ธ์ฆ์ด ๋˜์—ˆ์–ด์š”.
์ธ์ฆ์ด ๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์€ Spring Security์—์„œ ์ด์šฉ์ž Session์ด ๋งŒ๋“ค์–ด ์กŒ๋‹ค๋Š” ๊ฒƒ์ด๊ณ , ํ•ด๋‹น Session์ด ์„ฑ๊ณตํ•œ ์ธ์ฆ ๊ฐ์ฒด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๊ฒƒ์ด์—์š”.


๊ฐœ๋ฐœ์ž ๋„๊ตฌ๋ฅผ ํ†ตํ•ด Cookie๋ฅผ ํ™•์ธํ•ด ๋ณด๋‹ˆ ์œ„์™€ ๊ฐ™์ด ๊ฐ’์ด ๋‹ด๊ฒจ ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.



ํ•ด๋‹น Page๋ฅผ ์ข…๋ฃŒํ–ˆ๋‹ค๊ฐ€ ๋‹ค์‹œ ์ ‘๊ทผ์„ ํ•˜๊ฒŒ ๋˜๋ฉด ๋ฐ”๋กœ ์ ‘์†์ด ๊ฐ€๋Šฅํ•œ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.


์ด๋Š” ์œ„์— ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์—์„œ ๋ณด์•˜๋“ฏ์ด Client๊ฐ€ Server๊ฐ€ ์ค€ JSessionID ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ๊ณ , ์ด๋ฅผ ๋‹ค์‹œ ์ง„์ž…ํ•  ๋•Œ, Server์—๊ฒŒ ๋„˜๊ฒจ ์ธ์ฆ์„ ํ†ต๊ณผํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด์—์š”.



EditThisCookie

๊ทธ๋Ÿผ ํฌ๋กฌ ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ ์ค‘ EditThisCookie๋ฅผ ํ†ตํ•ด Cookie๋ฅผ ํ™•์ธํ•ด ๋ณผ๊ฒŒ์š”.




์ด๋ ‡๊ฒŒ Cookie ์ •๋ณด๋ฅผ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ ๋ณด๋‹ค ๋” ๊ฐ„ํŽธํ•˜๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.





์ด ๊ณณ์—์„œ ํœด์ง€ํ†ต ๋ชจ์–‘์„ ๋ˆŒ๋Ÿฌ Cookie๋ฅผ ํ•œ๋ฒˆ ๋‚ ๋ ค ๋ณผ๊ฒŒ์š”!

์–ด๋–ค ์ผ์ด ๋ฐœ์ƒํ• ๊นŒ์š”?



Remember-Me๋Š” ์ œ์™ธํ•˜๊ณ , JSessionID๋ฅผ ์ง€์šฐ๊ณ  ๋‚˜์„œ ๋‹ค์‹œ ์ ‘์†์„ ํ•˜๊ฒŒ ๋˜๋ฉด ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ธ์ฆ ์ ˆ์ฐจ ์—†์ด ์ ‘์†์„ ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”. 

๋‹ค์‹œ Cookie๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด JSessionID๋„ ๋‹ค์‹œ ๋ฐ›์•„์˜จ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.



์ด๋ฒˆ์—๋Š” ๋‘˜ ๋‹ค ํ•œ๋ฒˆ ์ง€์›Œ๋ณผ๊ฒŒ์š”.


๋ชจ๋“  Cookie๋ฅผ ๋‹ค ๋‚ ๋ ธ๊ณ , ์ƒˆ๋กœ๊ณ ์นจ์„ ํ•ด ๋ณผ๊ฒŒ์š”.



๊ทธ๋Ÿผ Server๋Š” '์ฒ˜์Œ ๋ต™๊ฒ ์Šต๋‹ˆ๋‹ค!'๋ฅผ ํ•˜๋ฉด์„œ ๋ˆ„๊ตฌ์ธ์ง€๋ฅผ ๋ฌผ์–ด๋ณด๋Š” ๊ฒƒ์ด์—์š”.








        ๐Ÿ“ฆ ์ธ์ฆ API - RememberMeAuthenticationFilter

 


์ตœ์ดˆ RememberMeAuthenticationFilter๊ฐ€ ์ด์šฉ์ž์˜ ์š”์ฒญ์„ ๋ฐ›๊ฒŒ ๋˜๋ฉด ์–ด๋–ค ์ผ์ด ์ผ์–ด๋‚ ๊นŒ์š”?

์ฒซ๋ฒˆ์งธ๋Š” ๋ฐ”๋กœ Authentication ์ฆ‰, ์ธ์ฆ ๊ฐ์ฒด๊ฐ€ Null์ผ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋Š”๋ฐ, ์ธ์ฆ ๊ฐ์ฒด๋Š” ์œ„์—์„œ๋„ ์–ธ๊ธ‰ํ–ˆ์ง€๋งŒ, SecurityContext์— ์ €์žฅ์ด ๋˜์–ด ์žˆ์–ด์š”. ์ฆ‰, ์ด์šฉ์ž๊ฐ€ ์ธ์ฆ์„ ํ•˜๊ฒŒ ๋˜๋ฉด ์ธ์ฆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ฒŒ ๋˜๊ณ , ์ด ์ธ์ฆ ๊ฐ์ฒด๋ฅผ SecurityContext์— ๋‹ด๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด์—์š”. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ด์šฉ์ž๊ฐ€ ์ธ์ฆ์„ ํ•˜์˜€๋‹ค๋Š” ๊ฒƒ์€ ๋ฐ”๋กœ Authentication์ด Null์ด ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์ด์—์š”.

๋งŒ์•ฝ ์ด์šฉ์ž์˜ Session์ด ๋งŒ๋ฃŒ๋˜์—ˆ๊ฑฐ๋‚˜, Session์ด ์–ด๋– ํ•œ ์ด์œ ๋กœ ๋Š๊ฒจ์ ธ์„œ ๋” ์ด์ƒ Session ์•ˆ์—์„œ SecurityContext๋ฅผ ์ฐพ์ง€ ๋ชปํ•˜๊ณ , SecurityContext๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, SecurityContext ์•ˆ์— Authentication ๊ฐ์ฒด๋„ ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐ”๋กœ ์ฒซ๋ฒˆ์งธ ๊ฒฝ์šฐ์—์š”. ์ด ๋•Œ ๋ฐ”๋กœ RememberMeAuthenticationFilter๊ฐ€ ๋™์ž‘ํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด์—์š”.


๋งŒ์•ฝ Authentication์ด Null์ด ์•„๋‹ˆ๋ผ๋ฉด RememberMeAuthenticationFilter๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋ฐ, ๊ทธ ์ด์œ ๋Š” ์ด๋ฏธ ์ธ์ฆ ๊ฐ์ฒด๊ฐ€ ์žˆ๋‹ค๋Š” ์ด์•ผ๊ธฐ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์‹œ ์ธ์ฆ์„ ๋ฐ›์„ ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์ด์—์š”.

์ฆ‰, RememberMeAuthenticationFilter๊ฐ€ ๋™์ž‘ํ–ˆ๋‹ค๋Š” ๊ฒƒ์€ ์ธ์ฆ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ๋™์ž‘ํ•œ๋‹ค๊ณ  ๋ณด๋ฉด ๋˜๋Š” ๊ฒƒ์ด์—์š”.


๋‘๋ฒˆ์งธ๋Š” ์ด์šฉ์ž๊ฐ€ Form ์ธ์ฆ์„ ๋ฐ›์„ ๋‹น์‹œ Remember Me ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™”ํ•œ ๋’ค ์ธ์ฆ์„ ํ•œ ๋’ค Server๋กœ ๋ถ€ํ„ฐ Remember Me Cookie๋ฅผ ๋ฐœ๊ธ‰ ๋ฐ›์€ ๊ฒฝ์šฐ์— ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์ด์—์š”.


์œ„์˜ ๊ฒฝ์šฐ ์ด์šฉ์ž๊ฐ€ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์ข…๋ฃŒํ–ˆ๊ฑฐ๋‚˜ ํ–ˆ์„ ์‹œ ์ด์šฉ์ž์˜ Session์€ ๋ฌดํšจํ™”๋˜๋‚˜, ๋‹ค์‹œ Server์— ์ ‘๊ทผํ•  ๋•Œ, Request Header์— Remember Me Cookie ๊ฐ’์„ ๊ฐ€์ง€๊ณ , ์ ‘๊ทผํ•˜๊ฒŒ ๋˜๋ฉด ํ•ด๋‹น Cookie๋ฅผ ์ด์šฉํ•˜์—ฌ ์ธ์ฆ์„ ์‹œ๋„ํ•˜๊ฒŒ ๋œ๋‹ต๋‹ˆ๋‹ค.


RememberMeAuthenticationFilter๊ฐ€ ๋™์ž‘ํ•˜๊ฒŒ ๋˜๋ฉด RememberMeServies๊ฐ€ ํ˜ธ์ถœ ๋˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด ์นœ๊ตฌ๋Š” ๋‘ ๊ฐœ์˜ ๊ตฌํ˜„์ฒด๋ฅผ ๋ณด์œ ํ•˜๊ณ  ์žˆ๋Š” ์นœ๊ตฌ์—์š”. ๋ฐ”๋กœ TokenBasedRememberMeServices์™€ PersistentTokenBasedRememberMeServices์—์š”. ์ด ๋‘ ์นœ๊ตฌ๊ฐ€ ๋ฐ”๋กœ Remember Me ์ธ์ฆ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ์นœ๊ตฌ๋“ค์ด์—์š”.

TokenBasedRememberMeServices๋Š” Memory์— ์ €์žฅ๋œ Token๊ณผ ์ด์šฉ์ž๊ฐ€ ์š”์ฒญ์„ ๋ณด๋ƒˆ์„ ์‹œ ๋ณด๋‚ธ Cookie์•ˆ์— ์žˆ๋Š” Token๊ณผ ๋น„๊ตํ•ด์„œ  ์ธ์ฆ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ์นœ๊ตฌ์—์š”. 

๊ธฐ๋ณธ์ ์œผ๋กœ ์ด Token์€ 14์ผ์ด๋ผ๋Š” ๊ธฐ๊ฐ„ ๋งŒ๋ฃŒ๊ฐ€ ์ •ํ•ด์ ธ ์žˆ์–ด์š”.

PersistentTokenBasedRememberMeServices๋Š” Persistent ์ฆ‰, ์˜๊ตฌ์ ์œผ๋กœ ์ด์šฉํ•˜๋Š” ๋ฐฉ์‹์ธ๋ฐ, DB์— Token๊ฐ’์„ ์ €์žฅํ•˜๊ณ ,  ์ด์šฉ์ž๊ฐ€ ์š”์ฒญ์„ ๋ณด๋ƒˆ์„ ์‹œ ๋ณด๋‚ธ Cookie์•ˆ์— ์žˆ๋Š” Token๊ณผ ๋น„๊ตํ•ด์„œ  ์ธ์ฆ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ์นœ๊ตฌ์—์š”. 

์ด์ œ Remember Me Token Cookie๋ฅผ ์ถ”์ถœํ•˜๊ฒŒ ๋˜๊ณ , Token์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด doFilter๋ฅผ ํ†ตํ•ด ๋‹ค์Œ Filter๊ฐ€ ๋™์ž‘ํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๊ฐ€ ๋˜๊ณ , Token์ด ์žˆ๋‹ค๋ฉด Remember Me Token์€ ๋‚˜๋ฆ„์˜ ๊ทœ์น™๋“ค์ด ์žˆ๋Š”๋ฐ, ์ด ๊ทœ์น™๋“ค์ด ์ž˜ ์ง€์ผœ์ ธ์„œ ์™”๋Š”์ง€๋Š” ํ™•์ธํ•˜๊ฒŒ ๋˜์š”. ๋งŒ์•ฝ ์•„๋‹ˆ๋ผ๋ฉด Exception์ด ํ„ฐ์ง€๊ฒŒ ๋˜๊ณ , ์ž˜ ์ง€์ผœ์ ธ์„œ ์™”๋‹ค๋ฉด ์ €์žฅ๋˜์–ด ์žˆ๋Š” Token๊ณผ ์ด์šฉ์ž๊ฐ€ ๋ณด๋‚ธ Token์ด ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธ์„ ํ•ฉ๋‹ˆ๋‹ค.

์ผ์น˜ํ•˜์ง€ ์•Š์œผ๋ฉด ์—ญ์‹œ Exception์ด ํ„ฐ์ง€๊ฒŒ ๋˜๊ณ , ์ผ์น˜ํ•˜๋ฉด ํ•ด๋‹น ์ด์šฉ์ž ๊ณ„์ •์ด DB์— ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ์„ ํ•˜๊ณ , ์กด์žฌํ•œ๋‹ค๋ฉด ์ƒˆ๋กœ์šด Authentication ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์„œ  AuthenticationManager์—๊ฒŒ ์ „๋‹ฌํ•˜์—ฌ ์ธ์ฆ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด์—์š”.

์—ญ์‹œ ์ด์šฉ์ž๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด Exception์ด ํ„ฐ์ง„๋‹ต๋‹ˆ๋‹ค.

Remember Me Token์—๋Š” ์ด์šฉ์ž์˜ Password ์ •๋ณด, ID ์ •๋ณด, Token ๋งŒ๋ฃŒ์ผ ์ •๋ณด ๋“ฑ์ด ๋‹ด๊ฒจ ์žˆ์–ด์š”.

 




        ๐Ÿ“ฆ ์ธ์ฆ API - AnonymousAuthenticationFilter

 


AnonymousAuthenticationFilter๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๋™์ž‘ํ•˜๋Š” ์นœ๊ตฌ์—์š”.


• ์ต๋ช… ์ด์šฉ์ž ์ธ์ฆ ์ฒ˜๋ฆฌ Filter.
• ์ต๋ช… ์ด์šฉ์ž์™€ ์ธ์ฆ ์ด์šฉ์ž๋ฅผ ๊ตฌ๋ถ„ํ•ด์„œ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์šฉ๋„๋กœ ์‚ฌ์šฉ.

• ํ™”๋ฉด์—์„œ ์ธ์ฆ ์—ฌ๋ถ€ ๊ตฌํ˜„ ์‹œ isAnonymous()์™€ isAuthenticated()๋กœ ๊ตฌ๋ถ„ํ•ด์„œ ์‚ฌ์šฉ.
• ์ธ์ฆ ๊ฐ์ฒด๋ฅผ Session์— ์ €์žฅํ•˜์ง€ ์•Š์Œ.


์›๋ž˜ ์ด์šฉ์ž๊ฐ€ ์ธ์ฆ์„ ํ•˜๊ฒŒ ๋˜๋ฉด ์ธ์ฆ ๊ฐ์ฒด์— ํ•ด๋‹น ์ด์šฉ์ž์— ์ •๋ณด๋ฅผ ๋‹ด๊ฒŒ ๋˜๊ณ , ์ด๋ฅผ Session์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฐ๋ฐ, ์ธ์ฆ์„ ๋ฐ›์ง€ ์•Š๊ฒŒ ๋˜๋ฉด ์ธ์ฆ ๊ฐ์ฒด ๊ฐ’์€ ๋‹น์—ฐํžˆ Null์ด ๋ ๊ฑฐ์—์š”.


ํ•˜์ง€๋งŒ, AnonymousAuthenticationFilter๋Š” ์ธ์ฆ ๋ฐ›์ง€ ์•Š์€ ์ด์šฉ์ž์— ๋Œ€ํ•œ ์ธ์ฆ ๊ฐ์ฒด๋ฅผ Null๋กœ ๋‘๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๊ณ , ๋ณ„๋„ ์ต๋ช… ์ด์šฉ์ž์šฉ ์ธ์ฆ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด์—์š”.


์ตœ์ดˆ ์ด์šฉ์ž๊ฐ€ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋˜๋ฉด AnonymousAuthenticationFilter๊ฐ€ ์š”์ฒญ์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋ฉด ํ˜„์žฌ ์š”์ฒญ์„ ๋ณด๋‚ธ ์ด์šฉ์ž๊ฐ€ ์ธ์ฆ ๊ฐ์ฒด๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋จผ์ € ํŒ๋‹จํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ธ์ฆ์„ ๋ฐ›์•˜๋‹ค๋ฉด SecurityContext์— ํ•ด๋‹น ์ด์šฉ์ž์— ์ธ์ฆ ๊ฐ์ฒด๊ฐ€ ์ €์žฅ์ด ๋˜์–ด ์žˆ์„ ๊ฒƒ์ด์—์š”.

SecurityContext ์•ˆ์— ์ธ์ฆ ๊ฐ์ฒด๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์€ ํ•ด๋‹น ์ด์šฉ์ž๋Š” ์ธ์ฆ์„ ๋ฐ›์ง€ ์•Š์•˜๋‹ค๊ณ  ํŒ๋‹จํ•  ์ˆ˜ ์žˆ์–ด์š”.

๋งŒ์•ฝ ์ธ์ฆ ๊ฐ์ฒด๊ฐ€ ์กด์žฌํ•œ๋‹ค๋ฉด
AnonymousAuthenticationFilter๋Š” ๋ณ„๋‹ค๋ฅธ ์ž‘์—…์—†์ด doFilter๋ฅผ ํ†ตํ•ด ๋‹ค์Œ Filter๋กœ ์ž‘์—…์„ ๋„˜๊น๋‹ˆ๋‹ค.

์ธ์ฆ ๊ฐ์ฒด๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ต๋ช… ์ด์šฉ์ž๋กœ ํŒ๋‹จํ•ด์„œ AnonymousAuthenticationToken ์ฆ‰, ์ต๋ช… ์ด์šฉ์ž์šฉ Token์„ ์ƒ์„ฑ์„ ํ•ด์„œ Null๋กœ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด์—์š”.

๊ทธ๋Ÿฐ ๋’ค SecurityContextHolder ์•ˆ์— SecurityContext์— ์ต๋ช… ์ด์šฉ์ž์šฉ ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ธ์ฆ์„ ๊ฑฐ์น˜์ง€ ์•Š์•˜์ง€๋งŒ, ์ธ์ฆ์„ ๋ฐ›์•˜์„ ๋•Œ์™€ ๋™์ผํ•˜๊ฒŒ SecurityContext ์•ˆ์— ์ธ์ฆ ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜๋„๋ก ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ๊ฒƒ์ด์—์š”.

isAnonymous() ๊ฐ’์ด True์ผ ๋•Œ ์ต๋ช… ์ด์šฉ์ž๋ผ๋Š” ๊ฒƒ์ด ํ™•์ธ๋˜๊ธฐ ๋•Œ๋ฌธ์— Menu๋ฅผ ๊ตฌ์„ฑํ•  ๋•Œ, Login Page๋กœ ์ด๋™ํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๊ณ , 

isAuthenticated() ๊ฐ’์ด True๋ผ๋Š” ๊ฒƒ์€ ์ธ์ฆ์„ ๋ฐ›์€ ์ด์šฉ์ž๋ผ๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— Menu๋ฅผ ๊ตฌ์„ฑํ•  ๋•Œ, Logout Button๊ณผ ๊ธฐ๋Šฅ์ด ํ™œ์„ฑํ™” ๋˜๋„๋ก ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด์—์š”.

 

 

 

 

        ๐Ÿ“ฆ ์ธ์ฆ API - ๋™์‹œ Session Controll / Session ๊ณ ์ • ๋ณดํ˜ธ / Session ์ •์ฑ…


๋™์‹œ Session ์ œ์–ด๋ž€ ๋ฌด์—‡์ผ๊นŒ์š”? ํ•˜๋‚˜์˜ ๊ณ„์ •์œผ๋กœ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ธ์ฆ์„ ๋ฐ›์„ ๋•Œ, ์ƒ์„ฑ ๋œ Session์— ๊ฐœ์ˆ˜๊ฐ€ ์ดˆ๊ณผ๋˜์—ˆ์„ ๋•Œ, ์–ด๋–ค์‹์œผ๋กœ ์ด๋Ÿฐ Session์„ ์ œ์–ดํ•  ๊ฒƒ์ธ์ง€๋ฅผ ์ •ํ•˜๋Š” ๋ถ€๋ถ„ ์ž…๋‹ˆ๋‹ค.

Spring Security๋Š” ์ด๋Ÿด ๋•Œ, ๋‘ ๊ฐ€์ง€๋กœ Handling์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.


์ตœ์ดˆ ์ตœ๋Œ€ Session ํ—ˆ์šฉ ๊ฐœ์ˆ˜๊ฐ€ ์ดˆ๊ณผํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •์„ ํ•ด ๋ณผ๊ฒŒ์š”. ์ด ๋•Œ, ํ•˜๋‚˜์˜ ๊ณ„์ •์œผ๋กœ ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ๋Š” Session์— ์ตœ๋Œ€ ๊ฐœ์ˆ˜๋Š” ํ•˜๋‚˜๋ผ๊ณ  ๊ฐ€์ •์„ ํ•ด ๋ณผ๊ฒŒ์š”.

์ด ๋•Œ, ์ด์ „ ์ด์šฉ์ž Session์„ ๋งŒ๋ฃŒ ์‹œํ‚ค๋Š” ์ „๋žต์„ ํ•œ๋ฒˆ ์‚ดํŽด ๋ณผ๊ฒŒ์š”.

์ตœ์ดˆ ์ด์šฉ์ž 1์ด Server์— Login์„ ํ•˜๊ณ , Server๋Š” ํ•ด๋‹น ์ด์šฉ์ž์—๊ฒŒ Session์„ ์ƒ์„ฑํ•ด์„œ ์ „๋‹ฌํ•ด ์ค๋‹ˆ๋‹ค.
๊ทธ๋ ‡๋‹ค๋ฉด Server์—๋Š” ์ด์šฉ์ž 1์— ๋Œ€ํ•œ Session์ด ์ƒ์„ฑ๋˜์–ด ์žˆ์„ ๊ฑฐ์—์š”.

๊ทธ๋Ÿฐ ๋’ค ์ด์šฉ์ž 2๊ฐ€ Login์„ ์š”์ฒญ์„ ํ•ด์š”. ๋‹น์—ฐํžˆ ์ด์šฉ์ž 1์ด ์ด์šฉํ–ˆ๋˜ ๊ณ„์ • ์ •๋ณด๋ฅผ ๋™์ผํ•˜๊ฒŒ ์ด์šฉํ•˜์—ฌ Login์„ ํ•˜๋Š” ๊ฒƒ์ด์—์š”.

๊ทธ๋Ÿฌ๋ฉด ์ด์šฉ์ž 2์— ๋Œ€ํ•œ Session์ด ์ƒˆ๋กญ๊ฒŒ ๋งŒ๋“ค์–ด์ ธ์„œ ๋ฐœ๊ธ‰๋ฉ๋‹ˆ๋‹ค.

Server์—๋Š” ์ด์šฉ์ž 1๊ณผ ์ด์šฉ์ž 2์— ๋Œ€ํ•œ Session์ด ์ €์žฅ๋˜์–ด ์žˆ๊ฒ ๋„ค์š”.
๊ทธ๋ ‡๋‹ค๋ผ๋Š” ๊ฑด Server์—๋Š” ๋™์ผํ•œ ๊ณ„์ •์— ๋Œ€ํ•œ Session์ด ๋‘ ๊ฐœ๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์ด์—์š”.

์œ„์—์„œ ์˜ˆ์‹œ๋Š” ์ตœ๋Œ€ Session ํ—ˆ์šฉ ๊ฐœ์ˆ˜๊ฐ€ 1๊ฐœ๋ผ๊ณ  ํ–ˆ์–ด์š”.
๊ทธ๋Ÿผ ์ดˆ๊ณผ๊ฐ€ ๋œ ๊ฒƒ์ด๊ณ , ์ด ๋•Œ, Server๋Š” ์ด ์ „ Login ์ธ์ฆ์— ๋Œ€ํ•œ Session ๋งŒ๋ฃŒ๊ฐ€ ๋˜๋„๋ก ์„ค์ •ํ•˜๊ฒŒ ๋˜๋ฉด
Server๋Š” ์ด ์ „ ์ด์šฉ์ž์ธ ์ด์šฉ์ž 1์— ๋Œ€ํ•œ Session์„ ์ฆ‰์‹œ ๋งŒ๋ฃŒ ์‹œ์ผœ ๋ฒ„๋ ค์š”.

์ด ๋ฐฉ์‹์ด ๋ฐ”๋กœ ๋™์‹œ Session ์ œ์–ด์—์„œ ์ด์ „ ์ด์šฉ์ž Session์„ ๋งŒ๋ฃŒ ์‹œํ‚ค๋Š” ์ „๋žต์ด์—์š”.


๋‘๋ฒˆ์งธ๋Š” ํ˜„์žฌ ์ด์šฉ์ž ์ธ์ฆ์„ ์‹คํŒจํ•˜๋„๋ก ํ•˜๋Š” ์ „๋žต์ด์—์š”.
์ตœ์ดˆ ์ด์šฉ์ž 1์ด Login์„ ์‹œ๋„ํ•ด์„œ Server๋Š” Session์„ ์ƒ์„ฑํ•˜๊ณ , ๋ฐœ๊ธ‰์„ ํ•ด ์ค๋‹ˆ๋‹ค.
๊ทธ๋Ÿฐ ๋’ค ์ด์šฉ์ž 2๊ฐ€ ๋™์ผ ๊ณ„์ •์œผ๋กœ Login์„ ์‹œ๋„ํ•˜๊ฒŒ ๋˜๋ฉด ์ธ์ฆ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ Login์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•ด ๋ฒ„๋ฆฌ๋Š” ์ „๋žต์ด์—์š”.

์ฒซ๋ฒˆ์งธ๋Š” ์ฒซ๋ฒˆ์งธ ์ด์šฉ์ž์— ๋Œ€ํ•œ Session์„ ๋งŒ๋ฃŒ ์‹œํ‚ค๊ณ , ๋‘๋ฒˆ์งธ๋Š” ๋‘๋ฒˆ์งธ ์ด์šฉ์ž์— ๋Œ€ํ•ด ์ธ์ฆ์„ ํ•˜์ง€ ๋ชปํ•˜๋„๋ก ๋ง‰๋Š” ์ „๋žต์ด์—์š”.


๋™์‹œ Session ์ œ์–ด๋Š” http.sessionManagement()๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ํ•˜๋Š”๋ฐ, ์ด๋Š” Session ๊ด€๋ฆฌ ๊ธฐ๋Šฅ์ด ์ž‘๋™ํ•˜๊ฒŒ ํ•˜๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

protected void configure(HttpSecurity http) throws Exception {
	http
    	.sessionManagement()
    	.maximumSessions(1)						// ์ตœ๋Œ€ ํ—ˆ์šฉ ๊ฐ€๋Šฅ Session ์ˆ˜ ์ง€์ • ( -1์€ ๋ฌด์ œํ•œ Session ํ—ˆ์šฉ)
        .maxSessionsPreventsLogin(true)			// ๋™์‹œ Login ์ฐจ๋‹จ(์ด์ „ ์ด์šฉ์ž Session์„ ๋งŒ๋ฃŒ ์‹œํ‚ค๋Š” ์ „๋žต), flase์ผ ๊ฒฝ์šฐ ๊ธฐ์กด Session ๋งŒ๋ฃŒ๋กœ ๋™์ž‘(Default) ์ด์šฉ์ž ์ธ์ฆ์„ ์‹คํŒจํ•˜๋„๋ก ํ•˜๋Š” ์ „๋žต
        .invalidSessionUrl("/invalid")			// Session์ด ์œ ํšจํ•˜์ง€ ์•Š์„ ๋•Œ, ์ด๋™ํ•  Page ์ง€์ •
        .expiredUrl("/expired")					// Session์ด ๋งŒ๋ฃŒ๋˜์—ˆ์„ ๊ฒฝ์šฐ ์ด๋™ํ•  Page ์ง€์ •
๋ฐ˜์‘ํ˜•





์ด๋ฒˆ์—๋Š” ์„ธ์…˜ ๊ณ ์ • ๋ณดํ˜ธ์— ๋Œ€ํ•ด ๊ณต๋ถ€ ํ•ด ๋ณผ๊ฒŒ์š”.


์œ„์— ๊ทธ๋ฆผ์— ๋Œ€ํ•ด ํ•˜๋‚˜ํ•˜๋‚˜ ์‚ดํŽด ๋ณผ๊ฒŒ์š”.

์ตœ์ดˆ ๊ณต๊ฒฉ์ž๊ฐ€ Server์— ์ ‘์†์„ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด Server๋Š” ๊ณต๊ฒฉ์ž์—๊ฒŒ JSessionID๊ฐ€ ๋‹ด๊ธด Cookie๋ฅผ ๋ฐœ๊ธ‰ํ•ด ์ค๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ณต๊ฒฉ์ž๋Š” ์ž์‹ ์ด Server์—๊ฒŒ ๋ฐ›์€ JSessionID ๊ฐ’์„ ์„ค๋Ÿ‰ํ•œ ์ด์šฉ์ž์—๊ฒŒ ์‹ฌ์–ด ๋†“๋Š” ์ž‘์—…์„ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋’ค ์ด์šฉ์ž๋Š” ๊ณต๊ฒฉ์ž๊ฐ€ ์‹ฌ์–ด๋†“์€ JSessionID๋ฅผ ๊ฐ€์ง€๊ณ , Login์„ ์‹œ๋„ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Server๋Š” ์ •์ƒ์ ์ธ ์ด์šฉ์ž๋ผ ํŒ๋‹จํ•˜๊ณ , Login ์ฒ˜๋ฆฌ๋ฅผ ํ•  ๊ฒƒ์ด์—์š”.

์ด ๋•Œ๋ถ€ํ„ฐ ๊ณต๊ฒฉ์ž๋Š” ์—„์ฒญ๋‚œ ์ผ์„ ํ•ด๋‚ผ ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š”๋ฐ, ๊ณต๊ฒฉ์ž์™€ ์ด์šฉ์ž์˜ JSessionID ๊ฐ’์ด ๊ฐ™๋‹ค๋Š” ๊ฑด ๊ณต๊ฒฉ์ž๋Š” ์ด์šฉ์ž์˜ ์ •๋ณด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด ๋ฉ๋‹ˆ๋‹ค.

์ฆ‰, ๊ณต๊ฒฉ์ž๋Š” ๋”ฐ๋กœ ์ธ์ฆ์„ ๋ฐ›์ง€ ์•Š์•„๋„ ์ด์šฉ์ž์ธ ์ฒ™ ์œ„์žฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์ด์—์š”.

์ด ๊ณต๊ฒฉ ๊ธฐ๋ฒ•์ด ๋ฐ”๋กœ Session ๊ณ ์ • ๊ณต๊ฒฉ ๊ธฐ๋ฒ•์ด์—์š”.

์œ„์˜ ๊ณต๊ฒฉ ๊ธฐ๋ฒ•์„ ๋ฐฉ์–ดํ•˜๊ธฐ ์œ„ํ•ด Spring Security๋Š” Session ๊ณ ์ • ๋ณดํ˜ธ ๊ธฐ๋ฒ•์„ ๋งŒ๋“ค์–ด ๋†จ์–ด์š”.

๊ทธ๋Ÿฐ ์–ด๋–ค ๋ฐฉ๋ฒ•์œผ๋กœ ์ด ๊ณต๊ฒฉ์„ ๋ง‰์•„๋‚ด๋„๋ก ๋งŒ๋“ค์–ด ๋†จ์„๊นŒ์š”?

์ด์šฉ์ž๊ฐ€ ๊ณต๊ฒฉ์ž๊ฐ€ ์‹ฌ์–ด๋†“์€ JSessionID ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์ธ์ฆ ์‹œ๋„๋ฅผ ํ•  ๋•Œ, Server๊ฐ€ ์ƒˆ๋กœ์šด Session์„ ๋ฐœ๊ธ‰ํ•˜๊ณ , ์ƒˆ๋กœ์šด Cookie๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ์ด ๊ณต๊ฒฉ์„ ๋ง‰์•„๋‚ด๊ณ  ์žˆ์–ด์š”.


Session ๊ณ ์ • ๋ณดํ˜ธ๋Š” http.sessionManagement()๋ฅผ ํ†ตํ•ด ํ™œ์„ฑํ™” ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด ์นœ๊ตฌ๋ฅผ ์ด์šฉํ•˜๋ฉด Session ๊ด€๋ฆฌ ๊ธฐ๋Šฅ์ด ํ™œ์„ฑํ™” ๋œ๋‹ต๋‹ˆ๋‹ค.

protected void configure(HttpSecurity http) throws Exception {
	http
    	.sessionManagement()
        .sessionFixation().changeSessionId() 	// Default Value -> non, migrateSession, new Session์ด ์กด์žฌ
}


changeSessionId() ๋Š” ์ด์šฉ์ž๊ฐ€ ์ธ์ฆ์— ์„ฑ๊ณตํ•˜๊ฒŒ ๋˜๋ฉด ํ•ด๋‹น ์ด์šฉ์ž์— Session์€ ๊ทธ๋Œ€๋กœ ๋‘๊ณ , Session ID ๊ฐ’๋งŒ ๋ณ€๊ฒฝ์„ ํ•ฉ๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ ์ด ์นœ๊ตฌ๋Š” ์„œ๋ธ”๋ฆฟ 3.1์—์„œ ๊ธฐ๋ณธ๊ฐ’์ด์—์š”.

migrateSession()์˜ ๊ฒฝ์šฐ๋Š” Session๊ณผ Session ID๊ฐ’ ๋ชจ๋‘ ์ƒˆ๋กญ๊ฒŒ ๋งŒ๋“ค์–ด ์ง€๋Š” ๊ฒƒ์ด์—์š”. ๊ทธ๋ฆฌ๊ณ  ์ด ์นœ๊ตฌ๋Š” ์„œ๋ธ”๋ฆฟ 3.1 ์ดํ•˜์—์„œ ๊ธฐ๋ณธ๊ฐ’์ด์—์š”.

์œ„ ๋‘ ์นœ๊ตฌ๋“ค์€ ์ƒˆ๋กญ๊ฒŒ Session์ด ์ƒ์„ฑ๋˜๊ธฐ ์ด ์ „์— ์„ค์ •๋œ ๊ฐ’์„ ๋ชจ๋‘ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋Š” ์นœ๊ตฌ๋“ค์ด์—์š”.


newSession()์˜ ๊ฒฝ์šฐ Session๊ณผ JSessionID ๋ชจ๋‘ ์ƒˆ๋กญ๊ฒŒ ๋ฐœ๊ธ‰๋˜๋ฉฐ, ์ด ์ „์— ์„ค์ •๋œ ๊ฐ’ ๋ชจ๋‘๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๊ณ , ์ƒˆ๋กญ๊ฒŒ ์„ค์ •ํ•ด์•ผ ํ•˜๋Š” ์นœ๊ตฌ์—์š”.

๋งˆ์ง€๋ง‰์œผ๋กœ none์€ ์˜๋ฏธ๊ฐ€ ์—†์–ด์š”. ์ด๋ ‡๊ฒŒ ํ•ด ๋†“์œผ๋ฉด ์œ„์˜ ๊ณต๊ฒฉ ๊ธฐ๋ฒ•์— ๋‹นํ•  ์ˆ˜ ๋ฐ–์— ์—†์Šต๋‹ˆ๋‹ค.

์œ„์˜ ๋‚ด์šฉ์€ ์šฐ๋ฆฌ๊ฐ€ ์‹ค์ œ์ ์œผ๋กœ Coding์„ ํ•˜์ง€ ์•Š์•„๋„ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ž‘๋™๋˜๊ฒŒ Spring Security๊ฐ€ ์ž‘๋™ํ•˜๊ณ  ์žˆ์–ด์š”.




์ด๋ฒˆ์—๋Š” Session ์ •์ฑ…์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•ด ๋ณผ๊ฒŒ์š”.

protected void configure(HttpSecurity http) throws Exception {
	http
    	.sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy. If_Required)
}


• SessionCreationPolicy.Always : Spring Security๊ฐ€ ํ•ญ์ƒ Session ์ƒ์„ฑ.
• SessionCreationPlicy.If_Required : Spring Security๊ฐ€ ํ•„์š” ์‹œ Session ์ƒ์„ฑ (Default Value).
• SessionCreationPolicy.Never : Spring Security๊ฐ€ Session์„ ์ƒ์„ฑํ•˜์ง€ ์•Š์ง€๋งŒ, ์ด๋ฏธ Session์ด ์กด์žฌํ•˜๋ฉด ์‚ฌ์šฉ.
• SessionCreationPolicy.Stateless : Spring Security๊ฐ€ Session์„ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ , Session์ด ์กด์žฌํ•ด๋„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ.
(Session ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๋•Œ ์‚ฌ์šฉ)







        ๐Ÿ“ฆ ์ธ์ฆ API - SessionManagementFilter


1. Session ๊ด€๋ฆฌ

  • ์ธ์ฆ ์‹œ ์ด์šฉ์ž์˜ Session ์ •๋ณด๋ฅผ ๋“ฑ๋ก, ์กฐํšŒ, ์‚ญ์ œ ๋“ฑ Session ์ด๋ ฅ ๊ด€๋ฆฌ.

2. ๋™์‹œ์  Session ์ œ์–ด

  • ๋™์ผ ๊ณ„์ •์œผ๋กœ ์ ‘์†์ด ํ—ˆ์šฉ๋˜๋Š” ์ตœ๋Œ€ Session ์ˆ˜ ์ œํ•œ.

3. Session ๊ณ ์ • ๋ณดํ˜ธ

  • ์ธ์ฆ ํ•  ๋•Œ๋งˆ๋‹ค Session Cookie๋ฅผ ์ƒˆ๋กœ ๋ฐœ๊ธ‰ํ•˜์—ฌ ๊ณต๊ฒฉ์ž์˜ Cookie ์กฐ์ž‘ ๋ฐฉ์ง€.

4. Session ์ƒ์„ฑ ์ •์ฑ…

  • Always, If_Required, Never, Stateless




        ๐Ÿ“ฆ ์ธ์ฆ API -  ConcurrentSessionFilter

์ด ์นœ๊ตฌ๋Š” ์œ„์˜ SessionManagementFilter์—์„œ ๋™์‹œ์  Session ์ œ์–ด๋ฅผ ํ•จ๊ป˜ ์ฒ˜๋ฆฌํ•˜๋Š” ์นœ๊ตฌ์—์š”.
์ฆ‰, ์„œ๋กœ ์—ฐ๊ณ„์—์„œ ๋™์‹œ์  Session ์ œ์–ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. 



  • ๋งค ์š”์ฒญ ๋งˆ๋‹ค ํ˜„์žฌ ์ด์šฉ์ž์˜ Session ๋งŒ๋ฃŒ ์—ฌ๋ถ€ ํ™•์ธ.
  • Session ๋งŒ๋ฃŒ ์‹œ ์ฆ‰์‹œ ๋งŒ๋ฃŒ ์ฒ˜๋ฆฌ.

Session.isExpired() == true

  • Logout ์ฒ˜๋ฆฌ.
  • ์ฆ‰์‹œ Error Page ์‘๋‹ต : " This session has been expired "



์ด๋ฒˆ์—๋Š” SessionManagementFilter์™€ ConcurrentSessionFilter๋ฅผ ํ•จ๊ป˜ ๊ณต๋ถ€ํ•ด ๋ณผ๊ฒŒ์š”.
์ด ๋‘ ์นœ๊ตฌ๊ฐ€ ๋™์‹œ์  Session ์ œ์–ด๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ, ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ์•Œ์•„๋ด์š”.



์ตœ์ดˆ ์ด์šฉ์ž๊ฐ€ Login์„ ํ•˜๋ ค๊ณ  ํ•  ๋•Œ, ์ด๋ฏธ ๋ˆ„๊ตฐ๊ฐ€ Login์„ ํ•˜์˜€๊ณ , Session์ด ์ƒ์„ฑ๋œ ์ƒํ™ฉ์ด์—์š”.
๋งŒ์•ฝ ์ตœ๋Œ€ ํ—ˆ์šฉ Session ๊ฐœ์ˆ˜๊ฐ€ 1๊ฐœ๋ผ๊ณ  ํ–ˆ์„ ๋•Œ, ์ตœ๋Œ€ ํ—ˆ์šฉ Session ๊ฐœ์ˆ˜๊ฐ€ ์ดˆ๊ณผ๊ฐ€ ๋œ ๊ฒƒ์ด๊ณ , ์ด ๋•Œ, ๋™์‹œ Session ์ œ์–ด์—์„œ โŒœ ์ด์ „ ์ด์šฉ์ž Session ๋งŒ๋ฃŒ โŒŸ ์ •์ฑ…์„ ์ด์šฉํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ–ˆ์„ ๋•Œ, ์ด์ „ Login์„ ํ•œ ์ด์šฉ์ž์— Session์„ ๋งŒ๋ฃŒ ์‹œํ‚ค๋Š”๋ฐ, ์ด๋ฅผ session.expireNow()๋ฅผ ํ†ตํ•ด์„œ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด ๋•Œ, ์ด ์ „์— ์ ‘์†ํ–ˆ๋˜ ์ด์šฉ์ž๊ฐ€ Login ์™ธ์— ๋‹ค๋ฅธ Request๋ฅผ ๋ณด๋‚ธ๋‹ค๊ณ  ํ•˜๋ฉด
session.expireNow()๋ฅผ ํ†ตํ•ด ์ด๋ฏธ Session์ด ๋งŒ๋ฃŒ๊ฐ€ ๋˜๋„๋ก ์ฒ˜๋ฆฌ๊ฐ€ ๋œ ๋’ค์˜ Request๊ฐ€ ๋“ค์–ด์˜จ ๊ฒƒ์ด์—์š”.

์ด ๋•Œ, ์ด ์ „ ์ด์šฉ์ž์— Request๋ฅผ ConcurrentSessionFilter๊ฐ€ ๋งค Request ๋งˆ๋‹ค ์ด์šฉ์ž์˜ Session ๋งŒ๋ฃŒ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด ์ „ ์ด์šฉ์ž์— ๋Œ€ํ•œ Session ๋งŒ๋ฃŒ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•  ๋•Œ, SessionManagementFilter ์•ˆ์—์„œ ์ด ์ „ ์ด์šฉ์ž์˜ Session์„ ๋งŒ๋ฃŒ ์‹œ์ผฐ๋˜ ์„ค์ •๊ฐ’์„ ์ฐธ์กฐํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด ๋•Œ,
SessionManagementFilter ์•ˆ์—์„œ ์ด ์ „ ์ด์šฉ์ž์˜ ๋Œ€ํ•œ Session์ด ๋งŒ๋ฃŒ๋˜๋„๋ก ์„ค์ •์ด ๋˜์–ด์žˆ๋‹ค๋ฉด ์ฆ‰์‹œ, ์ด ์ „ ์ด์šฉ์ž๋ฅผ Logout ์ฒ˜๋ฆฌ ํ•˜๊ณ , Error Page๋ฅผ ์‘๋‹ตํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.




์ด๋ฒˆ์—๋Š” ๋‘ ์นœ๊ตฌ๋“ค์˜ ์ „๋ฐ˜์ ์ธ ์ฒ˜๋ฆฌ ๊ณผ์ •์„ ํ•œ๋ฒˆ ์‚ดํŽด ๋ณผ๊ฒŒ์š”.

์ตœ๋Œ€ Session ํ—ˆ์šฉ ๊ฐœ์ˆ˜๋Š” 1๊ฐœ๋ผ๊ณ  ๊ฐ€์ •์„ ํ•ฉ๋‹ˆ๋‹ค.


์ตœ์ดˆ ์ด์šฉ์ž 1๊ณผ 2๊ฐ€ Login์„ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.
์ด ๋•Œ, UsernamePasswordAuthenticationFilter(์ธ์ฆ ์ฒ˜๋ฆฌ Filter)๊ฐ€ ์ธ์ฆ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ตœ์ดˆ UsernamePasswordAuthenticationFilter๋Š” ConcurrentSessionControlAuthenticationStrategy Class๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

ConcurrentSessionControlAuthenticationStrategy Class๋Š” ๋™์‹œ์  Session ์ œ์–ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” Class์—์š”.

ConcurrentSessionControlAuthenticationStrategy๋Š” ์ธ์ฆ ์š”์ฒญ์„ ํ•œ ์ด์šฉ์ž์— Session ๊ฐœ์ˆ˜๊ฐ€ ๋ช‡๊ฐœ์ธ์ง€๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ์ƒํ™ฉ์—์„œ๋Š” ์ด์šฉ์ž 1์ด ์ธ์ฆ ์š”์ฒญ์„ ํ–ˆ์„ ๋•Œ๋Š” ๋‹น์—ฐํžˆ Session ๊ฐœ์ˆ˜๊ฐ€ 0๊ฐœ ์ผ ๊ฒƒ์ด๊ณ , ConcurrentSessionControlAuthenticationStrategy Class๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์•„๋ฌด๋Ÿฐ ๋ฌธ์ œ์—†์ด ํ†ต๊ณผ ์ฒ˜๋ฆฌ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋’ค ChangeSessionIdAuthenticationStrategy Class(Session ๊ณ ์ • ๋ณดํ˜ธ ์ฒ˜๋ฆฌ)๊ฐ€ ํ˜ธ์ถœ์ด ๋˜๋Š”๋ฐ, session.changeSessionId()๊ฐ€ Default Value์ด๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กœ์šด Session์„ ๋ฐœ๊ธ‰ํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ ๋‹ค์Œ์œผ๋กœ ํ˜ธ์ถœ ๋˜๋Š” Class๋Š” RegisterSessionAuthenticationStrategy์ธ๋ฐ, ์ด ์นœ๊ตฌ๋Š” ์ด์šฉ์ž์˜ Session์„ ๋“ฑ๋กํ•˜๊ณ , ์ €์žฅํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
์ด ์นœ๊ตฌ๊ฐ€ Session์„ ๋“ฑ๋กํ•˜๊ณ  ์ €์žฅ์„ ํ•ด์•ผ๋งŒ Session์ด Server ์•ˆ์— ์ €์žฅ๋˜๊ณ , ๊ทธ์ œ์„œ์•ผ Session Count ๊ฐ’์ด 1๋กœ ๋ฐ”๋€Œ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ๊นŒ์ง€ ๋‚ด์šฉ์ด ์ด์šฉ์ž 1์ด ์ธ์ฆ ์š”์ฒญ์„ ๋ณด๋ƒˆ์„ ๋•Œ,
UsernamePasswordAuthenticationFilter๊ฐ€ ๊ฐ๊ฐ์˜ Class๋“ค์„ ํ˜ธ์ถœํ•˜๋ฉด์„œ ์ž‘์—…ํ•˜๋Š” ๋‚ด์šฉ์„ ์•Œ์•„๋ณด์•˜์–ด์š”.

์ด ๋•Œ, ์ด์šฉ์ž 2๊ฐ€ ๋™์ผํ•œ ๊ณ„์ •์œผ๋กœ ์ธ์ฆ ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

์ด์šฉ์ž 2์— ๋Œ€ํ•œ ์ธ์ฆ ์š”์ฒญ๋„ ๋™์ผํ•˜๊ฒŒ UsernamePasswordAuthenticationFilter(์ธ์ฆ ์ฒ˜๋ฆฌ Filter)๊ฐ€ ์ธ์ฆ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ตœ์ดˆ UsernamePasswordAuthenticationFilter๋Š” ConcurrentSessionControlAuthenticationStrategy Class๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

ConcurrentSessionControlAuthenticationStrategy๋Š” ์ธ์ฆ ์š”์ฒญ์„ ํ•œ ์ด์šฉ์ž์— Session ๊ฐœ์ˆ˜๊ฐ€ ๋ช‡๊ฐœ์ธ์ง€๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ์ƒํ™ฉ์—์„œ๋Š” ์ด์šฉ์ž 1์ด ์ธ์ฆ์ด ๋œ ์ƒํ™ฉ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‹น์—ฐํžˆ Session ๊ฐœ์ˆ˜๊ฐ€ 1์ผ ๊ฒƒ์ด๊ณ , ์ตœ๋Œ€ ํ—ˆ์šฉ Session ๊ฐœ์ˆ˜๋Š” 1์ด๋ผ๊ณ  ๊ฐ€์ •์„ ํ•œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.

session count 1 (sessionCount == maxSessions) ๋ผ๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค.

์ด๋ ‡๋‹ค๋ผ๋Š” ๊ฑด ์ตœ๋Œ€ ํ—ˆ์šฉ Session ๊ฐœ์ˆ˜๋ฅผ ์ดˆ๊ณผํ•œ ์ƒํƒœ์ด๊ณ , ๋‘ ๊ฐ€์ง€ ์ „๋žต์œผ๋กœ ์ด ๋‚ด์šฉ์„ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ธ์ฆ ์‹คํŒจ ์ „๋žต๊ณผ ์„ธ์…˜ ๋งŒ๋ฃŒ ์ „๋žต์ด ์žˆ๋Š”๋ฐ, ๋จผ์ € ์ธ์ฆ ์‹คํŒจ ์ „๋žต์ธ ๊ฒฝ์šฐ SessionAuthenticationException (์ธ์ฆ ์˜ˆ์™ธ)๋ฅผ ๋ฐœ์ƒ ์‹œํ‚ค๊ณ , Session์ด ๋งŒ๋“ค์–ด์ง€์ง€ ๋ชปํ•˜๊ณ , ์ธ์ฆ ์‹คํŒจ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ฒŒ ๋˜ ๋ฒ„๋ฆฝ๋‹ˆ๋‹ค.

๋‘๋ฒˆ์งธ ์„ธ์…˜ ๋งŒ๋ฃŒ ์ „๋žต์ธ ๊ฒฝ์šฐ์—๋Š” session.expireNow()๋ฅผ ํ†ตํ•ด ์ด ์ „์— ์ธ์ฆํ•œ ์ด์šฉ์ž 1์— ๋Œ€ํ•œ Session์„ ๋งŒ๋ฃŒ ์‹œ์ผœ ๋ฒ„๋ฆฝ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์ด์šฉ์ž 2๋Š” ์ธ์ฆ์— ์„ฑ๊ณตํ•œ ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. 
์ธ์ฆ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋Š” ์œ„์—์„œ ์ตœ์ดˆ ์ด์šฉ์ž 1์ด ์ธ์ฆ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ๋•Œ์™€ ๋™์ผํ•œ ์ ˆ์ฐจ๋ฅผ ๋ฐŸ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด ๋•Œ, Server์—๋Š” ์ด์šฉ์ž 1๊ณผ ์ด์šฉ์ž 2์— ๋Œ€ํ•œ Session์ด ๊ฐ๊ฐ ํ•œ ๊ฐœ์”ฉ ์ €์žฅ๋˜์–ด ์žˆ๋Š” ์ƒํƒœ ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ์ด์šฉ์ž 1์ด ๋‹ค์‹œ ์–ด๋–ค ์ž์›์— ์ ‘๊ทผ์„ ์œ„ํ•œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋˜๋ฉด ConcurrentSessionFilter๊ฐ€ ์ด์šฉ์ž 1๊ณผ ์ด์šฉ์ž 2์— Session ๋งŒ๋ฃŒ ์—ฌ๋ถ€๋ฅผ ํ™•์ธ ํ•ฉ๋‹ˆ๋‹ค. ConcurrentSessionFilter๋Š” Client์—์„œ ์š”์ฒญ์ด ์˜ฌ ๋•Œ๋งˆ๋‹ค Session ๋งŒ๋ฃŒ ์—ฌ๋ถ€๋ฅผ ํ™•์ธ ํ•ฉ๋‹ˆ๋‹ค. 

์ด ํ™•์ธ์„ ์œ„ํ•ด ConcurrentSessionControlAuthenticationStrategy์˜ session.expireNow() : ์ด์šฉ์ž 1 ์ฒ˜๋ฆฌ๋ฅผ ํ•œ ๋‚ด์šฉ์„ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๋˜๋ฉด session.isExpired() ๊ฐ’์€ ์ด์šฉ์ž 1์— ๋Œ€ํ•ด true๊ฐ€ ๋˜๊ณ , ConcurrentSessionFilter๋Š” ์ฆ‰์‹œ ์ด์šฉ์ž 1์„ Logout ์ฒ˜๋ฆฌ ํ•ด๋ฒ„๋ฆฌ๊ณ , ์‘๋‹ต๊ฐ’์œผ๋กœ " this session has been expired "์™€ ๊ฐ™์€ ๋‚ด์šฉ์„ ๋ฐ˜ํ™˜ํ•ด ์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.








        ๐Ÿ“ฆ ์ธ์ฆ API -  ๊ถŒํ•œ ์„ค์ • ๋ฐ ํ‘œํ˜„์‹

1. ์„ ์–ธ์  ๋ฐฉ์‹

    •  URL : http.antMatchers("/users/**").hasRole("USER")
    • Method : @PreAuthorize("hasRole('USER')")
       public void user() { System.out.println("user") }

2. ๋™์  ๋ฐฉ์‹ - Data Base ์—ฐ๋™ Programming

    • URL   
• Method 

์ด๋ฒˆ์—๋Š” ์„ ์–ธ์  ๋ฐฉ์‹์—์„œ URL ์„ค์ • ๋ฐฉ์‹์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•ด ๋ณผ๊ฒŒ์š”.

 

@Override
protected void configure(HttpSecurity http) throws Exception {
	http
    	.antMatcher("/shop/**")
        .authorizeRequests()
        	.antMatchers("/shop/login", "/shop/users/**").permitAll()
            .antMatchers("/shop/mypage").hasRole("USER")
            .antMatchers("/shop/admin/pay").access("hasRole('ADMIN')");
            .antMatchers("/shop/admin/**").access("hasRole('ADMIN') or hasRole('SYS')");
            .anyRequest().authenticated()
}


์œ„์˜ URL ์„ค์ • ์‹œ ์ฃผ์˜์‚ฌํ•ญ์€ ๊ตฌ์ฒด์ ์ธ ๊ฒฝ๋กœ๊ฐ€ ๋จผ์ € ์˜ค๊ณ , ๊ทธ๊ฒƒ๋ณด๋‹ค ํฐ ๋ฒ”์œ„์˜ ๊ฒฝ๋กœ๊ฐ€ ๋’ค์— ์˜ค๋„๋กํ•ด์•ผ ํ•˜๋Š” ์  ์ž…๋‹ˆ๋‹ค.

์ตœ์ดˆ .antMatcher("/shop/**") ์€ ์ด์šฉ์ž๊ฐ€ /shop ํ•˜์œ„(**)์— ๋Œ€ํ•ด ์š”์ฒญ์„ ๋ณด๋ƒˆ์„ ๋•Œ์—๋งŒ ๊ทธ ํ•˜์œ„์— ์„ค์ •๋œ ๋‚ด์šฉ์ด ์ ์šฉ๋˜๋„๋ก ํ•˜๊ฒ ๋‹ค๋Š” ์˜๋ฏธ์—์š”.

๋”ฐ๋ผ์„œ ์œ„์™€ ๊ฐ™์ด ์„ค์ •ํ–ˆ์„ ๋•Œ, /shop/** ์ด ์•„๋‹Œ ๋‹ค๋ฅธ URI์— ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋œ๋‹ค๋ฉด ์œ„์— ์„ค์ •์€ ์ž‘๋™ํ•˜์ง€ ์•Š๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

.antMatchers("/shop/login", "/shop/users/**").permitAll()
์œ„์˜ ๋‚ด์šฉ์—์„œ antMatchers() ๊ด„ํ˜ธ์•ˆ์— ์—ฌ๋Ÿฌ๊ฐ€์ง€ URI๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋„ฃ์„ ์ˆ˜ ์žˆ์–ด์š”. ์ด๊ฒƒ์€ ์ด์šฉ์ž๊ฐ€ ์š”์ฒญํ•œ URI ์ •๋ณด์™€ Server ๋‚ด์— ๋“ฑ๋ก๋œ URI๊ฐ€ ์ผ์น˜ํ•˜๋ฉด ๊ถŒํ•œ ์‹ฌ์‚ฌ๋ฅผ ํ•˜๊ฒ ๋‹ค๋Š” ์˜๋ฏธ์—์š”. ๊ทธ๋Ÿฐ ๋’ค .permitAll()์„ ํ•˜๋ฉด ์ธ์ฆ ์ ˆ์ฐจ ์—†์ด ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•˜๊ฒ ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

.antMatchers("/shop/mypage").hasRole("USER")

์œ„์˜ ๋‚ด์šฉ์—์„œ .hasRole("USER")๋Š” USER ๊ถŒํ•œ ์ธ์ง€์— ๋Œ€ํ•œ ์ธ๊ฐ€ ์‹ฌ์‚ฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฒ ๋‹ค๋Š” ์˜๋ฏธ์—์š”.

์œ„์˜ ๋‚ด์šฉ์— ์ ์€ ๋‚ด์šฉ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ์ ์šฉ๋˜์ง€ ์•Š์œผ๋ฉด ์ธ๊ฐ€ ์ฒ˜๋ฆฌ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์—†์–ด์š”.

.anyRequest().authenticate()๋Š” ์œ„์— ๋ชจ๋“  ์กฐ๊ฑด์— ๋งŒ์กฑํ•˜์ง€ ์•Š์œผ๋ฉด ๋ชจ๋“  ์š”์ฒญ์€ ์ธ์ฆ ์ฒ˜๋ฆฌ๋ฅผ ๋ฐ›์•„์•ผ ํ•œ๋‹ค.๋ผ๋Š” ๋‚ด์šฉ์ด์—์š”.


Method ๋™์ž‘ ๋ฐฉ์‹
authenticated() ์ธ์ฆ๋œ ์ด์šฉ์ž ์ ‘๊ทผ ํ—ˆ์šฉ.
FullyAuthenticated() ์ธ์ฆ๋œ ์ด์šฉ์ž ์ ‘๊ทผ ํ—ˆ์šฉ.
๋‹จ, rememberMe ์ธ์ฆ ์ œ์™ธ.
ID, Password๋กœ๋งŒ ์ธ์ฆ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ณ ์ž ํ•  ๋•Œ ์‚ฌ์šฉ.
permitAll() ์ธ์ฆ์„ ๋ฐ›์ง€ ์•Š์•„๋„ ์ ‘๊ทผ ํ—ˆ์šฉ.
denyAll() ์ธ์ฆ์„ ๋ฐ›์•„๋„ ๋ฌด์กฐ๊ฑด ์ ‘๊ทผ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Œ.
anonymous() ์ต๋ช… ์ด์šฉ์ž์— ๋Œ€ํ•œ ์ ‘๊ทผ ํ—ˆ์šฉ.
rememberMe() ์ธ์ฆ ์ •๋ณด ๊ธฐ์–ตํ•˜๊ธฐ๋ฅผ ํ†ตํ•ด ์ธ์ฆ๋œ ์ด์šฉ์ž ์ ‘๊ทผ ํ—ˆ์šฉ.
access(String) ์ฃผ์˜ค์ง„ SpEL ํ‘œํ˜„์‹("hasRole('ADMIN')") ํ‰๊ฐ€ ๊ฒฐ๊ณผ๊ฐ€ true ์ผ ๋•Œ, ์ ‘๊ทผ ํ—ˆ์šฉ.
hasRole(String) ์š”์ฒญ ์ด์šฉ์ž๊ฐ€ ์ฃผ์–ด์ง„ ์—ญํ• ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด ์ ‘๊ทผ ํ—ˆ์šฉ.
hasAuthority(String) ์š”์ฒญ ์ด์šฉ์ž๊ฐ€ ์ฃผ์–ด์ง„ ๊ถŒํ•œ์ด ์žˆ๋‹ค๋ฉด ์ ‘๊ทผ ํ—ˆ์šฉ.
hasAnyRole(String...) ์š”์ฒญ ์ด์šฉ์ž๊ฐ€ ์ฃผ์–ด์ง„ ๊ถŒํ•œ์ด ์žˆ๋‹ค๋ฉด ์ ‘๊ทผ ํ—ˆ์šฉ.
hasAnyAuthority(String...) ์š”์ฒญ ์ด์šฉ์ž๊ฐ€ ์ฃผ์–ด์ง„ ๊ถŒํ•œ ์ค‘ ์–ด๋–ค ๊ฒƒ์ด๋ผ๋„ ์žˆ๋‹ค๋ฉด ์ ‘๊ทผ ํ—ˆ์šฉ.
hasIpAddress(String) ๋“ฑ๋ก๋œ IP๋กœ๋ถ€ํ„ฐ ์š”์ฒญ์ด ์™”๋‹ค๋ฉด ์ ‘๊ทผ ํ—ˆ์šฉ.



์ด์ œ Code๋ฅผ ์ž‘์„ฑํ•ด์„œ ํ•ด๋‹น Code๋ฅผ ๋ถ„์„ํ•˜๋ฉด์„œ ๊ณต๋ถ€๋ฅผ ํ•ด ๋ณผ๊ฒŒ์š”.

public class SecurityConfig extends WebSecurityConfigurerAdapter


๋จผ์ € configure(AuthenticationManagerBuilder auth)๋ฅผ ํ†ตํ•ด auth.inMemoryAuthentication()์œผ๋กœ Memory ๋‚ด์— ์ž„์‹œ ๊ณ„์ •์„ ์ƒ์„ฑํ•ด ๋ณผ๊ฒŒ์š”.

.password() ์•ˆ์— noop์€ ์œ„์™€ ๊ฐ™์ด ๊ณ„์ •์„ ๋งŒ๋“ค ๋•Œ, Password์•ˆ์— ์–ด๋–ค ๋ฐฉ์‹์˜ Hash ์•”ํ˜ธํ™”๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ธ์ง€๋ฅผ ์ž‘์„ฑํ•ด ์ค˜์•ผ ๋‚˜์ค‘์— Login์„ ํ•  ๋•Œ, ํ•ด๋‹น Hash ์•”ํ˜ธํ™” ๋ฐฉ์‹์„ ์ด์šฉํ•ด ๊ฐ’์„ ๋น„๊ตํ•ด ๋ณผํ…๋ฐ, ์ž‘์„ฑํ•ด ์ฃผ์ง€ ์•Š์œผ๋ฉด, ๋น„๊ต ์ž์ฒด๊ฐ€ ์•ˆ๋˜์–ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋ฐ”๋กœ ์ด๋ ‡๊ฒŒ ์ธ์ฆ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋˜๋ฉด Exception์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋  ๊ฑฐ์—์š”.




๊ทธ๋ž˜์„œ noop์œผ๋กœ ํ‰๋ฌธ์œผ๋กœ ์ €์žฅํ•˜๊ฒŒ ํ•˜๊ฒ ๋‹ค๋ฅผ ๋ช…์‹œํ•œ ๊ฒƒ์ด์—์š”.



Test๋กœ ์‚ฌ์šฉ๋  Controller์— ์œ„์™€ ๊ฐ™์ด 4๊ฐœ์˜ Method๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ์—ˆ์–ด์š”.

๊ฐ๊ฐ์˜ Method์— ์š”์ฒญ์ด ๋“ค์–ด์˜ค๊ฒŒ ๋˜๋ฉด Web Page ์ƒ์— ์š”์ฒญ ์ด์šฉ์ž์˜ ID (principal.getName()) ๊ณผ ์š”์ฒญ ์ด์šฉ์ž ๊ถŒํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ์ฒ˜๋ฆฌ ํ•ด ์ฃผ์—ˆ์–ด์š”.

getRoleinfo()๋Š” ์ตœ์ดˆ SecurityContextHoder์—๋Š” ์ธ์ฆ ์š”์ฒญ ์ด์šฉ์ž์— ์ •๋ณด๊ฐ€ ๋‹ด๊ฒจ ์žˆ๋‹ค๊ณ  ์œ„์—์„œ ๊ณต๋ถ€ํ•ด ๋ณด์•˜์–ด์š”.
๊ทธ๋ž˜์„œ ์ฃผ๋‹ˆํ•˜๋ž‘์€ ์ด ์•ˆ์— getContext().getAuthentication()์„ ํ†ตํ•ด ์ธ์ฆ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋„๋ก ํ•˜์˜€๊ณ , ๊ทธ ์ธ์ฆ ๊ฐ์ฒด ์•ˆ์— ๊ถŒํ•œ ์ •๋ณด ๋ชฉ๋ก์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ์ฒ˜๋ฆฌํ•˜์—ฌ ์‘๋‹ต์„ ์ฃผ๋„๋ก ์ฒ˜๋ฆฌํ–ˆ์–ด์š”.



์ตœ์ดˆ user ๊ณ„์ •์œผ๋กœ ์ธ์ฆ์„ ๋ฐ›์•„ ๋ณผ๊ฒŒ์š”.


์ธ์ฆ์„ ์ •์ƒ์ ์œผ๋กœ ๋ฐ›์•˜์–ด์š”.

์ด ๋•Œ, ๊ถŒํ•œ ํ™•์ธ์„ ์œ„ํ•ด /user๋กœ ์ ‘๊ทผํ•ด ๋ณผ๊ฒŒ์š”.


์•„์ฃผ ์ ‘๊ทผ์ด ์ž˜ ๋˜๊ณ  ์žˆ์–ด์š”.



user ๊ถŒํ•œ์„ ๊ฐ€์ง„ user ๊ณ„์ •์œผ๋กœ /admin URI Get ์š”์ฒญ์„ ๋ณด๋‚ด๋‹ˆ ์œ„์™€ ๊ฐ™์ด Forbidden (๊ถŒํ•œ ์—†์Œ) Error ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ์žˆ์–ด์š”.



/admin/pay ๋„ ๋™์ผํ•˜๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋„ค์š”!


์ด๋ฒˆ์—” sys ๊ถŒํ•œ์— ๋Œ€ํ•ด Test๋ฅผ ์ง„ํ–‰ ํ•ด ๋ณผ๊ฒŒ์š”.

 

 

์ธ์ฆ์ด ์ •์ƒ์ ์œผ๋กœ ๋˜์—ˆ๊ณ , Home์— ์ ‘์†์ด ๋˜์—ˆ์–ด์š”.

 


SYS ๊ณ„์ •์€ /admin/** ํ•˜์œ„ ๋ชจ๋“  URI์— ๋Œ€ํ•ด์„œ๋Š” ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ์„ค์ •์„ ํ•ด์ฃผ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ„์˜ URI ์š”์ฒญ์— ๋Œ€ํ•ด์„œ๋Š” ๋ฌธ์ œ ์—†์ด ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•ด์š”.


ํ•˜์ง€๋งŒ, /admin/pay์— ๋Œ€ํ•ด์„œ๋Š” ADMIN ๊ถŒํ•œ์„ ๊ฐ€์ง„ ์ด์šฉ์ž๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ ‘๊ทผ์ด ๋ถˆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.




๋˜ํ•œ /user ์—ญ์‹œ USER ๊ถŒํ•œ๋งŒ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ ‘๊ทผ์ด ๋ถˆ๊ฐ€ํ•ด์š”.


public class SecurityConfig extends WebSecurityConfigurerAdapter


ํ•˜์ง€๋งŒ, ์œ„์™€ ๊ฐ™์ด ๊ฐ ๊ณ„์ •์— ๋งž๊ฒŒ ์—ฌ๋Ÿฌ ๊ถŒํ•œ๋“ค์„ ๋‚ด๋ถ€ ์ •์ฑ…์— ๋งž๊ฒŒ ์„ค์ •์„ ํ•ด์ฃผ๋ฉด SYS๋Š” USER ๊ถŒํ•œ์„ ๊ฐ–๊ฒŒ ๋˜์—ˆ์Œ์œผ๋กœ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 


์ด๋ ‡๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์–ด์š”.




์ด๋ฒˆ์—๋Š” /admin ํ•˜์œ„ ๋ชจ๋“  ์ž์›์„ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋‚ด์šฉ์ด /admin/pay๋ณด๋‹ค ์œ„์— ์žˆ์„ ๋•Œ, ์ฆ‰, ๊ตฌ์ฒด์ ์ธ ๊ฒฝ๋กœ๊ฐ€ ๋จผ์ € ์˜ค๊ณ , ๊ทธ๊ฒƒ๋ณด๋‹ค ํฐ ๋ฒ”์œ„์˜ ๊ฒฝ๋กœ๊ฐ€ ๋’ค์— ์˜ค๋„๋กํ•ด์•ผ ํ•˜๋Š” ์ ์— ์œ„๋ฐ˜ ๋˜์—ˆ์„ ๋•Œ๋ฅผ Test ํ•ด๋ณผ๊ฒŒ์š”.

๊ฒฐ๊ณผ์ ์œผ๋กœ /admin/** ์— ๋Œ€ํ•œ ์„ค์ •๊ฐ’์ด ๋จผ์ € ์ฒ˜๋ฆฌ๊ฐ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์— /admin/pay๋Š” ๋„๋‹ฌํ•  ์ˆ˜ ์—†๋Š” ์ฝ”๋“œ๊ฐ€ ๋˜์–ด๋ฒ„๋ฆฝ๋‹ˆ๋‹ค.


์œ„์—์„œ SYS ๊ณ„์ •์€ /admin/pay์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์—ˆ์œผ๋‚˜, ์ง€๊ธˆ์€ ์ด๋ ‡๊ฒŒ ์ ‘๊ทผ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์œ ๋Š” ์œ„์— ์„ค๋ช…ํ•œ ๋ฐ”์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.









        ๐Ÿ“ฆ ์ธ์ฆ API -  ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฐ ์š”์ฒญ ์บ์‹œ ํ•„ํ„ฐ : ExceptionTranslationFilter / RequestCacheAwareFilter


๋จผ์ €
ExceptionTranslationFilter์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•ด ๋ณผ๊ฒŒ์š”.



1.  AuthenticationException

    • ์ธ์ฆ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ
      - AuthenticationEntryPoint ํ˜ธ์ถœ

         -> Login Page ์ด๋™, 401 Error Code ์ „๋‹ฌ ๋“ฑ

    • ์ธ์ฆ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์ „ ์š”์ฒญ ์ •๋ณด ์ €์žฅ
      - RequestCache - ์ด์šฉ์ž์˜ ์ด์ „ ์š”์ฒญ ์ •๋ณด๋ฅผ Session์— ์ €์žฅํ•˜๊ณ , ์ด๋ฅผ ๊บผ๋‚ด์˜ค๋Š” ๋ฐฉ์‹.
      - SaveRequest - ์ด์šฉ์ž๊ฐ€ ์š”์ฒญํ–ˆ๋˜ Request Parameter ๊ฐ’๋“ค, ๊ทธ ๋‹น์‹œ Request Header ๊ฐ’ ๋“ฑ์„ ์ €์žฅ.



2.  AccessDeniedException

    • ์ธ๊ฐ€ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ
      - AccessDeniedHandler ์—์„œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์ œ๊ณต.

 

์œ„ ๋‘๊ฐ€์ง€ Exception์„ Throw (๋ฐœ์ƒ) ์‹œํ‚ค๋Š” ์ฃผ์ฒด Filter๋Š” ๋ฐ”๋กœ FilterSecurityInterceptor์—์š”.

์œ„ Filter๋Š” Spring Security๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” Filter ์ค‘ ๋งจ ๋งˆ์ง€๋ง‰์— ์œ„์น˜ํ•œ Filter์—์š”. ์ด ์•ž์— ์œ„์น˜ํ•œ Filter๊ฐ€ ๋ฐ”๋กœ 

ExceptionTranslationFilter์—์š”.

ExceptionTranslationFilter๊ฐ€ ์ด์šฉ์ž ์š”์ฒญ์„ ๋ฐ›์•„ ๊ทธ ๋‹ค์Œ Filter์—๊ฒŒ ์ „๋‹ฌํ•  ๋•Œ, try catch {}๋กœ ๊ฐ์‹ธ์„œ FilterSecurityInterceptor๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ FilterSecurityInterceptor์—์„œ ๋ฐœ์ƒ๋œ ์ธ์ฆ, ์ธ๊ฐ€ Exception์€ ํ•ด๋‹น Filter๋ฅผ ํ˜ธ์ถœํ•œ ExceptionTranslationFilter์—๊ฒŒ ์ธ์ฆ, ์ธ๊ฐ€ Exception์„ Throw ์ฆ‰, ์ „๋‹ฌํ•˜๊ณ  ์žˆ์–ด์š”.




์ตœ์ดˆ ์ด์šฉ์ž๊ฐ€ /user URI์— ์ ‘๊ทผ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
ํ•ด๋‹น URI ์ž์›์€ ์ธ์ฆ์„ ๋ฐ›์•„์•ผ๋งŒ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•œ ์ž์›์ž…๋‹ˆ๋‹ค.
๋งŒ์•ฝ ์ด ์ด์šฉ์ž๊ฐ€ ์ธ์ฆ์„ ๋ฐ›์ง€ ์•Š์•˜๋‹ค๋ฉด FilterSecurityInterceptor๊ฐ€ ์ด์šฉ์ž์˜ ์š”์ฒญ์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. 

์ด ์ƒํ™ฉ์—์„œ FilterSecurityInterceptor๋Š” ์ธ์ฆ์„ ๋ฐ›์ง€ ์•Š๊ณ , ์ ‘๊ทผํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ธ์ฆ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ ์‹œํ‚ค๊ฒŒ ๋˜์š”.
์ •ํ™•ํ•˜๊ฒŒ ์ด์•ผ๊ธฐ ํ•˜์ž๋ฉด ์ธ์ฆ ์˜ˆ์™ธ๊ฐ€ ์•„๋‹ˆ๊ณ , ์ธ๊ฐ€ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค๊ณ  ๋ด์•ผํ•ด์š”. ์™œ๋ƒํ•˜๋ฉด ์ธ์ฆ์„ ๋ฐ›์ง€ ์•Š๊ณ , ์ ‘๊ทผ์„ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ต๋ช… ์ด์šฉ์ž๊ฐ€ ์ ‘๊ทผํ•˜๋Š” ์ƒํ™ฉ์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ์–ด์š”.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ธ์ฆ ์˜ˆ์™ธ๊ฐ€ ์•„๋‹ˆ๋ผ, ๊ถŒํ•œ์ด ์—†๋‹ค๊ณ  ํŒ๋‹จ์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ธ๊ฐ€ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ƒํ™ฉ์ด ๋˜์š”.

์ด ๋•Œ, ExceptionTranslationFilter๊ฐ€ ๋ฐ”๋กœ AccessDeniedException์œผ๋กœ ์˜ˆ์™ธ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ๋Š” ํ•˜๋Š”๋ฐ, AccessDeniedHandler๋ฅผ ํ˜ธ์ถœํ•˜์ง€๋Š” ์•Š์•„์š”. ์ต๋ช… ์ด์šฉ์ž์— ์ ‘๊ทผ ์š”์ฒญ์ด๋˜์ง€ remember Me ์ธ์ฆ ์ด์šฉ์ž์˜ ๊ฒฝ์šฐ 
AuthenticationException์œผ๋กœ ์˜ˆ์™ธ๋ฅผ ์ „๋‹ฌํ•˜๊ฒŒ ๋˜์š”. ์ฆ‰, ์ธ์ฆ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ณผ์ •์œผ๋กœ ๋„˜์–ด๊ฐ€๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด์—์š”.

์€ Class์— ์ธ์ฆ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ ์ด์šฉ์ž ์š”์ฒญ ๊ด€๋ จ ์ •๋ณด๋ฅผ ์ €์žฅํ•ด์š”. ํ•ด๋‹น ์ •๋ณด๋Š” ๊ฐ์ฒด ์•ˆ์— ์ €์žฅ์ด ๋˜๋ฉฐ, ์ด ๊ฐ์ฒด๋Š” ์— ๋‹ค์‹œ ์ €์žฅ์ด ๋ฉ๋‹ˆ๋‹ค.AuthenticationExceptionHttpSessionRequestCacheDefaultSavedRequestSession

๊ทธ๋Ÿฐ ๋’ค AuthenticationException์€ AuthenticationEntryPoint Interface ๊ตฌํ˜„์ฒด๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ธ์ฆ ์‹คํŒจ ์ดํ›„ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์ „๋‹ฌํ•ด์š”.

๊ทธ๋Ÿฌ๋ฉด ์ธ์ฆ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ณดํ†ต Login Page๋กœ ์ด๋™ํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์š”. ๊ทธ ์ „์— ๊ฐ์ฒด์•ˆ์— ์ธ์ฆ ๊ฐ์ฒด๋ฅผ Null๋กœ ๋งŒ๋“œ๋Š” ์ž‘์—…์„ ์„ ํ–‰ํ•ฉ๋‹ˆ๋‹ค.๋งŒ์•ฝ ์š”์ฒญ ์ด์šฉ์ž๊ฐ€ ์ธ์ฆ์€ ๋ฐ›์•˜๋Š”๋ฐ, ๊ถŒํ•œ์ด ๋งž์ง€ ์•Š์„ ๋•Œ๋Š” ์–ด๋–ค์ผ์ด ๋ฐœ์ƒํ• ๊นŒ์š”?์ด๋Ÿด ๋•Œ๋Š” ์ธ๊ฐ€ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด ๋•Œ๋Š”SecurityContext



ExceptionTranslationFilter ๊ฐ€AccessDeniedException๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋˜์š”.

AccessDeniedHandler๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ , ๊ทธ ์•ˆ์—์„œ ๊ทธ ๋‹ค์Œ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ๋ณดํ†ต์€ /denied์™€ ๊ฐ™์€ Error Page๋กœ ์ด๋™์„ ์‹œ์ผœ์š”. ๊ทธ๋ ‡๊ฒŒ ํ•ด์„œ ์ด์šฉ์ž์—๊ฒŒ ์ž์›์— ์ ‘๊ทผํ•  ๊ถŒํ•œ์ด ์—†๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ์–ด์š”.


ExceptionTranslationFilter๋ฅผ ์–ด๋–ป๊ฒŒ ์ด์šฉํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?

: ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ ํ™œ์„ฑํ™”http.exceptionHandling()


protected void configure(HttpSecurity http) throws Exception {
	http
    	.exceptionHandling()
        .authenticationEntryPoint(authenticationEntryPoint())	// ์ธ์ฆ ์‹คํŒจ ์‹œ ์ฒ˜๋ฆฌ
        .accessDeniedHandler(accessDeniedHandler())				// ์ธ๊ฐ€ ์‹คํŒจ ์‹œ ์ฒ˜๋ฆฌ



public class SecurityConfig extends WebSecurityConfigurerAdapter


์œ„์—์„œ ์„ค๋ช…ํ•œ ๋‚ด์šฉ์„ ๊ธฐ๋ฐ˜ํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด ์ฃผ์—ˆ์–ด์š”.


public class SecurityConfig extends WebSecurityConfigurerAdapter


๊ทธ๋Ÿฐ ๋’ค ์ด์šฉ์ž๊ฐ€ ์ธ์ฆ์— ์„ฑ๊ณตํ•˜๋ฉด ๋ถˆ๋ฆฌ๊ฒŒ ๋˜๋Š” successHandler์— ์ธ์ฆ ์„ฑ๊ณต ์š”์ฒญ์ž๊ฐ€ ์š”์ฒญํ•œ URI ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ณ , ๊ทธ URI๋กœ ์ด๋™ํ•˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด ์ฃผ์—ˆ์–ด์š”.


๊ทธ๋ฆฌ๊ณ , Controller์— ์ธ๊ฐ€ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•  ์‹œ ๋“ค์–ด์˜ฌ Page URI์— ๋Œ€ํ•œ Method๋ฅผ ์ž‘์„ฑํ•ด ์ฃผ์—ˆ์–ด์š”.

 


์ธ๊ฐ€๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ๋ถ€์— /signin์€ ์ธ์ฆ ์—†์ด ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•˜๊ณ , ๋‚˜๋จธ์ง€ ๋ชจ๋“  URI ์š”์ฒญ์— ๋Œ€ํ•ด์„œ๋Š” ์ธ์ฆ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๊ณ , AuthenticationException์ด AuthenticationEntryPoint๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ 171๋ฒˆ์งธ ์ฝ”๋“œ์™€ ๊ฐ™์ด /signin (Spring security๊ฐ€ ์ œ๊ณตํ•˜๋Š” Login Page ์•„๋‹˜)์œผ๋กœ ์ด๋™ํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๊ฐ€ ๋˜๋„๋ก ํ•ด ๋‘์—ˆ์–ด์š”.



root page๋กœ ์ ‘๊ทผ์„ ํ•˜๊ฒŒ ๋˜๋ฉด ์–ด๋–ค์ผ์ด ์ผ์–ด๋‚ ๊นŒ์š”?



๋ฐ”~๋กœ signin Page๋กœ ๋„˜์–ด๊ฐ€๊ฒŒ ๋˜๊ณ , ์š”์ฒญ ์ด์šฉ์ž์˜ ๊ถŒํ•œ์€ ์ต๋ช… ์ด์šฉ์ž์ธ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.





์ด๋ฒˆ์—๋Š” ์ธ์ฆ ์˜ˆ์™ธ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ถ€๋ถ„์„ ์ฃผ์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ์ธ์ฆ์ด ์„ฑ๊ณตํ•˜๋ฉด ํ•ด๋‹น ์ด์šฉ์ž๊ฐ€ ์š”์ฒญํ•œ URI๋กœ ๋ฐ”๋กœ ์ ‘๊ทผ์„ ํ•˜๋Š”์ง€ Test ํ•ด ๋ณผ๊ฒŒ์š”.



์ตœ์ดˆ /admin/test URI ์ž์› ์ ‘๊ทผ ์š”์ฒญ์„ ๋ณด๋‚ผ๊ฒŒ์š”.



๊ทธ๋Ÿฌ๋ฉด Spring Security๊ฐ€ ์ œ๊ณตํ•˜๋Š” Sign in Page์— ์ ‘๊ทผ์ด ๋˜๊ณ , SYS ๊ณ„์ •์œผ๋กœ Login์„ ํ•ด ๋ณผ๊ฒŒ์š”.


์ด ์ „์— ์ด์šฉ์ž๊ฐ€ ์š”์ฒญํ•œ URI๋กœ ๋ฐ”๋กœ ์ด๋™ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.



ํ•ด๋‹น ๊ณ„์ •์ด ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” /admin/pay๋กœ ์ ‘๊ทผ ์š”์ฒญ์„ ํ•˜๊ฒŒ ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?


 

์ด๋ ‡๊ฒŒ ์ธ๊ฐ€ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ /denied Page๋กœ ์ด๋™ํ•˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.





 

 

        ๐Ÿ“ฆ Form ์ธ์ฆ -  CSRF, CsrfFilter

๋จผ์ € CSRF(Cross Site Request Forgery - ์‚ฌ์ดํŠธ ๊ฐ„ ์š”์ฒญ ์œ„์กฐ ๊ณต๊ฒฉ)์— ๋Œ€ํ•œ ๋‚ด์šฉ์€ ์ด ๊ณณ์— ์ •๋ฆฌ ํ•ด ๋‘์—ˆ์–ด์š”.

๊ทธ๋Ÿผ CSRF ๊ณต๊ฒฉ์„ ๋ง‰์œผ๋กœ๋ฉด Spring Security๋กœ ์–ด๋–ป๊ฒŒ ๋ง‰์„ ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ๊ณต๋ถ€ํ•ด ๋ณผ๊ฒŒ์š”.
์ด๋ฅผ ์œ„ํ•ด CsrfFilter๋ฅผ ๊ณต๋ถ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

    •  ๋ชจ๋“  Request์— Randomํ•˜๊ฒŒ ์ƒ์„ฑ๋œ Token์„ HTTP Parameter๋กœ ์š”๊ตฌ.
    • Request์— ์ „๋‹ฌ๋˜๋Š” Token๊ฐ’๊ณผ Server์— ์ €์žฅ๋œ Token ๊ฐ’์ด ๊ฐ™์€์ง€๋ฅผ ๋น„๊ตํ•˜๊ณ , ์ผ์น˜ํ•˜์ง€ ์•Š์œผ๋ฉด ์‹คํŒจ ์ฒ˜๋ฆฌ.

1. Client

    •       - Front End ์—์„œ๋Š” hidden type์œผ๋กœ name์„ Server์—์„œ ๋ฐœ๊ธ‰ํ•œ Token ์ด๋ฆ„๊ณผ ๊ฐ’์€ Token ๊ฐ’์œผ๋กœ ์„ค์ •. <input type = "hidden" name = "${_csrf.parameterName}" value="${_csrf.token}" />

    • HTTP Method : PATCH, POST, PUT, DELETE
       - ์œ„์˜ Method๋ฅผ ์ด์šฉํ•  ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ Server์—์„œ ๋ฐœ๊ธ‰ํ•œ Token์„ ์š”์ฒญ์‹œ ํ•จ๊ป˜ Server์— ์ œ์ถœํ•ด์•ผ ํ•จ.

2. Spring Security

    • http.csrf() : ๊ธฐ๋ณธ ํ™œ์„ฑํ™”.
http.csrf.disabled() : ๋น„ ํ™œ์„ฑํ™” ์ฒ˜๋ฆฌ. 
ForgeryF



 

 




 

๋‹ค์Œ ๊ธ€ : [Stpring Boot] Spring Security Basic - ์ฃผ์š” ์•„ํ‚คํ…์ฒ˜ ์ดํ•ดํŽธ

 



728x90
๋ฐ˜์‘ํ˜•