Apress / pivotal-certified-pro-spring-dev-exam-02

Source Code for 'Pivotal Certified Professional Core Spring 5 Developer Exam' by Iuliana Cosmina
Other
168 stars 239 forks source link

Chapter 07 Examples fail to start with: An Authentication object was not found in the SecurityContext #18

Closed urs-beeli closed 3 years ago

urs-beeli commented 3 years ago

Hi iuliana

Thank you for your book, I'm really enjoying working through it. I have succesfully managed to launch all chapter 06 examples in Tomcat using IntelliJ run configurations as described in the book.

However, when I try to do the same with the chapter 07 examples, each of them fails with the same stack trace:

14:26:17.885 [http-nio-3054-exec-6] ERROR o.s.w.s.DispatcherServlet - Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'initializer': Invocation of init method failed; nested exception is org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:160) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:416) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:702) at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:578) at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:530) at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:170) at javax.servlet.GenericServlet.init(GenericServlet.java:158) at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1134) at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:777) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:135) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.base/java.lang.Thread.run(Thread.java:834) Caused by: org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:379) at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:223) at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:65) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy117.findAll(Unknown Source) at com.apress.cems.dj.services.Initializer.init(Initializer.java:81) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157) ... 35 common frames omitted

Is there some specific setup required for Tomcat to work with spring security?

urs-beeli commented 3 years ago

Playing around with the mvc-sec project, changing WebInitializer from

@Override protected Class<?>[] getServletConfigClasses() { return new Class[]{H2DbConfig.class, ServiceConfig.class,WebConfig.class, SecurityConfig2.class}; }

to

@Override protected Class<?>[] getServletConfigClasses() { return new Class[]{H2DbConfig.class, ServiceConfig.class,WebConfig.class, SecurityConfig.class}; }

makes the application work. It seems that
@EnableGlobalMethodSecurity(prePostEnabled = true) is required for the application to start. With any of the other two // @EnableGlobalMethodSecurity(securedEnabled = true) // @EnableGlobalMethodSecurity(jsr250Enabled = true) I get the above exception.

urs-beeli commented 3 years ago

Playing some more, it seems that while that lets me at least start the application and show the /home view, as soon as I navigate to /persons/list I get the following error:

org.apache.jasper.JasperException: Beim Verarbeiten von [/WEB-INF/persons/list.jsp] ist in Zeile [72] eine Ausnahme erzeugt worden 69: <c:if test="${menuTab != 'users'}"> 70: <a href="<c:url value="/persons/list"/>"><spring:message code="menu.persons"/></a> 71: </c:if> 72: <sec:authorize access="/person/newPerson"> 73: <ul> 74: <li> 75: <c:if test="${navigationTab eq 'newPerson'}">

So it seems that the <sec:authorize token causes issues...

iuliana commented 3 years ago

Hello urs-beeli,

I am currently building the project. I will come back to you in a short while with an explanation. If the issue is indeed that element, that means there is an issue with the Spring Security Tag library.

Cheers!

iuliana commented 3 years ago

Hello urs-beeli,

The reson why the application was failing to start is because there security at the servie level, but no security class is configured. The mvc-sec project contains 2 security classes SecurityConfig and SecurityConfig2, you can use one or the other, but the WebInitializer class you have to set any of them as a Root configuration class, so that security is enabled for the service layer as weel.

It was a bad decision from my part to use the same project to show security configured at metod level as well, but at the time I saw no point of duplicatign the whole project just to add 2 extra annotations, and went for a redundancy in the WebInitializer class.

I pushed the changes and you should be able to deploy the project on Apache Tomcat now.

Cheers!