简体   繁体   中英

Spring MVC with Spring Security a simple example does not work

I'm having trouble with setting up a simple spring security. I'm trying to set up the most simple example possible with the configuration below. It seems that the request never gets intercepted?

Project structure

在此处输入图片说明

BasicController.java

package controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class BasicController {

    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello() {
        return "hello";
    }

}

web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
      /WEB-INF/spring/context.xml
      /WEB-INF/spring/security.xml
    </param-value>
  </context-param>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <servlet>
    <servlet-name>web</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value></param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>web</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

  <filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  </filter>

  <filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
  </filter>

</web-app>

security.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

    <security:http auto-config="true" use-expressions="true" >
        <security:intercept-url pattern="/**" access="isAuthenticated()" />
        <security:http-basic />
    </security:http>

    <security:authentication-manager>
        <security:authentication-provider>
            <security:user-service>
                <security:user name="admin" password="admin" authorities="ROLE_USER" />
            </security:user-service>
        </security:authentication-provider>
    </security:authentication-manager>

</beans>

context.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="controller" />

    <mvc:annotation-driven />

    <mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />

    <bean id="templateLoader" class="de.neuland.jade4j.spring.template.SpringTemplateLoader">
        <property name="basePath" value="/WEB-INF/views/" />
    </bean>

    <bean id="jadeConfiguration" class="de.neuland.jade4j.JadeConfiguration">
        <property name="prettyPrint" value="false" />
        <property name="caching" value="false" />
        <property name="templateLoader" ref="templateLoader" />
    </bean>

    <bean id="viewResolver" class="de.neuland.jade4j.spring.view.JadeViewResolver">
        <property name="configuration" ref="jadeConfiguration" />
        <property name="renderExceptions" value="true" />
    </bean>

</beans>

Logs

