💬
목차
< 뒤로가기
인쇄

시큐리티(세션)

본 문서에서는 웹사이트에서 사용하는 세션기반 시큐리티를 사용하기 위한 기능을 제공한다.
캐모마일의 Security 기능은 Spring Security5.7 기반 하에 작업 되었다.

authentication(인증)

  • 인증은 사용자의 신원을 확인하는 과정을 의미한다. Chamomile에서의 인증은 Spring Security에서 제공하는 사용자 인증 정보를 RDB로 관리하기 위해 JdbcDaoImpl(UserDetailsService의 구현체)을 확장하여 제공한다.

  • 사용자 인증 정보

    • 사용자의 정보, 사용자가 가진 권한, 사용자가 속한 그룹에 대한 권한 정보를 바탕으로 인증이 이루어진다.
  • 인증 매커니즘

    • 기본적인 인증 매커니즘은 Spring Security의 인증 매커니즘을 그대로 사용하며, 아래와 같은 흐름으로 이루어진다.
      1. 인증 요청
        • UsernamePasswordAuthenticationFilter에서 사용자가 입력한 아이디와 비밀번호를 기반으로 UsernamePasswordAuthenticationToken을 생성한다.
      1. AuthenticationManager 위임
        • AuthenticationManager에 AuthenticationToken을 전달하여 인증을 위임한다.
      1. Authentication 정보 획득
        • AuthenticationManager에 등록된 AuthenticationProvider를 통해 Authentication 정보를 획득한다.
      1. RDB를 통한 인증 정보 획득
        • RDB를 통해 사용자 아이디를 기반으로 Authentication 정보를 획득하고, 사용자가 가진 권한 및 사용자가 속한 그룹의 권한 정보를 획득한다.
      1. 사용자 상태 확인 및 인증 수행
        • 사용자의 기본적인 상태(계정 잠김, 비활성화, 만료 등)를 확인하고, 정상적인 경우 패스워드를 검사하여 인증을 수행한다. 그 후, 비밀번호 상태(비밀번호 만료 등)를 확인한다.
      1. 인증 성공 후 처리
        • 인증이 성공하면, 원래 요청한 페이지로 redirect 된다.

          authorization(인가)

  • authorization은 누군가에게 무엇을 할 수 있게 하거나, 원하는 정보를 얻을 수 있도록 허용하는 과정이다. (즉, 웹 사이트 개발 시 리소스에 접근하기 위한 권한을 부여/허용하는 과정을 말한다.)

  • Chamomile에서의 authorization은 권한에 대한 정보를 RDB로 관리 할 수 있도록 기능을 확장하였다.

  • 보호되는 자원(리소스)에 대한 DB 권한 처리

  • 권한 계층 정보의 DB 화

  • 보호되는 자원에 접근하게 되는 경우 FilterSecurityInterceptor에서 요청을 받아 처리하게 된다.

  • 실제 대상 보호되는 자원에 접근하기 전 beforeInvocation()을 수행하고 권한이 존재하는지 확인하게 된다.

  • 먼저 현재 요청에 대한 권한 정보를 획득한다. (리소스에 부여된 권한 정보 – RDB로 관리된다.)

  • 인증이 필요한 경우 인증을 수행한다.

  • AccessDecisionManager.decide()를 통해 리소스에 대한 접근의 가부를 결정한다. (Spring Security에서는 투표방식으로 접근 여부를 결정한다.)

    • 총 3개의 AccessDecisionManager가 제공된다.
    • AffirmativeBased(하나라도 접근허용 한다면) – 기본설정, ConsensusBased(허용하는것이 접근거부보다 많다면, UnanimousBased(만장일치)
    • 등록 된 AccessDecisionVoter의 투표에 의한 결정.
  • 접근이 허용되는 경우 요청을 전달하게 되고, AfterInvocationManager를 통한 반환되는 결과에 대한 후처리 작업을 진행하게 된다.

설정

  • 설정방법
    • 아래와 같이 파일내 설정을 해준다.
    • pom.xml
      
          net.lotte.chamomile.module
          chamomile-security
      
      • Autoconfiguration 설정에 의해 자동으로 Bean에 등록 된다.
      • 모든 모듈 구성은 해당 Bean에 의해 자동으로 구성된다.
      • 필요에 따라 수정이 필요한 부분은 별도의 Bean을 작성하여 사용자 정의할 수 있다.
    • application.yml
      chmm:
      ##SECURITY
      security:
          # 로그인 처리를 위한 URL 경로를 설정합니다.
          loginProcessingUrl: /login
          # 로그아웃 처리를 위한 URL 경로를 설정합니다.
          logoutProcessingUrl: /logout
          # 로그인 폼에서 사용자 이름을 받기 위한 파라미터 이름을 설정합니다.
          usernameParameter: username
          # 로그인 폼에서 비밀번호를 받기 위한 파라미터 이름을 설정합니다.
          passwordParameter: password
          # 기본 비밀번호 인코더로 SHA-256 해시 알고리즘을 사용합니다.
          defaultPasswordEncoder: sha256
          # 사용 가능한 비밀번호 인코더 목록을 설정합니다. 여기서는 SHA-256과 bcrypt를 사용합니다.
          passwordEncoderList: sha256,bcrypt
          # 보안 검사를 무시할 URL 패턴 목록을 설정합니다.
          rsaPassword:  # 패스워드 RSA 복호화
                      use : false  
                      # true: RSA 복호화 사용
                      # false : 일반 평문 사용(RSA 사용X)
                      privateKey : sampleKey 
          ignorePatterns: 
              - /security/test
      # custom
      autoconfig:
          # true: autoconfig 설정에 의해 chamomile-security 모듈 자동등록
          # false : 사용자단에서 별도의 SecurityConfiguration 구성 후 진행 가능
          use: true
          # 리멤버미 설정
          rememberMe: true
          # 유효 기간을 초 단위로 설정합니다. 여기서는 604800초(7일)로 설정합니다.
          rememberMeValiditySeconds: 604800
          # 동시 세션의 최대 수를 설정합니다. -1은 제한이 없음을 의미합니다.
          maximumSessions: -1
          # 로그인 후 리디렉션될 기본 반환 URL을 설정합니다.
          returnUrl: /index.html
      • 여기까지 설정 내용을 토대로 전체적인 세션기반 시큐리티 설정이 가능하며 로그인이 가능하다.
      • 아래 내용부터 ChamomileSecurityConfiguration.java 에 있는 기능 설명에 대한 내용이다.

SecurityFilterChain

  • Spring Security는 HTTP 요청을 처리하기 위해 다양한 필터들의 체인을 사용하며, 이 메소드는 그 체인을 구성한다.

    @Bean
        public SecurityFilterChain filterChain(HttpSecurity http,AuthenticationManager authManager,AuthenticationProvider chamomileAuthenticationProvider
                , RoleHierarchyService roleHierarchyService, AuthenticationSuccessHandler authenticationSuccessHandler, AuthenticationFailureHandler authenticationFailureHandler) throws Exception {
            http.httpBasic();
            configureRememberMe(http);
            configureSessionManagement(http);
            addAuthenticationProvider(http, chamomileAuthenticationProvider);
            addSecurityInterceptorFilter(http, authManager, roleHierarchyService);
            configureFormLogin(http, authenticationSuccessHandler, authenticationFailureHandler);
            configureLogoutHandling(http);
            configureExceptionHandling(http);
    
            return http.build();
        }
  • http.httpBasic():
    • 기본 HTTP 인증을 활성화한다. 사용자 이름과 비밀번호를 통한 간단한 인증 방법이다.
  • http.rememberMe():
    • rememberMe() 메소드는 HTTP 요청에 ‘Remember Me’ 기능을 활성화한다.
  • configureSessionManagement();
    • 동시세션 제어를 한다.
  • addAuthenticationProvider()
    • 커스텀 AuthenticationProvider인 chamomileAuthenticationProvider를 Spring Security에 추가한다.
  • addSecurityInterceptorFilter()
    • 보호되는 자원을 RDB로 처리하기 위한 FilterSecurityInterceptor이다.
      • 모든 요청에 대해 권한이 적절한지 검사를 수행한다.
    • authManager:
      • AuthenticationManager는 사용자 인증을 처리하는 구성요소이다. 이 매니저는 인증 과정을 관리한다.
    • accessDecisionManager(roleHierarchyService):
      • accessDecisionManager 메소드는 접근 결정을 내리는 데 필요한 로직을 구현한다. 이 메소드는 RoleHierarchyService를 사용하여 역할 계층 구조에 따라 접근 결정을 내릴 수 있다.
      • reloadableFilterInvocationSecurityMetadataSource():
      • 이 메소드는 FilterInvocationSecurityMetadataSource의 구현체를 제공한다. 이 구현체는 각 HTTP 요청에 필요한 보안 메타데이터(예: 요청에 필요한 권한)를 결정한다.
  • configureFormLogin()
    • form 기반 인증 관련 메서드
    • http.formLogin():
      • HttpSecurityformLogin() 메소드를 호출하여 폼 로그인을 활성화한다.
    • loginProcessingUrl(...):
      • 로그인 처리를 위한 URL을 설정한다. 사용자가 로그인 폼을 제출할 때 이 URL로 요청을 보낸다. securityProperties.getLoginProcessingUrl()을 통해 이 URL을 가져온다.
    • usernameParameter(...), .passwordParameter(...):
      • 사용자 이름과 비밀번호 필드의 이름을 설정한다. 폼에서 사용되는 입력 필드의 이름을 지정한다.
    • successHandler(...), .failureHandler(...):
      • 로그인 성공 및 실패 처리를 위한 핸들러를 설정한다. 로그인 성공 시 authenticationSuccessHandler가, 실패 시 authenticationFailureHandler가 호출된다.
  • configureLogoutHandling()
    • 로그아웃 구성을 작성하기 위한 메서드.
    • http.logout():
      • HttpSecuritylogout() 메소드를 호출하여 로그아웃 기능을 활성화한다. 이 메소드는 로그아웃 관련 설정을 정의할 수 있는 LogoutConfigurer 객체를 반환한다.
    • .logoutUrl(...):
      • 로그아웃을 처리할 URL을 설정한다. 이 URL은 사용자가 로그아웃 요청을 보낼 때 사용된다.
      • this.securityProperties.getLogoutProcessingUrl()를 통해 로그아웃 처리 URL을 가져온다.
      • 로그아웃 요청을 받을 URL을 지정하여, 사용자가 해당 URL로 요청을 보내 로그아웃을 수행할 수 있도록 설정한다.
  • configureExceptionHandling()
    • http.exceptionHandling().accessDeniedPage(page):
      • HttpSecurityexceptionHandling() 메소드를 사용하여 예외 처리 설정을 시작한다.
      • accessDeniedPage(page) 메소드로 사용자가 접근할 수 없는 리소스에 접근하려고 시도할 때 보여줄 페이지를 설정한다..

AuthenticationManager

  • 인증요청에 대한 처리 메서드
  • AuthenticationManager는 Spring Security의 핵심 인터페이스 중 하나로, 인증(Authentication) 과정을 관리한다.
    이 인터페이스는 사용자의 인증 정보(아이디와 비밀번호 등)를 받아 유효성을 검증하는 역할을 한다.

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
            return authenticationConfiguration.getAuthenticationManager();
            }

AuthenticationProvider

  • AuthenticationProvider는 Spring Security에서 인증 메커니즘을 추상화하는 인터페이스 이다.
    사용자가 제공한 인증 정보(예: 아이디와 비밀번호)를 검증하고, 해당 사용자에 대한 인증 결과를 반환하는 역할을 한다.
  • ChamomileAuthenticationProvider는 AuthenticationProvider 인터페이스이다.
    이 클래스는 특정 인증 로직(예: 사용자 인증, 권한 검사 등)을 구현하고 있다.

    • 사용자정보, 사용자권한, 사용자그룹권한, 계정만료, 계정잠김, 사용여부, 비밀번호 확인등
      @Bean
      @ConditionalOnMissingBean(AuthenticationProvider.class)
      public AuthenticationProvider getDaoAuthProvider() {
          return new ChamomileAuthenticationProvider();
          }

WebSecurityCustomizer

  • Spring Security에서 웹 보안 설정을 커스터마이징는 데 사용하는 인터페이스이다.
  • web.ignoring()은 특정 요청에 대해 Spring Security의 보안 필터를 적용하지 않도록 설정한다.
  • ‘{ chmm.security.ignorePatterns}’에 설정된 URL 패턴을 무시한다.
    • HttpSecurity 보다 우선 실행 된다. (filterChain 이전)
      @Bean
      public WebSecurityCustomizer webSecurityCustomizer() {
          return web -> {
          Optional.ofNullable(securityProperties.getIgnorePatterns())
          .ifPresent(patterns -> web.ignoring().antMatchers(patterns));
          };
      }

RememberMe

  • ‘Remember Me’ 기능을 구성한다. 이 기능은 사용자가 로그인 상태를 유지할 수 있게 한다.
    private void configureRememberMe(HttpSecurity http) {
        Optional.ofNullable(securityProperties.getAutoConfig().get("rememberMe"))
            .filter("true"::equals)
            .ifPresent(rememberMe -> {
                try {
                    http.rememberMe()
                            .rememberMeCookieName("custom-cookie")
                            .rememberMeParameter("remember-me")  .tokenValiditySeconds(Integer.parseInt(securityProperties.getAutoConfig().get("rememberMeValiditySeconds")));
                    } catch (Exception e) {
                        throw new ChamomileException(ChamomileExceptionCode.Unauthorized);
                    }
                });
        }
    • .rememberMeCookieName("custom-cookie"):
    • ‘Remember Me’ 쿠키의 이름을 "custom-cookie"로 설정한다.
  • .rememberMeParameter("remember-me"):
    • ‘Remember Me’ 파라미터의 이름을 "remember-me"로 설정한다. 이는 폼 제출 시 사용된다.
  • .tokenValiditySeconds(…):
    • ‘Remember Me’ 토큰의 유효 기간을 설정한다. 여기서는 securityProperties에서 "rememberMeValiditySeconds" 값을 가져와 해당 기간을 초 단위로 설정한다.

PasswordEncoder

  • 이 메서드는 PasswordEncoder 인터페이스의 인스턴스를 반환한다.
  • PasswordEncoder는 Spring Security에서 사용하는 인터페이스로, 비밀번호를 안전하게 저장하고 검증하는 데 사용된다.
  • 반환되는 객체는 MultiplePasswordEncoder라는 사용자 정의 클래스의 인스턴스이다. 여러 종류의 비밀번호 인코딩 방식을 지원하도록 설계된다.
    @Bean
    @ConditionalOnMissingBean({PasswordEncoder.class})
    public PasswordEncoder passwordEncoder() {
    return new MultiplePasswordEncoder(this.securityProperties.getDefaultPasswordEncoder(), this.securityProperties.getPasswordEncoderList());
        }

    JdbcUserDetailsService

  • JdbcUserDetailsService는 이 인터페이스의 구현체 중 하나로, 데이터베이스를 사용하여 사용자 정보를 로드하는데 사용된다.
  • chamomile에서 제공하는 테이블 형태의 구조로 사용자 정보를 제공한다.
    • dataSource : RDB에 연결하기 위한 데이터소스를 설정한다.
    • usersByUsernameQuery (optional) : 입력받은 사용자 아이디로 사용자를 조회하는 쿼리를 설정한다.
      • 쿼리의 결과는 기본적으로 6개의 항목을 조회하고 있다.
      • userId(아이디), userPassword(비밀번호), enabled(활성화여부), accountNonExpired(계정이만료되지 않았는지), accountNonLocked(계정이 잠겨있지 않았는지), credentialsNonExpired(비밀번호가 만료되지 않았는지): 순서는 변경되어서는 안된다.
      • 예) select userId, userPassword, enabled, accountNonExpired, accountNonLocked, credentialsNonExpired from {your table} where {start_date} < ? and {end_date} > ? and userId = ?
    • authoritiesByUsernameQuery (optional) : 입력받은 사용자 아이디에 부여 된 권한 목록을 조회하는 쿼리를 설정한다.
      • 쿼리의 결과는 기본적으로 2개의 항목을 조회하고 있다.
      • userId(아이디), roleId(권한): 순서가 변경되어서는 안된다.
    • groupAuthoritiesByUsernameQuery (optional) : 사용자가 속한 그룹의 권한 목록을 조회하는 쿼리를 설정한다.
      • 쿼리의 결과는 기본적으로 3개의 항목을 조회하고 있다.
      • userId(아이디), groupId(그룹), roleId(권한): 순서가 변경되어서는 안된다.
        @Bean
        public JdbcUserDetailsService jdbcUserDetailsService(DataSource dataSource) throws Exception {
        JdbcUserDetailsService jdbcUserDetailsService = new JdbcUserDetailsService();
        jdbcUserDetailsService.setDataSource(dataSource);
        return jdbcUserDetailsService;
        }

AccessDecisionManager

  • 리소스에 대한 접근 여부를 결정하기 위한 판단주체이다.
  • 설정 된 AccessDecisionManager는 등록 된 voter 중 하나라도 리소스에 대한 접근을 허용하게 되는 경우 접근하도록 결정한다.
  • 2개의 AccessDecisionVoter가 설정되어 있으며, expression 기반의 처리와 권한계층을 포함하는 Role Voter가 설정되어져 있다.
    @Bean
    public AccessDecisionManager accessDecisionManager(RoleHierarchyService RoleHierarchyService) {
            WebExpressionVoter webExpressionVoter = new WebExpressionVoter();
            webExpressionVoter.setExpressionHandler(this.webSecurityExpressionHandler(RoleHierarchyService));
            RoleHierarchyVoter roleHierarchyVoter = new RoleHierarchyVoter(this.reloadableRoleHierarchy(RoleHierarchyService));
            roleHierarchyVoter.setRolePrefix("");
            List> decisionVoters = Arrays.asList(webExpressionVoter, roleHierarchyVoter);
            return new AffirmativeBased(decisionVoters);
    }
    • WebExpressionVoter 객체는 Spring Security의 표현식 기반 접근 제어(예: hasRole(‘ROLE_USER’))를 평가하는 데 사용된다.
    • webSecurityExpressionHandler 메서드는 RoleHierarchyService를 사용하여 역할 계층을 지원한다.
    • RoleHierarchyVoter 역할 계층을 고려하여 접근 결정을 내리는 데 사용한다.
    • AffirmativeBased AffirmativeBased는 제공된 투표자(decisionVoters) 목록 중 하나라도 접근을 승인하면, 접근을 허용하는 결정 전략을 사용한다.

ReloadableFilterInvocationSecurityMetadataSource

  • 리소스(주로 URL)에 대한 보안 메타데이터를 관리하는 컴포넌트이다
  • 필터 체인에서 URL 기반의 보안 메타데이터를 동적으로 관리해준다.
  • 보안 메타데이터를 변경할 필요가 있을 때 애플리케이션을 재시작 하지 않고도 변경 사항을 적용할 수 있게 해준다.
    @Bean
    public ReloadableFilterInvocationSecurityMetadataSource reloadableFilterInvocationSecurityMetadataSource() {
            ReloadableFilterInvocationSecurityMetadataSource reloadableFilterInvocationSecurityMetadataSource = new ReloadableFilterInvocationSecurityMetadataSource();
            reloadableFilterInvocationSecurityMetadataSource.setSecuredUrlResourceService(securedUrlResourceService(dataSource));
            return reloadableFilterInvocationSecurityMetadataSource;
        }

