빈쿵바라기
좌충우돌 개발자의 기록
빈쿵바라기
전체 방문자
오늘
어제
  • 분류 전체보기 (53)
    • Programming (25)
      • JAVA (12)
      • Spring Boot (6)
      • JPA (7)
      • Python (0)
    • Database (12)
      • RDBMS (4)
      • NoSQL (7)
    • Server (11)
    • Elasticsearch (3)
    • ETC (2)

블로그 메뉴

    공지사항

    인기 글

    최근 댓글

    최근 글

    티스토리

    hELLO · Designed By 정상우.
    빈쿵바라기
    Programming/Spring Boot

    [Spring Security] 두개의 로그인 페이지(Multiple Login Pages)

    Programming/Spring Boot

    [Spring Security] 두개의 로그인 페이지(Multiple Login Pages)

    2022. 8. 10. 20:07

    Spring Boot 프로젝트 진행 중 두개의 로그인 페이지(User, Admin)를 각각 구현해야 하는 이슈가 발생해서 정리하고자 합니다.


    1. Maven Dependencies 추가

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
        <version>2.7.2</version>
    </dependency>
    <dependency> 
        <groupId>org.springframework.boot</groupId> 
        <artifactId>spring-boot-starter-web</artifactId> 
        <version>2.7.2</version> 
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>2.7.2</version>
    </dependency>    
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-test</artifactId>
        <version>5.7.2</version>
    </dependency>
    • 마지막 버전 확인
      • spring-boot-starter-security
      • spring-boot-starter-web
      • spring-boot-starter-test
      • spring-security-test

    2. SecurityConfig 설정

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig {
        ... // 내부클래스로 User와 Admin 관련 클래스를 작성할 것이다.
    }
    • @Configuration
      • 스프링 설정 클래스를 선언하는 어노테이션. xml 설정을 대체할 수 있는 Java Config로 여러 설정들을 자바 클래스 파일로 사용하겠다는 의미 
    • @EnableWebSecurity
      • 해당 어노테이션을 작성해야지 Security를 활성화 시킬 수 있습니다.
      • 해당 어노테이션을 자세히 보면(아래 코드) WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class, HttpSecurityConfiguration.class들을 import해서 실행시켜주는 것을 알 수 있습니다.
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Documented
    @Import({ WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class,
    		HttpSecurityConfiguration.class })
    @EnableGlobalAuthentication
    @Configuration
    public @interface EnableWebSecurity {
    
    	/**
    	 * Controls debugging support for Spring Security. Default is false.
    	 * @return if true, enables debug support with Spring Security
    	 */
    	boolean debug() default false;
    
    }

     

    이제 Admin 사용자에 대한 Security 코드입니다. 위에서 만든 SecurityConfig.java 안에 작성합니다.

    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.annotation.Order;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    @Configuration
    @Order(1)
    public class SpringBootAdminSecurityConfiguration extends WebSecurityConfigurerAdapter {
    	
    	@Override
    	public void configure(AuthenticationManagerBuilder auth) throws Exception {
    		auth.inMemoryAuthentication()
    			.withUser("admin").password("{noop}password").roles("ADMIN");
    	}
    
    	@Override
    	public void configure(HttpSecurity http) throws Exception {
    		http
    			.antMatcher("/admin/**")
    			.authorizeRequests().anyRequest().authenticated()
    			.and().formLogin().loginPage("/admin/login")
    				.defaultSuccessUrl("/admin/dashboard", true)
    			.permitAll()
    			.and().logout().logoutUrl("/admin/logout").logoutSuccessUrl("/admin/login");
    		http.csrf().disable();
    
    	}
    }

    configurer 메소드안에 코드는 사용자 권한이 없는 상태에서 /admin으로 시작하는 url로 요청이 올 경우 /admin/login 페이지로 이동 후, 로그인 성공 시 /admin/dashboard로 이동합니다.

    User 사용자에 대한 코드도 SecurityConfig.java 안에 작성합니다.

    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.annotation.Order;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    @Configuration
    @Order(2)
    public class SpringBootUserSecurityConfiguration extends WebSecurityConfigurerAdapter {
    	
    	@Override
    	public void configure(AuthenticationManagerBuilder auth) throws Exception {
    		auth.inMemoryAuthentication()
    			.withUser("user").password("{noop}password").roles("USER");
    	}
    
    	@Override
    	public void configure(HttpSecurity http) throws Exception {
    		http
    			.antMatcher("/**")
    			.authorizeRequests().anyRequest().authenticated()
    			.and().formLogin().loginPage("/login")
    				.defaultSuccessUrl("/dashboard", true)
    			.permitAll()
    			.and().logout().logoutSuccessUrl("/login");
    		
    		http.csrf().disable();
    	}
    }

    사용자 권한이 없는 상태에서 의에 설정한 /admin을 제외한 모든 url로 요청이 올 경우 /login 페이지로 이동 후, 로그인 성공 시 /dashboard로 이동합니다.

    각 정적 클래스에 @Order 주석을 배치하여 URL이 요청될 때 일치하는 패턴을 기반으로 두 클래스가 고려되는 순서를 지정합니다. 두 구성 클래스는 동일한 순서를 가질 수 없습니다.


    3. Controller

    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    
    @Controller
    @RequestMapping
    public class TestController {
    
    	@RequestMapping("/")
    	public ModelAndView defaultHome() {
    		return new ModelAndView("login");
    	}
    
    	@RequestMapping("/login")
    	public ModelAndView login() {
    		return new ModelAndView("login");
    	}
    
    	@RequestMapping("/dashboard")
    	public ModelAndView userDashboard() {
    		return new ModelAndView("dashboard");
    	}
    
    	@RequestMapping("/admin/")
    	public ModelAndView admin() {
    		return new ModelAndView("admin/login");
    	}
    
    	@RequestMapping("/admin/login")
    	public ModelAndView adminlogin() {
    		return new ModelAndView("admin/login");
    	}
    
    	@RequestMapping("/admin/dashboard")
    	public ModelAndView admindashboard() {
    		return new ModelAndView("admin/dashboard");
    	}
    }

    4. Jsp File

    <!-- User Login Form -->
    <form method="POST" action="/login">
    	User Name : <input type="text" name="username" value="user"/><br><br>
    	Password  : <input type="password" name="password" value="password"/><br><br>
    	<input type="submit" name="submit"/>
    </form>
    
    <!-- Admin Login Form -->
    <form method="POST" action="/admin/login">
    	User Name : <input type="text" name="username" value="admin"/><br><br>
    	Password  : <input type="password" name="password" value="password"/><br><br>
    	<input type="submit" name="submit"/>
    </form>

    주의점

    • 사용자 분류를 anonymous(public), user(private), admin(admin)으로 구분하고자 하면 각 권한별로 WebSecurityConfigurerAdapter파일을 구현해야한다. user와 admin은 위의 예제와 같고, anonymous는 http 설정만 해주면 됩니다.
    • 위의 예제 코드는 http.antMatcher("/url")로 구현하고 있는데, http.authorizeRequests().antMatchers()로 구현하게 되면 모든 http.antMatcher() 설정을 무시하고 http.authorizeRequests().antMatchers() 설정만 작동합니다.
    • 사용자 페이지와 관리자 페이지가 다른 경우, 설정을 따로 하기보다 프로젝트를 구분하는 것이 관리 측면에서 더 나은 방법인 것 같습니다.
    저작자표시 (새창열림)

    'Programming > Spring Boot' 카테고리의 다른 글

    [Spring Security] 수동 인증(강제 로그인)  (0) 2023.05.16
    Spring AOP를 활용한 모든 Request에 Log 남기기  (0) 2023.03.29
    [Jasypt] Spring Boot 애플리케이션의 프로퍼티 암호화  (0) 2023.03.24
    [Maven] 라이브러리 Dependency 충돌 해결하기(Maven Tree)  (0) 2023.03.02
    [Mybatis] PostgreSQL ilike 구현하기(feat. Criteria 커스텀하기)  (0) 2022.08.20
      'Programming/Spring Boot' 카테고리의 다른 글
      • Spring AOP를 활용한 모든 Request에 Log 남기기
      • [Jasypt] Spring Boot 애플리케이션의 프로퍼티 암호화
      • [Maven] 라이브러리 Dependency 충돌 해결하기(Maven Tree)
      • [Mybatis] PostgreSQL ilike 구현하기(feat. Criteria 커스텀하기)
      빈쿵바라기
      빈쿵바라기
      삽질하는 개발자의 좌충우돌 개발기

      티스토리툴바

      개인정보

      • 티스토리 홈
      • 포럼
      • 로그인

      단축키

      내 블로그

      내 블로그 - 관리자 홈 전환
      Q
      Q
      새 글 쓰기
      W
      W

      블로그 게시글

      글 수정 (권한 있는 경우)
      E
      E
      댓글 영역으로 이동
      C
      C

      모든 영역

      이 페이지의 URL 복사
      S
      S
      맨 위로 이동
      T
      T
      티스토리 홈 이동
      H
      H
      단축키 안내
      Shift + /
      ⇧ + /

      * 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.