It evident that both spring configuration files are being read and security is mapped onto Creating access control expression attribute 'isAuthenticated()' for /** and yet the page is not protected!

Listening for transport dt_socket at address: 63383
Connected to the target VM, address: '127.0.0.1:63383', transport: 'socket'
Nov 25, 2016 11:50:42 AM org.springframework.web.context.ContextLoader initWebApplicationContext
INFO: Root WebApplicationContext: initialization started
Nov 25, 2016 11:50:42 AM org.springframework.web.context.support.XmlWebApplicationContext prepareRefresh
INFO: Refreshing Root WebApplicationContext: startup date [Fri Nov 25 11:50:42 GMT 2016]; root of context hierarchy
Nov 25, 2016 11:50:42 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from ServletContext resource [/WEB-INF/spring/context.xml]
Nov 25, 2016 11:50:43 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from ServletContext resource [/WEB-INF/spring/security.xml]
Nov 25, 2016 11:50:43 AM org.springframework.security.core.SpringSecurityCoreVersion performVersionChecks
INFO: You are running with Spring Security Core 4.2.0.RELEASE
Nov 25, 2016 11:50:43 AM org.springframework.security.config.SecurityNamespaceHandler <init>
INFO: Spring Security 'config' module version is 4.2.0.RELEASE
Nov 25, 2016 11:50:43 AM org.springframework.security.config.http.FilterInvocationSecurityMetadataSourceParser parseInterceptUrlsForFilterInvocationRequestMap
INFO: Creating access control expression attribute 'isAuthenticated()' for /**
Nov 25, 2016 11:50:43 AM org.springframework.security.config.http.AuthenticationConfigBuilder createLoginPageFilterIfNeeded
INFO: No login page configured. The default internal one will be used. Use the 'login-page' attribute to set the URL of the login page.
Nov 25, 2016 11:50:43 AM org.springframework.security.config.http.HttpSecurityBeanDefinitionParser checkFilterChainOrder
INFO: Checking sorted filter chain: [Root bean: class [org.springframework.security.web.context.SecurityContextPersistenceFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 200, Root bean: class [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 400, Root bean: class [org.springframework.security.web.header.HeaderWriterFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 500, Root bean: class [org.springframework.security.web.csrf.CsrfFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 700, Root bean: class [org.springframework.security.web.authentication.logout.LogoutFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 800, <org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0>, order = 1200, Root bean: class [org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 1400, Root bean: class [org.springframework.security.web.authentication.www.BasicAuthenticationFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 1600, Root bean: class [org.springframework.security.web.savedrequest.RequestCacheAwareFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 1700, Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.security.config.http.HttpConfigurationBuilder$SecurityContextHolderAwareRequestFilterBeanFactory#0; factoryMethodName=getBean; initMethodName=null; destroyMethodName=null, order = 1800, Root bean: class [org.springframework.security.web.authentication.AnonymousAuthenticationFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 2100, Root bean: class [org.springframework.security.web.session.SessionManagementFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 2200, Root bean: class [org.springframework.security.web.access.ExceptionTranslationFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 2300, <org.springframework.security.web.access.intercept.FilterSecurityInterceptor#0>, order = 2400]
Nov 25, 2016 11:50:44 AM org.springframework.web.servlet.handler.SimpleUrlHandlerMapping registerHandler
INFO: Mapped URL path [/resources/**] onto handler 'org.springframework.web.servlet.resource.ResourceHttpRequestHandler#0'
Nov 25, 2016 11:50:45 AM org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping register
INFO: Mapped "{[/hello],methods=[GET]}" onto public java.lang.String controller.BasicController.hello()
Nov 25, 2016 11:50:45 AM org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter initControllerAdviceCache
INFO: Looking for @ControllerAdvice: Root WebApplicationContext: startup date [Fri Nov 25 11:50:42 GMT 2016]; root of context hierarchy
Nov 25, 2016 11:50:45 AM org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter initControllerAdviceCache
INFO: Looking for @ControllerAdvice: Root WebApplicationContext: startup date [Fri Nov 25 11:50:42 GMT 2016]; root of context hierarchy
Nov 25, 2016 11:50:46 AM org.springframework.security.web.DefaultSecurityFilterChain <init>
INFO: Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.SecurityContextPersistenceFilter@4a5905d9, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@1a3e5f23, org.springframework.security.web.header.HeaderWriterFilter@6293e39e, org.springframework.security.web.csrf.CsrfFilter@365553de, org.springframework.security.web.authentication.logout.LogoutFilter@34a0ef00, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@5c0f79f0, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@21fdfefc, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@3daa82be, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@ec1b2e4, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@29a69a35, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@67e28be3, org.springframework.security.web.session.SessionManagementFilter@e344ad3, org.springframework.security.web.access.ExceptionTranslationFilter@de18f63, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@108bdbd8]
Nov 25, 2016 11:50:47 AM org.springframework.web.context.ContextLoader initWebApplicationContext
INFO: Root WebApplicationContext: initialization completed in 4797 ms
Nov 25, 2016 11:50:47 AM org.springframework.web.servlet.DispatcherServlet initServletBean
INFO: FrameworkServlet 'web': initialization started
Nov 25, 2016 11:50:47 AM org.springframework.web.context.support.XmlWebApplicationContext prepareRefresh
INFO: Refreshing WebApplicationContext for namespace 'web-servlet': startup date [Fri Nov 25 11:50:47 GMT 2016]; parent: Root WebApplicationContext
Nov 25, 2016 11:50:47 AM org.springframework.web.servlet.DispatcherServlet initServletBean
INFO: FrameworkServlet 'web': initialization completed in 25 ms

I preferably want to use XML configuration rather than java. However, if I try to use an annotation @Secured or @PreAuthorize I will get an exception AuthenticationCredentialsNotFoundException when I try to access the page:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:976)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:856)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:841)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:837)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:583)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:119)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
    at org.eclipse.jetty.server.Server.handle(Server.java:524)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
    at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
    at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
    at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
    at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
    at java.lang.Thread.run(Thread.java:745)
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:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)
    at controller.BasicController$$EnhancerBySpringCGLIB$$bf19eb0f.hello(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:220)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:964)

For the context part, i noticed that you forgot to specify the path to the actual file (spring config file): <init-param> <param-name>contextConfigLocation</param-name> <param-value></param-value> </init-param>

You simply have to replace that part to the new one :

<init-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/spring/context.xml</param-value>
</init-param>

I originally used IntelliJ with Jetty plugin which does not work.

I was able to successfully run the Spring security on Tomcat server .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM