시큐리티(세션)
본 문서에서는 웹사이트에서 사용하는 세션기반 시큐리티를 사용하기 위한 기능을 제공한다.
캐모마일의 Security 기능은 Spring Security5.7 기반 하에 작업 되었다.
authentication(인증)
-
인증은 사용자의 신원을 확인하는 과정을 의미한다. Chamomile에서의 인증은 Spring Security에서 제공하는 사용자 인증 정보를 RDB로 관리하기 위해 JdbcDaoImpl(UserDetailsService의 구현체)을 확장하여 제공한다.
-
사용자 인증 정보
- 사용자의 정보, 사용자가 가진 권한, 사용자가 속한 그룹에 대한 권한 정보를 바탕으로 인증이 이루어진다.
-
인증 매커니즘
- 기본적인 인증 매커니즘은 Spring Security의 인증 매커니즘을 그대로 사용하며, 아래와 같은 흐름으로 이루어진다.
-
- 인증 요청
- UsernamePasswordAuthenticationFilter에서 사용자가 입력한 아이디와 비밀번호를 기반으로 UsernamePasswordAuthenticationToken을 생성한다.
- 인증 요청
-
- AuthenticationManager 위임
- AuthenticationManager에 AuthenticationToken을 전달하여 인증을 위임한다.
- AuthenticationManager 위임
-
- Authentication 정보 획득
- AuthenticationManager에 등록된 AuthenticationProvider를 통해 Authentication 정보를 획득한다.
- Authentication 정보 획득
-
- RDB를 통한 인증 정보 획득
- RDB를 통해 사용자 아이디를 기반으로 Authentication 정보를 획득하고, 사용자가 가진 권한 및 사용자가 속한 그룹의 권한 정보를 획득한다.
- RDB를 통한 인증 정보 획득
-
- 사용자 상태 확인 및 인증 수행
- 사용자의 기본적인 상태(계정 잠김, 비활성화, 만료 등)를 확인하고, 정상적인 경우 패스워드를 검사하여 인증을 수행한다. 그 후, 비밀번호 상태(비밀번호 만료 등)를 확인한다.
- 사용자 상태 확인 및 인증 수행
-
- 인증 성공 후 처리
- 인증이 성공하면, 원래 요청한 페이지로 redirect 된다.
authorization(인가)
- 인증이 성공하면, 원래 요청한 페이지로 redirect 된다.
- 인증 성공 후 처리
-
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에 추가한다.
- 커스텀 AuthenticationProvider인
addSecurityInterceptorFilter()
- 보호되는 자원을 RDB로 처리하기 위한
FilterSecurityInterceptor
이다.- 모든 요청에 대해 권한이 적절한지 검사를 수행한다.
authManager
:AuthenticationManager
는 사용자 인증을 처리하는 구성요소이다. 이 매니저는 인증 과정을 관리한다.
accessDecisionManager(roleHierarchyService)
:accessDecisionManager
메소드는 접근 결정을 내리는 데 필요한 로직을 구현한다. 이 메소드는RoleHierarchyService
를 사용하여 역할 계층 구조에 따라 접근 결정을 내릴 수 있다.reloadableFilterInvocationSecurityMetadataSource()
:- 이 메소드는
FilterInvocationSecurityMetadataSource
의 구현체를 제공한다. 이 구현체는 각 HTTP 요청에 필요한 보안 메타데이터(예: 요청에 필요한 권한)를 결정한다.
- 보호되는 자원을 RDB로 처리하기 위한
configureFormLogin()
- form 기반 인증 관련 메서드
http.formLogin()
:HttpSecurity
의formLogin()
메소드를 호출하여 폼 로그인을 활성화한다.
loginProcessingUrl(...)
:- 로그인 처리를 위한 URL을 설정한다. 사용자가 로그인 폼을 제출할 때 이 URL로 요청을 보낸다.
securityProperties.getLoginProcessingUrl()
을 통해 이 URL을 가져온다.
- 로그인 처리를 위한 URL을 설정한다. 사용자가 로그인 폼을 제출할 때 이 URL로 요청을 보낸다.
usernameParameter(...)
,.passwordParameter(...)
:- 사용자 이름과 비밀번호 필드의 이름을 설정한다. 폼에서 사용되는 입력 필드의 이름을 지정한다.
successHandler(...)
,.failureHandler(...)
:- 로그인 성공 및 실패 처리를 위한 핸들러를 설정한다. 로그인 성공 시
authenticationSuccessHandler
가, 실패 시authenticationFailureHandler
가 호출된다.
- 로그인 성공 및 실패 처리를 위한 핸들러를 설정한다. 로그인 성공 시
configureLogoutHandling()
- 로그아웃 구성을 작성하기 위한 메서드.
http.logout()
:HttpSecurity
의logout()
메소드를 호출하여 로그아웃 기능을 활성화한다. 이 메소드는 로그아웃 관련 설정을 정의할 수 있는LogoutConfigurer
객체를 반환한다.
.logoutUrl(...)
:- 로그아웃을 처리할 URL을 설정한다. 이 URL은 사용자가 로그아웃 요청을 보낼 때 사용된다.
this.securityProperties.getLogoutProcessingUrl()
를 통해 로그아웃 처리 URL을 가져온다.- 로그아웃 요청을 받을 URL을 지정하여, 사용자가 해당 URL로 요청을 보내 로그아웃을 수행할 수 있도록 설정한다.
configureExceptionHandling()
http.exceptionHandling().accessDeniedPage(page)
:HttpSecurity
의exceptionHandling()
메소드를 사용하여 예외 처리 설정을 시작한다.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)); }; }
- HttpSecurity 보다 우선 실행 된다. (filterChain 이전)
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(); } /** 이하 내용 생략 **/ }
-
-