SecuredUrlResourceService

  • URL 리소스에 대한 권한정보를 제공하는 서비스
  • dataSource : RDB의 데이터소스를 설정한다.
  • rolesQuery : URL 리소스에 대한 권한 정보를 조회하는 쿼리를 설정한다.
    • 기본적으로 url(리소스 url 정보), authority(권한)을 조회하게 되어 있다.
    • 순서와 명칭이 동일해야 한다.
      @Bean
      public SecuredUrlResourceService securedUrlResourceService(DataSource dataSource) {
          SecuredUrlResourceService securedUrlResourceService = new SecuredUrlResourceService();
          securedUrlResourceService.setDataSource(dataSource);
          return securedUrlResourceService;
          }

ReloadableRoleHierarchy

  • 권한의 계층정보를 제공한다.
  • 역할 계층(Role Hierarchy)을 관리하는 컴포넌트로, 역할 간의 관계를 정의하고 동적으로 업데이트할 수 있게 한다
  • 상위 역할이 하위 역할의 권한을 상속받는 구조를 만들 수 있다.
    @Bean
    public ReloadableRoleHierarchy reloadableRoleHierarchy(RoleHierarchyService RoleHierarchyService) {
        ReloadableRoleHierarchy reloadableRoleHierarchy = new ReloadableRoleHierarchy();
        reloadableRoleHierarchy.setRoleHierarchyService(RoleHierarchyService);
        return reloadableRoleHierarchy;
        }

jdbcRoleHierarchyService

  • 권한의 계층 정보를 제공하는 서비스
  • dataSource : RDB의 데이터소스를 설정한다.
  • hierarchicalRolesQuery : 권한의 계층 정보를 조회하는 쿼리를 설정한다.
    • 기본적으로 parent(상위 권한), child(하위 권한)을 조회하게 되어 있다.
    • 순서와 명칭이 동일해야 한다.
      @Bean
      @ConditionalOnMissingBean({RoleHierarchyService.class})
      public JdbcRoleHierarchyService jdbcRoleHierarchyService(DataSource dataSource) {
          JdbcRoleHierarchyService roleHierarchyService = new JdbcRoleHierarchyService();
          roleHierarchyService.setDataSource(dataSource);
          return roleHierarchyService;
          }

FilterSecurityInterceptor

  • 보호되는 자원을 RDB로 처리하기 위한 FilterSecurityInterceptor이다.
    • 모든 요청에 대해 권한이 적절한지 검사를 수행한다.
    • 인증과 권한 부여의 중심 역할을 하며, 각 HTTP 요청이 보안 정책에 부합하는지를 검사한다
  • authenticationManager : 추가 인증이 필요한경우 사용하게 될 인증 처리 주체
    • 사용자의 인증 요청을 처리하는 역할
  • accessDecisionManager : 리소스에 대한 접근 여부를 판단하게 될 AccessDecisionManager를 설정한다.
    • 요청된 리소스에 대한 접근을 승인할 것인지를 결정
  • securityMetadataSource : RDB로 관리되는 보호되는 자원(리소스)를 제공하는 메타데이터소스
    • 보호되는 리소스(예: URL)에 대한 보안 메타데이터를 제공
  • rejectPublicInvocations : 권한을 부여하지 않은 리소스에 대한 접근 시 오류 발생 여부 설정
    public FilterSecurityInterceptor filterSecurityInterceptor(AuthenticationManager authenticationManager, AccessDecisionManager accessDecisionManager, ReloadableFilterInvocationSecurityMetadataSource reloadableFilterInvocationSecurityMetadataSource) {
            FilterSecurityInterceptor customFilterSecurityInterceptor = new FilterSecurityInterceptor();
            //인증 처리 주체로서, 사용자의 인증 요청을 처리하는 AuthenticationManager를 설정
            customFilterSecurityInterceptor.setAuthenticationManager(authenticationManager);
            //RDB로 관리되는 보호되는 자원(리소스)를 제공하는 메타데이터소스
            customFilterSecurityInterceptor.setSecurityMetadataSource(reloadableFilterInvocationSecurityMetadataSource);
            //리소스에 대한 접근 여부를 판단하게 될 AccessDecisionManager를 설정
            //주어진 인증과 요청한 URL리소스에 대해 사용자가 접근할 권한이 있는지 결정
            customFilterSecurityInterceptor.setAccessDecisionManager(accessDecisionManager);
            //권한을 부여하지 않은 리소스에 대한 접근 시 오류 발생 여부 설정
            customFilterSecurityInterceptor.setRejectPublicInvocations(true);
            return customFilterSecurityInterceptor;
        }

커스터마이징

  • AuthenticationSuccessHandler.java
    • Provider의 경우 프로젝트 상황에 맞게 수정이 가능하다.
    • 프로젝트 내에 특정 패키지에 아래 AuthenticationSuccessHandler.java를 생성해준다.
    @Configuration  
    public class CustomAuthenticationProvider implements AuthenticationProvider {  
        @Autowired  
        private JdbcUserDetailsService jdbcUserDetailsService;  

        @Autowired  
        private JdbcLoginService jdbcLoginService;  

        @Autowired  
        private PasswordEncoder passwordEncoder;  

        @Override  
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {  
            try {  
                String loginId = authentication.getName();  
                String password = (String) authentication.getCredentials();  

                LoggingUtils.userAccessLogging(loginId, UserAccessActionType.LOGIN_ATTEMPT);  
                // 입력받은 userID로 사용자 정보(UserDetails)를 조회하여 반환한다. (사용자정보, 사용자권한 사용자그룹권한)  
                DefaultUser userDetails = (DefaultUser) jdbcUserDetailsService.loadUserByUsername(loginId);  

                checkCredentials(password, userDetails);  
                checkAccountStatus(userDetails);  

                LoggingUtils.userAccessLogging(loginId, UserAccessActionType.LOGIN_SUCCESS);  
                return new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());  
            } catch (ChamomileException ex) {  
                throw new AuthenticationServiceException(ex.getMessage(), new ChamomileException(((ChamomileException) ex).getChamomileCode(), ex.getMessage()));  
            } catch (Exception ex) {  
                throw new AuthenticationServiceException(ex.getMessage());  
            }  
        }  

        @Override  
        public boolean supports(Class authentication) {  
            return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);  
        }
    }
  • AuthenticationSuccessHandler.java

    • SampleLoginSuccessHandler는 AuthenticationProvide 에서 계정 유효성 검사 성공시 후 처리 역활을 한다.
    • 프로젝트 내에 특정 패키지에 아래 SampleLoginSuccessHandler는.java를 생성해준다.

      @Configuration  
      public class SampleLoginSuccessHandler implements AuthenticationSuccessHandler {  
      private static final Logger LOGGER = LoggerFactory.getLogger(SampleLoginSuccessHandler.class);  
      private final ObjectMapper objectMapper;  
      
      public SampleLoginSuccessHandler() {  
          this.objectMapper = new ObjectMapper();  
      }  
      @Override  
      public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,  
              Authentication authentication) throws IOException, ServletException {  
      
          String userID = authentication.getName();  
          LOGGER.info("Account that succeeded authentication : {}", userID);  
          //락카운트 초기화 등 필요한 기능 추가 
      
          Map map = new HashMap<>();  
          map.put("success", true);  
      
          String jsonString = objectMapper.writeValueAsString(map);  
      
          try (OutputStream out = response.getOutputStream()) {  
              out.write(jsonString.getBytes());  
          }  
      }  
      }
  • AuthenticationFailureHandler

    • SampleLoginFailureHandler는 AuthenticationProvide 에서 계정 유효성 검사 실패시 후 처리 역활을 한다.
    • 프로젝트 내에 특정 패키지에 아래 AuthenticationFailureHandler.java를 생성해준다.

      @Configuration  
      public class SampleLoginFailureHandler implements AuthenticationFailureHandler {  
          private static final Logger LOGGER = LoggerFactory.getLogger(SampleLoginFailureHandler.class);  
      
          @Autowired  
          private JdbcLoginService jdbcLoginService;  
      
          @Override  
          public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,  
                  AuthenticationException exception) throws IOException, ServletException {  
              String userID = request.getParameter("username");  
      
              try {  
                  jdbcLoginService.lockProcessAccount(userID, exception);  
              } catch (Exception e) {  
                  throw new RuntimeException(e);  
              }  
              Map responseMap = new HashMap<>();  
              responseMap.put("success", false);  
      
              String jsonResponse = new ObjectMapper().writeValueAsString(responseMap);  
              response.getOutputStream().write(jsonResponse.getBytes());  
          }  
      }
  • ChamomileSecurityConfiguration 커스텀

    • 캐모마일 시큐리티 설정에 대한 전반적인 수정이 필요한 경우 아래 properties내 설정 후 전체적인 커스텀 및 사용자가 작성한 Security 적용이 가능하다.

    • 단 캐모마일 시큐리티에 대한 커스텀이 아닌 새로운 SecurityConfiguration 구성시 pom.xml 내 chamomile-security의존성을 제거 후 진행한다.

    • 설정방법

      chmm:
          # custom 
          autoconfig:
              use: false  
              # true: autoconfig 설정에 의해 chamomile-security 모듈 자동등록
              # false : 사용자단에서 별도의 SecurityConfiguration 구성 후 진행 가능
    • 아래 CustomsecurityConfiguration.java 를 예시로 설정시 전체적인 커스텀이 가능하다.

    • CustomsecurityConfiguration 전체 소스는 캐모마일 담당자를 통해 요청시 제공한다.

    • CustomsecurityConfiguration.java

      • 프로젝트 내에 특정 패키지에 아래 CustomsecurityConfiguration.java을 생성해준다.

        @Configuration  
        @EnableWebSecurity  
        @EnableConfigurationProperties({ChamomileSecurityProperties.class})  
        public class CustomsecurityConfiguration  {  
        private final ChamomileSecurityProperties securityProperties;  
        private final DataSource dataSource;  
        
        public ChamomileSecurityJwtConfiguration(ChamomileSecurityProperties securityProperties,  DataSource dataSource) {  
            this.dataSource = dataSource;  
            this.securityProperties = securityProperties;  
        }  
        /**  
         * 인증 요청에 대한 처리 메서드  
         * JdbcUserDetailsService PasswordEncoder가 자동으로 설정 (provider 사용안할시)  
         * 복수 공급자 사용시 provider 수정 사용하여 이용 가능  
         * @param authenticationConfiguration  
         * @return  
         * @throws Exception  
         */  
        @Bean  
        public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {  
            return authenticationConfiguration.getAuthenticationManager();  
        }
        /**  
         * 인증 프로세스 provider  
         * {@link AuthenticationProvider} 구현 후 Bean 등록시 사용자단에서 커스텀 가능  
         * 다중 provider 구성 가능  
         * @return  
         * @throws Exception  
         */  
        @Bean  
        @ConditionalOnMissingBean({AuthenticationProvider.class})  
        public AuthenticationProvider getDaoAuthProvider() {  
            return new JwtAuthenticationProvider();  
        }
        /** 이하 내용 생략 **/
        }
이전 시큐리티(JWT)