簡體   English   中英

Oauth2和Spring-Security:java.lang.IllegalStateException:找不到WebApplicationContext:沒有注冊ContextLoaderListener?

[英]Oauth2 and Spring-Security: java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?

我使用Oauth2和spring-security來保證我的休息服務。 我正在使用最新版本的oauth2和spring-security依賴項。 以下是我的依賴:

<!-- Spring Security Dependencies -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
</dependency>
<!-- END of Core Spring and Spring Web Dependencies -->

我正在使用maven multimodule項目。 所以在父pom中聲明依賴項的版本。 以下是depdendencies的版本:

<spring-security-oauth2>2.0.1.RELEASE</spring-security-oauth2>
<spring.security.version>3.2.4.RELEASE</spring.security.version>

我的Spring-security-aouth2.xml配置文件如下:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:sec="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd ">

<!-- Create client details bean for manage client details from database -->
<!-- The JdbcClientDetailsService provide default implementation for fetching 
    the data from oauth_client_details table Other wise we need to create our 
    custom class that Implement ClientDetailsService Interface and override its 
    loadClientByClientId method -->
<bean id="clientDetails"
    class="org.springframework.security.oauth2.provider.client.JdbcClientDetailsService">
    <constructor-arg index="0">
        <ref bean="dataSource" />
    </constructor-arg>
</bean>

<!-- Configure Authentication manager -->
<bean id="passwordEncoder"
    class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
    <constructor-arg name="strength" value="11" />
</bean>

<!-- This class is the custom implementation of UserDetailSerive Interface 
    that provide by the spring, which we Need to implement and override its method. 
    But for Oauth spring provide us ClientDetailsUserDetailsService, which already 
    implement UserDetailSerive Interface and override its method. -->
<bean id="clientDetailsUserService"
    class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
    <constructor-arg ref="clientDetails" />
    <property name="passwordEncoder" ref="passwordEncoder"></property>
</bean>

<!-- <bean id="oauthDaoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"> 
    <property name="passwordEncoder" ref="passwordEncoder" /> <property name="userDetailsService" 
    ref="clientDetailsUserService" /> </bean> -->

<sec:authentication-manager id="authenticationManager">
    <sec:authentication-provider
        user-service-ref="clientDetailsUserService" />
</sec:authentication-manager>

<!-- Oauth Token Service Using Database -->
<!-- The JdbcTokenStore class provide the default implementation from access 
    the token from database. If we want to customize the JDBC implementation 
    we need to implement TokenStore interface and overrider its methods -->
<bean id="tokenStore"
    class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
    <constructor-arg ref="dataSource" />
</bean>

<!-- This the service class which is used to access the function of JdbcTokenStore 
    class. This is like MVC structure JdbcTokenStore is Dao layer and DefaultTokenServices 
    is service layer -->
<bean id="tokenServices"
    class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
    <property name="tokenStore" ref="tokenStore" />
    <property name="supportRefreshToken" value="true" />
    <property name="clientDetailsService" ref="clientDetails" />
</bean>

<!-- A user approval handler that remembers approval decisions by consulting 
    existing tokens -->
<bean id="oAuth2RequestFactory"
    class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
    <constructor-arg ref="clientDetails" />
</bean>
<bean id="userApprovalHandler"
    class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
    <property name="requestFactory" ref="oAuth2RequestFactory" />
    <property name="tokenStore" ref="tokenStore" />
</bean>

<!-- Authorization Server Configuration of the server is used to provide 
    implementations of the client details service and token services and to enable 
    or disable certain aspects of the mechanism globally. -->
<oauth:authorization-server
    client-details-service-ref="clientDetails" token-services-ref="tokenServices"
    user-approval-handler-ref="userApprovalHandler">
    <oauth:authorization-code />
    <oauth:implicit />
    <oauth:refresh-token />
    <oauth:client-credentials />
    <oauth:password authentication-manager-ref="authenticationManager" />
</oauth:authorization-server>

<!-- A Resource Server serves resources that are protected by the OAuth2 
    token. Spring OAuth provides a Spring Security authentication filter that 
    implements this protection. -->
<oauth:resource-server id="resourceServerFilter"
    token-services-ref="tokenServices" resource-id="rsourceId" />

<!-- Grants access if only grant (or abstain) votes were received. We can 
    protect REST resource methods with JSR-250 annotations such as @RolesAllowed -->
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
    <property name="decisionVoters">
        <list>
            <bean class="org.springframework.security.access.annotation.Jsr250Voter" />
        </list>
    </property>
</bean>

<!-- If authentication fails and the caller has asked for a specific content 
    type response, this entry point can send one, along with a standard 401 status -->
<bean id="clientAuthenticationEntryPoint"
    class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <property name="realmName" value="empirecl-api/client" />
    <property name="typeName" value="Basic" />
</bean>

<bean id="oauthAuthenticationEntryPoint"
    class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <property name="realmName" value="empirecl-api" />
</bean>

<bean id="oauthAccessDeniedHandler"
    class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />

<!-- Allows clients to authenticate using request parameters if included 
    as a security filter. It is recommended by the specification that you permit 
    HTTP basic authentication for clients, and not use this filter at all. -->
<bean id="clientCredentialsTokenEndpointFilter"
    class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
    <property name="authenticationManager" ref="authenticationManager" />
</bean>

<sec:http pattern="/oauth/token" create-session="stateless"
    authentication-manager-ref="authenticationManager">
    <sec:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
    <sec:intercept-url pattern="/api/logout" access="ROLE_USER,ROLE_ADMIN" method="GET" />
    <sec:logout invalidate-session="true" logout-url="/api/logout" />

    <sec:anonymous enabled="false" />
    <sec:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
    <sec:custom-filter ref="clientCredentialsTokenEndpointFilter"
        before="BASIC_AUTH_FILTER" />
    <sec:access-denied-handler ref="oauthAccessDeniedHandler" />
</sec:http>
</beans>

以下是我的web.xml文件:

<?xml version="1.0" encoding="UTF-8"?>

http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd“version =”3.0“>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
                classpath:security-config/spring-security-oauth2.xml
                classpath*:**/applicationContext*.xml
    </param-value>
</context-param>

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


<servlet>
    <servlet-name>empirecl</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>empirecl</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>    
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>contextAttribute</param-name>
        <param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

當我啟動服務器時,應用程序成功加載並且沒有異常拋出。 但是當我嘗試使用Postman chrome rest客戶端訪問URL時,將拋出以下異常:

SEVERE: Servlet.service() for servlet [empirecl] in context with path [/empirecl-api] threw exception
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:252)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:78)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:526)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1033)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:652)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1566)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1523)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)

在使用我的應用程序配置Oauth2之前,其余服務工作成功並且沒有拋出異常,但是在配置之后,當我嘗試訪問url以訪問Oauth令牌時,它將拋出異常。 關注我的網址:

http://localhost:8080/empirecl-api/oauth/token

在此先感謝,我是Oauth和Spring-Security的新人。 究竟是什么問題?

我找到了解決方案,需要從DelegatingFilterProxy刪除<init-param> 之后該應用程序將運行。 我認為security-filter會覆蓋容器找不到的contextAttributeorg.springframework.web.servlet.FrameworkServlet.CONTEXT.spring值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM