본문 바로가기

Backend Development/Spring boot

[Spring boot] Spring Security 분석 - Authentication 에러 처리

token이 만료되어 Access denied exception이 떳을때

 

org/springframework/security/access/intercept/AbstractSecurityInterceptor.java:178
attemptAuthorization(object, attributes, authenticated) 를 부를기 전에
SecurityContextHolder.getContext().getAuthentication()를 가져온다.

 

=> 따라서 filter에서 SecurityContextHolder.getContext().setAuthentication 를 안해주면 access denied 에러가 발생하게 된다.

 

org/springframework/security/access/intercept/AbstractSecurityInterceptor.java

protected InterceptorStatusToken beforeInvocation(Object object) {
    Assert.notNull(object, "Object was null");
    if (!getSecureObjectClass().isAssignableFrom(object.getClass())) {
        throw new IllegalArgumentException("Security invocation attempted for object " + object.getClass().getName()
                + " but AbstractSecurityInterceptor only configured to support secure objects of type: "
                + getSecureObjectClass());
    }
    Collection<ConfigAttribute> attributes = this.obtainSecurityMetadataSource().getAttributes(object);
    if (CollectionUtils.isEmpty(attributes)) {
        Assert.isTrue(!this.rejectPublicInvocations,
                () -> "Secure object invocation " + object
                        + " was denied as public invocations are not allowed via this interceptor. "
                        + "This indicates a configuration error because the "
                        + "rejectPublicInvocations property is set to 'true'");
        if (this.logger.isDebugEnabled()) {
            this.logger.debug(LogMessage.format("Authorized public object %s", object));
        }
        publishEvent(new PublicInvocationEvent(object));
        return null; // no further work post-invocation
    }
    if (SecurityContextHolder.getContext().getAuthentication() == null) {
        credentialsNotFound(this.messages.getMessage("AbstractSecurityInterceptor.authenticationNotFound",
                "An Authentication object was not found in the SecurityContext"), object, attributes);
    }
    
    // Attemp authrization 전에 Authentication 정보를 가져온다.
    Authentication authenticated = authenticateIfRequired();
    if (this.logger.isTraceEnabled()) {
        this.logger.trace(LogMessage.format("Authorizing %s with attributes %s", object, attributes));
    }
    // Attempt authorization
    attemptAuthorization(object, attributes, authenticated);

 

org/springframework/security/access/intercept/AbstractSecurityInterceptor.java => authenticateIfRequired 메소드

/**
	 * Checks the current authentication token and passes it to the AuthenticationManager
	 * if {@link org.springframework.security.core.Authentication#isAuthenticated()}
	 * returns false or the property <tt>alwaysReauthenticate</tt> has been set to true.
	 * @return an authenticated <tt>Authentication</tt> object.
	 */
	private Authentication authenticateIfRequired() {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if (authentication.isAuthenticated() && !this.alwaysReauthenticate) {
			if (this.logger.isTraceEnabled()) {
				this.logger.trace(LogMessage.format("Did not re-authenticate %s before authorizing", authentication));
			}
			return authentication;
		}
		authentication = this.authenticationManager.authenticate(authentication);
		// Don't authenticated.setAuthentication(true) because each provider does that
		if (this.logger.isDebugEnabled()) {
			this.logger.debug(LogMessage.format("Re-authenticated %s before authorizing", authentication));
		}
		SecurityContextHolder.getContext().setAuthentication(authentication);
		return authentication;
	}

 

Authentication Exception 발생시 Security Config에 설정한 Exception Handling에 의해 처리가 된다.

.exceptionHandling().authenticationEntryPoint(new BasicAuthenticationPoint());

 

commence:31, BasicAuthenticationPoint (com.sdp.common.security)
sendStartAuthentication:213, ExceptionTranslationFilter (org.springframework.security.web.access)
handleAccessDeniedException:192, ExceptionTranslationFilter (org.springframework.security.web.access)
handleSpringSecurityException:173, ExceptionTranslationFilter (org.springframework.security.web.access)
doFilter:142, ExceptionTranslationFilter (org.springframework.security.web.access)
doFilter:115, ExceptionTranslationFilter (org.springframework.security.web.access)
doFilter:336, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilter:126, SessionManagementFilter (org.springframework.security.web.session)
doFilter:81, SessionManagementFilter (org.springframework.security.web.session)
doFilter:336, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilter:105, AnonymousAuthenticationFilter (org.springframework.security.web.authentication)
doFilter:336, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilter:149, SecurityContextHolderAwareRequestFilter (org.springframework.security.web.servletapi)
doFilter:336, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilter:63, RequestCacheAwareFilter (org.springframework.security.web.savedrequest)
doFilter:336, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilterInternal:47, TokenAuthenticationFilter (com.sdp.common.security)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
doFilter:336, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilter:103, LogoutFilter (org.springframework.security.web.authentication.logout)
doFilter:89, LogoutFilter (org.springframework.security.web.authentication.logout)
doFilter:336, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doHeadersAfter:90, HeaderWriterFilter (org.springframework.security.web.header)
doFilterInternal:75, HeaderWriterFilter (org.springframework.security.web.header)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
doFilter:336, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilter:110, SecurityContextPersistenceFilter (org.springframework.security.web.context)
doFilter:80, SecurityContextPersistenceFilter (org.springframework.security.web.context)
doFilter:336, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilterInternal:55, WebAsyncManagerIntegrationFilter (org.springframework.security.web.context.request.async)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
doFilter:336, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilterInternal:211, FilterChainProxy (org.springframework.security.web)
doFilter:183, FilterChainProxy (org.springframework.security.web)
invokeDelegate:358, DelegatingFilterProxy (org.springframework.web.filter)
doFilter:271, DelegatingFilterProxy (org.springframework.web.filter)
internalDoFilter:189, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:100, RequestContextFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:189, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:93, FormContentFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:189, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:201, CharacterEncodingFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:189, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
invoke:197, StandardWrapperValve (org.apache.catalina.core)
invoke:97, StandardContextValve (org.apache.catalina.core)
invoke:540, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:135, StandardHostValve (org.apache.catalina.core)
invoke:92, ErrorReportValve (org.apache.catalina.valves)
invoke:78, StandardEngineValve (org.apache.catalina.core)
service:357, CoyoteAdapter (org.apache.catalina.connector)
service:382, Http11Processor (org.apache.coyote.http11)
process:65, AbstractProcessorLight (org.apache.coyote)
process:895, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1722, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1191, ThreadPoolExecutor (org.apache.tomcat.util.threads)
run:659, ThreadPoolExecutor$Worker (org.apache.tomcat.util.threads)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:834, Thread (java.lang)

 

Authentication 에러도 Authorization 에러 부터 시작해서 처리가 됨을 알 수 있다.

 

Exception의 원천은 AccessDeniedException

더보기

cause = {AccessDeniedException@12857} "org.springframework.security.access.AccessDeniedException: Access is denied"
stackTrace = {StackTraceElement[68]@12862} 
 0 = {StackTraceElement@12864} "org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:73)"
 1 = {StackTraceElement@12865} "org.springframework.security.access.intercept.AbstractSecurityInterceptor.attemptAuthorization(AbstractSecurityInterceptor.java:238)"
 2 = {StackTraceElement@12866} "org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:208)"
 3 = {StackTraceElement@12867} "org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:113)"
 4 = {StackTraceElement@12868} "org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)"
 5 = {StackTraceElement@12869} "org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)"
 6 = {StackTraceElement@12870} "org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:121)"
 7 = {StackTraceElement@12871} "org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)"
 8 = {StackTraceElement@12872} "org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)"
 9 = {StackTraceElement@12873} "org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)"
 10 = {StackTraceElement@12874} "org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)"
 11 = {StackTraceElement@12875} "org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)"
 12 = {StackTraceElement@12876} "org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105)"
 13 = {StackTraceElement@12877} "org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)"
 14 = {StackTraceElement@12878} "org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)"
 15 = {StackTraceElement@12879} "org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)"
 16 = {StackTraceElement@12880} "org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)"
 17 = {StackTraceElement@12881} "org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)"
 18 = {StackTraceElement@12882} "com.sdp.common.security.TokenAuthenticationFilter.doFilterInternal(TokenAuthenticationFilter.java:47)"
 19 = {StackTraceElement@12883} "org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)"
 20 = {StackTraceElement@12884} "org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)"
 21 = {StackTraceElement@12885} "org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)"
 22 = {StackTraceElement@12886} "org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)"
 23 = {StackTraceElement@12887} "org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)"
 24 = {StackTraceElement@12888} "org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)"
 25 = {StackTraceElement@12889} "org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)"
 26 = {StackTraceElement@12890} "org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)"
 27 = {StackTraceElement@12891} "org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)"
 28 = {StackTraceElement@12892} "org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)"
 29 = {StackTraceElement@12893} "org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)"
 30 = {StackTraceElement@12894} "org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)"
 31 = {StackTraceElement@12895} "org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)"
 32 = {StackTraceElement@12896} "org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)"
 33 = {StackTraceElement@12897} "org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)"
 34 = {StackTraceElement@12898} "org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)"
 35 = {StackTraceElement@12899} "org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)"
 36 = {StackTraceElement@12900} "org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)"
 37 = {StackTraceElement@12901} "org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)"
 38 = {StackTraceElement@12902} "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)"
 39 = {StackTraceElement@12903} "org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)"
 40 = {StackTraceElement@12904} "org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)"
 41 = {StackTraceElement@12905} "org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)"
 42 = {StackTraceElement@12906} "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)"
 43 = {StackTraceElement@12907} "org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)"
 44 = {StackTraceElement@12908} "org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)"
 45 = {StackTraceElement@12909} "org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)"
 46 = {StackTraceElement@12910} "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)"
 47 = {StackTraceElement@12911} "org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)"
 48 = {StackTraceElement@12912} "org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)"
 49 = {StackTraceElement@12913} "org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)"
 50 = {StackTraceElement@12914} "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)"
 51 = {StackTraceElement@12915} "org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)"
 52 = {StackTraceElement@12916} "org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)"
 53 = {StackTraceElement@12917} "org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)"
 54 = {StackTraceElement@12918} "org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)"
 55 = {StackTraceElement@12919} "org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)"
 56 = {StackTraceElement@12920} "org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)"
 57 = {StackTraceElement@12921} "org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)"
 58 = {StackTraceElement@12922} "org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)"
 59 = {StackTraceElement@12923} "org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)"
 60 = {StackTraceElement@12924} "org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)"
 61 = {StackTraceElement@12925} "org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)"
 62 = {StackTraceElement@12926} "org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1722)"
 63 = {StackTraceElement@12927} "org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)"
 64 = {StackTraceElement@12928} "org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)"
 65 = {StackTraceElement@12929} "org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)"
 66 = {StackTraceElement@12930} "org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)"
 67 = {StackTraceElement@12931} "java.base/java.lang.Thread.run(Thread.java:834)"
depth = 68
suppressedExceptions = {Collections$EmptyList@8861}  size = 0