Spring OAuth oauth/token returns 404 war tomcat

Spring OAuth oauth/token returns 404 war on tomcat

我已经按照这里的例子做了 https://www.youtube.com/watch?v=LnJsspvxE1c 在我的 spring war 应用程序上设置 OAuth。 由于我使用的是 spring 4.0.6.RELEASE 和 spring-security-oauth2 2.0.7.RELEASE 我不得不对其进行调整。

HTTP 上/oauth/token returns 404 (因为我的 war 名字是 kma.war 那么请求是 /kma/oauth/token)

根据日志,安全过滤器似乎工作正常。 但是我没有看到对 TokenEndpoint bean 的调用,我什至进行了远程调试并在其上放置了一个断点,但什么也没有。请注意下面日志中的最后一行。

.08:27:06.798 [http-nio-8080-exec-12] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/oauth/token' 
.08:27:06.798 [http-nio-8080-exec-12] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/oauth/token' 
.08:27:06.799 [http-nio-8080-exec-12] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /oauth/token?grant_type=password&client-id=kma-client&username=admin@kampyle.com&password=123; Attributes: [IS_AUTHENTICATED_ANONYMOUSLY] 
.08:27:06.799 [http-nio-8080-exec-12] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /oauth/token?grant_type=password&client-id=kma-client&username=admin@kampyle.com&password=123; Attributes: [IS_AUTHENTICATED_ANONYMOUSLY] 
.08:27:06.800 [http-nio-8080-exec-12] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@90550640: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@7798: RemoteIpAddress: 10.0.2.2; SessionId: null; Granted Authorities: ROLE_ANONYMOUS 
.08:27:06.800 [http-nio-8080-exec-12] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@90550640: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@7798: RemoteIpAddress: 10.0.2.2; SessionId: null; Granted Authorities: ROLE_ANONYMOUS 
.08:27:06.803 [http-nio-8080-exec-12] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.RoleVoter@270d09d0, returned: 0 
.08:27:06.803 [http-nio-8080-exec-12] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.RoleVoter@270d09d0, returned: 0 
.08:27:06.806 [http-nio-8080-exec-12] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.AuthenticatedVoter@48ff4ab7, returned: 1 
.08:27:06.806 [http-nio-8080-exec-12] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.AuthenticatedVoter@48ff4ab7, returned: 1 
.08:27:06.808 [http-nio-8080-exec-12] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful 
.08:27:06.808 [http-nio-8080-exec-12] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful 
.08:27:06.809 [http-nio-8080-exec-12] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object 
.08:27:06.809 [http-nio-8080-exec-12] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object 
.08:27:06.810 [http-nio-8080-exec-12] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client-id=kma-client&username=admin@kampyle.com&password=123 reached end of additional filter chain; proceeding with original chain 
.08:27:06.810 [http-nio-8080-exec-12] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client-id=kma-client&username=admin@kampyle.com&password=123 reached end of additional filter chain; proceeding with original chain 
.08:27:06.811 [http-nio-8080-exec-12] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally 
.08:27:06.811 [http-nio-8080-exec-12] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally 
.08:27:06.812 [http-nio-8080-exec-12] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed 
.08:27:06.812 [http-nio-8080-exec-12] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed 

我确实在日志的开头看到 url 与 TokenEndpoint Bean 的匹配。

.08:24:05.230 [localhost-startStop-2] INFO  o.s.s.o.p.e.FrameworkEndpointHandlerMapping - Mapped "{[/oauth/confirm_access],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint.getAccessConfirmation(java.util.Map<java.lang.String, java.lang.Object>,javax.servlet.http.HttpServletRequest) throws java.lang.Exception 
.08:24:05.230 [localhost-startStop-2] INFO  o.s.s.o.p.e.FrameworkEndpointHandlerMapping - Mapped "{[/oauth/confirm_access],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint.getAccessConfirmation(java.util.Map<java.lang.String, java.lang.Object>,javax.servlet.http.HttpServletRequest) throws java.lang.Exception 
.08:24:05.277 [localhost-startStop-2] INFO  o.s.s.o.p.e.FrameworkEndpointHandlerMapping - Mapped "{[/oauth/authorize],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.authorize(java.util.Map<java.lang.String, java.lang.Object>,java.util.Map<java.lang.String, java.lang.String>,org.springframework.web.bind.support.SessionStatus,java.security.Principal) 
.08:24:05.277 [localhost-startStop-2] INFO  o.s.s.o.p.e.FrameworkEndpointHandlerMapping - Mapped "{[/oauth/authorize],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.authorize(java.util.Map<java.lang.String, java.lang.Object>,java.util.Map<java.lang.String, java.lang.String>,org.springframework.web.bind.support.SessionStatus,java.security.Principal) 
.08:24:05.283 [localhost-startStop-2] INFO  o.s.s.o.p.e.FrameworkEndpointHandlerMapping - Mapped "{[/oauth/authorize],methods=[POST],params=[user_oauth_approval],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.View org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.approveOrDeny(java.util.Map<java.lang.String, java.lang.String>,java.util.Map<java.lang.String, ?>,org.springframework.web.bind.support.SessionStatus,java.security.Principal) 
.08:24:05.283 [localhost-startStop-2] INFO  o.s.s.o.p.e.FrameworkEndpointHandlerMapping - Mapped "{[/oauth/authorize],methods=[POST],params=[user_oauth_approval],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.View org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.approveOrDeny(java.util.Map<java.lang.String, java.lang.String>,java.util.Map<java.lang.String, ?>,org.springframework.web.bind.support.SessionStatus,java.security.Principal) 
.08:24:05.284 [localhost-startStop-2] INFO  o.s.s.o.p.e.FrameworkEndpointHandlerMapping - Mapped "{[/oauth/token],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException 
.08:24:05.284 [localhost-startStop-2] INFO  o.s.s.o.p.e.FrameworkEndpointHandlerMapping - Mapped "{[/oauth/token],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException 
.08:24:05.292 [localhost-startStop-2] INFO  o.s.s.o.p.e.FrameworkEndpointHandlerMapping - Mapped "{[/oauth/token],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.getAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException 
.08:24:05.292 [localhost-startStop-2] INFO  o.s.s.o.p.e.FrameworkEndpointHandlerMapping - Mapped "{[/oauth/token],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.getAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException**** 

这是我的 web.xml

<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>KMA Web Application</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:/spring/kmaAppContext.xml
            classpath:/spring/security/kmaSecurityContext.xml
        </param-value>
    </context-param>

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

    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

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

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


    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:/spring/kmaAppContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

</web-app>

这是我的 kmaAppContext.xml

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

    <mvc:annotation-driven/>
    <context:component-scan base-package="com.kma" />
</beans>

最后但同样重要的是,这是我的安全上下文

<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:security="http://www.springframework.org/schema/security"
       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/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">

    <bean id="userDetailsService" class="com.kma.security.UserDetailsService">
    </bean>

    <security:authentication-manager id="authenticationManager">
        <security:authentication-provider user-service-ref="userDetailsService">
            <!--<security:user-service id="userService">-->
                <!--<security:user name="test" password="pass" authorities="customer" />-->
            <!--</security:user-service>-->
        </security:authentication-provider>
    </security:authentication-manager>

    <security:http pattern="/oauth/token" create-session="stateless"
        authentication-manager-ref="clientAuthenticationManager">
        <security:intercept-url pattern="/oauth/token"
        access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <security:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
        <security:custom-filter ref="clientCredentialsTokenEndpointFilter"
        before="BASIC_AUTH_FILTER" />
        <security:access-denied-handler ref="oauthAccessDeniedHandler" />

    </security:http>

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

    <bean id="clientAuthenticationEntryPoint"
          class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
        <property name="realmName" value="kampyle/client"/>
        <property name="typeName" value="Basic"/>
    </bean>

    <bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
        <property name="authenticationManager" ref="authenticationManager"/>
    </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">
        <oauth:authorization-code />
        <oauth:implicit />
        <oauth:refresh-token />
        <oauth:client-credentials />
        <oauth:password authentication-manager-ref="authenticationManager" />
    </oauth:authorization-server>

    <!-- Client Definition -->
    <oauth:client-details-service id="clientDetails">

        <oauth:client client-id="kma-client"
                      authorized-grant-types="password,authorization_code,refresh_token,implicit,redirect"
                      authorities="ROLE_USER"
                      redirect-uri="/web"
                      scope="read,write,trust"
                      access-token-validity="30"
                      refresh-token-validity="600"/>

    </oauth:client-details-service>

    <!-- Token Store  -->
    <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore"/>
    <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"/>
        <!-- VIV -->
        <property name="accessTokenValiditySeconds" value="10"/>
    </bean>

    <authentication-manager id="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
        <authentication-provider user-service-ref="clientDetailsUserService"/>
    </authentication-manager>
    <bean id="clientDetailsUserService"
          class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
        <constructor-arg ref="clientDetails"/>
    </bean>

    <!--<security:http create-session="stateless" use-expressions="true">-->

        <!--<security:intercept-url pattern="/api/admin/**"-->
                                <!--access="hasRole('ROLE_ADMIN')" />-->
        <!--<security:http-basic />-->
        <!--<security:intercept-url pattern="/api/**"-->
                                <!--access="isAuthenticated()" />-->
        <!--<security:http-basic />-->
    <!--</security:http>-->

</beans>

您已经加载了两次 XML 文件,并且您点击的安全性 Filter 在其上下文中没有 Servlet,因此它无法处理该请求。我建议不要使用 web.xml 并切换到 Spring Boot 以使一切正常。如果您不想这样做,请查看旧版本的 sparklr2 示例(例如 1.0.5)并从那里窃取 web.xml。这是:

<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>

<servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
        classpath:/spring/security/kmaSecurityContext.xml
        classpath:/spring/kmaAppContext.xml
        </param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

在 Dave 的大量帮助下,我修复了我的 web.xml 和我的安全上下文 xml。我设法到达 oauth/token 端点可用的地步,并且验证了客户端 ID。用户验证仍然失败。

日志显示客户端认证成功

.12:38:10.404 [http-nio-8080-exec-48] DEBUG o.s.s.o.p.c.ClientCredentialsTokenEndpointFilter - Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@d7afe829: Principal: org.springframework.security.core.userdetails.User@93b2ea19: Username: kma-client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_USER 

日志显示用户验证失败:

.12:38:10.439 [http-nio-8080-exec-48] DEBUG o.s.s.w.a.w.BasicAuthenticationFilter - Basic Authentication Authorization header found for user 'admin@kma.com' 
.12:38:10.459 [http-nio-8080-exec-48] DEBUG o.s.s.authentication.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider 
.12:38:10.459 [http-nio-8080-exec-48] DEBUG o.s.s.authentication.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider 
.12:38:10.460 [http-nio-8080-exec-48] DEBUG o.s.s.a.d.DaoAuthenticationProvider - User 'admin@kma.com' not found 
.12:38

这是我更新的 web.xml

<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>KMA Web Application</display-name>

    <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.kmaApp</param-value>
        </init-param>
    </filter>

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

    <servlet>
        <servlet-name>kmaApp</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                classpath:/spring/servlet-context.xml
                classpath:/spring/kmaAppContext.xml
                classpath:/spring/security/kmaSecurityContext.xml
            </param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>kmaApp</servlet-name>
        <url-pattern>/api/</url-pattern>
    </servlet-mapping>

</web-app>

这是我更新的 kmaSecurityContext.xml

<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:security="http://www.springframework.org/schema/security"
       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/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">

    <bean id="userDetailsService" class="com.kma.security.UserDetailsService">
    </bean>

    <security:authentication-manager id="authenticationManager">
        <security:authentication-provider user-service-ref="userDetailsService">
            <!--<security:user-service id="userService">-->
                <!--<security:user name="test" password="pass" authorities="customer" />-->
            <!--</security:user-service>-->
        </security:authentication-provider>
    </security:authentication-manager>

    <security:http pattern="/oauth/token" create-session="stateless"
        authentication-manager-ref="clientAuthenticationManager">
        <security:intercept-url pattern="/oauth/token"
        access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <security:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
        <security:custom-filter ref="clientCredentialsTokenEndpointFilter"
        before="BASIC_AUTH_FILTER" />
        <security:access-denied-handler ref="oauthAccessDeniedHandler" />

    </security:http>

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

    <bean id="clientAuthenticationEntryPoint"
          class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
        <property name="realmName" value=“kma/client"/>
        <property name="typeName" value="Basic"/>
    </bean>

    <bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
        <property name="authenticationManager" ref="clientAuthenticationManager"/>
    </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">
        <oauth:authorization-code />
        <oauth:implicit />
        <oauth:refresh-token />
        <oauth:client-credentials />
        <oauth:password authentication-manager-ref="authenticationManager" />
    </oauth:authorization-server>

    <!-- Client Definition -->
    <oauth:client-details-service id="clientDetails">

        <oauth:client client-id="kma-client"
                      authorized-grant-types="password,authorization_code,refresh_token,implicit,redirect"
                      authorities="ROLE_USER"
                      redirect-uri="/web"
                      scope="read,write,trust"
                      access-token-validity="30"
                      refresh-token-validity="600"/>

    </oauth:client-details-service>

    <!-- Token Store  -->
    <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore"/>
    <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"/>
        <!-- VIV -->
        <property name="accessTokenValiditySeconds" value="10"/>
    </bean>

    <authentication-manager id="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
        <authentication-provider user-service-ref="clientDetailsUserService" />
    </authentication-manager>

    <bean id="clientDetailsUserService"
          class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
        <constructor-arg ref="clientDetails"/>
    </bean>

    <!--<security:http create-session="stateless" use-expressions="true">-->

        <!--<security:intercept-url pattern="/api/admin/**"-->
                                <!--access="hasRole('ROLE_ADMIN')" />-->
        <!--<security:http-basic />-->
        <!--<security:intercept-url pattern="/api/**"-->
                                <!--access="isAuthenticated()" />-->
        <!--<security:http-basic />-->
    <!--</security:http>-->

</beans>

这应该不难。我一定是遗漏了一些基本的东西。我仍然得到 404

我的web.xml

<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>KMA Web Application</display-name>

    <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.kmaApp</param-value>
        </init-param>
    </filter>

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

    <servlet>
        <servlet-name>kmaApp</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!--<param-value>-->
                <!--classpath:/spring/servlet-context.xml-->
                <!--classpath:/spring/kmaAppContext.xml-->
                <!--classpath:/spring/security/kmaSecurityContext.xml-->
            <!--</param-value>-->
            <param-value>
                classpath:/spring/kmaAppContext.xml
                classpath:/spring/servlet-context.xml
                classpath:/spring/security/kmaSecurityContext.xml
            </param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>kmaApp</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

</web-app>

我的 kmaSecurityContext

<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:security="http://www.springframework.org/schema/security"
       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/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">

    <bean id="userDetailsService" class="com.kma.kmawebservice.services.security.MAUserDetailsService">
    </bean>

    <bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
        <constructor-arg name="strength" value="11"/>
    </bean>


    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider user-service-ref="userDetailsService">
            <security:password-encoder ref="encoder"/>
            <!--<security:user-service id="userService">-->
                <!--<security:user name="test" password="pass" authorities="customer" />-->
            <!--</security:user-service>-->
        </security:authentication-provider>
    </security:authentication-manager>

    <security:http pattern="/oauth/token" create-session="stateless"
        authentication-manager-ref="clientAuthenticationManager">
        <security:intercept-url pattern="/oauth/token"
        access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <security:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
        <security:custom-filter ref="clientCredentialsTokenEndpointFilter"
        before="BASIC_AUTH_FILTER" />
        <security:access-denied-handler ref="oauthAccessDeniedHandler" />

    </security:http>

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

    <bean id="clientAuthenticationEntryPoint"
          class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
        <property name="realmName" value="kma/client"/>
        <property name="typeName" value="Basic"/>
    </bean>

    <bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
        <property name="authenticationManager" ref="clientAuthenticationManager"/>
    </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">
        <oauth:authorization-code />
        <oauth:implicit />
        <oauth:refresh-token />
        <oauth:client-credentials />
        <oauth:password authentication-manager-ref="authenticationManager" />
    </oauth:authorization-server>

    <!-- Client Definition -->
    <oauth:client-details-service id="clientDetails">

        <oauth:client client-id="kma-client"
                      authorized-grant-types="password,authorization_code,refresh_token,implicit,redirect"
                      authorities="ROLE_USER"
                      redirect-uri="/web"
                      scope="read,write,trust"
                      access-token-validity="30"
                      refresh-token-validity="600"/>

    </oauth:client-details-service>

    <!-- Token Store  -->
    <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore"/>
    <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"/>
        <!-- VIV -->
        <property name="accessTokenValiditySeconds" value="10"/>
    </bean>

    <authentication-manager id="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
        <authentication-provider user-service-ref="clientDetailsUserService" />
    </authentication-manager>

    <bean id="clientDetailsUserService"
          class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
        <constructor-arg ref="clientDetails"/>
    </bean>

    <!--<security:http create-session="stateless" use-expressions="true">-->

        <!--<security:intercept-url pattern="/api/admin/**"-->
                                <!--access="hasRole('ROLE_ADMIN')" />-->
        <!--<security:http-basic />-->
        <!--<security:intercept-url pattern="/api/**"-->
                                <!--access="isAuthenticated()" />-->
        <!--<security:http-basic />-->
    <!--</security:http>-->

</beans>

我的servlet-context.xml

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

    <mvc:annotation-driven/>
    <context:component-scan base-package="com.kma.kmawebservice.controllers, com.kma.feedback.controllers, com.kma.kmabackend.controllers"/>

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

</beans>

访问时

http://localhost:8080/kma/oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123

我收到 HTTP 状态 404 - /kma/oauth/token 我的 war 名字是 kma.war

日志显示

.20:44:42.375 [http-nio-8080-exec-146] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/oauth/token' 
.20:44:42.375 [http-nio-8080-exec-146] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/oauth/token' 
.20:44:42.376 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 1 of 8 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' 
.20:44:42.376 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 1 of 8 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' 
.20:44:42.377 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 2 of 8 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' 
.20:44:42.377 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 2 of 8 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' 
.20:44:42.378 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 3 of 8 in additional filter chain; firing Filter: 'ClientCredentialsTokenEndpointFilter' 
.20:44:42.378 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 3 of 8 in additional filter chain; firing Filter: 'ClientCredentialsTokenEndpointFilter' 
.20:44:42.380 [http-nio-8080-exec-146] DEBUG o.s.s.o.p.c.ClientCredentialsTokenEndpointFilter - Request is to process authentication 
.20:44:42.380 [http-nio-8080-exec-146] DEBUG o.s.s.o.p.c.ClientCredentialsTokenEndpointFilter - Request is to process authentication 
.20:44:42.380 [http-nio-8080-exec-146] DEBUG o.s.s.authentication.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider 
.20:44:42.380 [http-nio-8080-exec-146] DEBUG o.s.s.authentication.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider 
.20:44:42.381 [http-nio-8080-exec-146] DEBUG o.s.s.o.p.c.ClientCredentialsTokenEndpointFilter - Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@d7afe829: Principal: org.springframework.security.core.userdetails.User@93b2ea19: Username: kma-client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_USER 
.20:44:42.381 [http-nio-8080-exec-146] DEBUG o.s.s.o.p.c.ClientCredentialsTokenEndpointFilter - Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@d7afe829: Principal: org.springframework.security.core.userdetails.User@93b2ea19: Username: kma-client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_USER 
.20:44:42.382 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 4 of 8 in additional filter chain; firing Filter: 'BasicAuthenticationFilter' 
.20:44:42.382 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 4 of 8 in additional filter chain; firing Filter: 'BasicAuthenticationFilter' 
.20:44:42.384 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 5 of 8 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' 
.20:44:42.384 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 5 of 8 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' 
.20:44:42.385 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 6 of 8 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' 
.20:44:42.385 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 6 of 8 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' 
.20:44:42.386 [http-nio-8080-exec-146] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@d7afe829: Principal: org.springframework.security.core.userdetails.User@93b2ea19: Username: kma-client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_USER' 
.20:44:42.386 [http-nio-8080-exec-146] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@d7afe829: Principal: org.springframework.security.core.userdetails.User@93b2ea19: Username: kma-client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_USER' 
.20:44:42.388 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 7 of 8 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' 
.20:44:42.388 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 7 of 8 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' 
.20:44:42.388 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 8 of 8 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' 
.20:44:42.388 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 at position 8 of 8 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' 
.20:44:42.389 [http-nio-8080-exec-146] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/oauth/token' 
.20:44:42.389 [http-nio-8080-exec-146] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/oauth/token' 
.20:44:42.389 [http-nio-8080-exec-146] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123; Attributes: [IS_AUTHENTICATED_ANONYMOUSLY] 
.20:44:42.389 [http-nio-8080-exec-146] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123; Attributes: [IS_AUTHENTICATED_ANONYMOUSLY] 
.20:44:42.390 [http-nio-8080-exec-146] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@d7afe829: Principal: org.springframework.security.core.userdetails.User@93b2ea19: Username: kma-client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_USER 
.20:44:42.390 [http-nio-8080-exec-146] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@d7afe829: Principal: org.springframework.security.core.userdetails.User@93b2ea19: Username: kma-client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_USER 
.20:44:42.391 [http-nio-8080-exec-146] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.RoleVoter@2b65b068, returned: 0 
.20:44:42.391 [http-nio-8080-exec-146] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.RoleVoter@2b65b068, returned: 0 
.20:44:42.391 [http-nio-8080-exec-146] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.AuthenticatedVoter@2120921a, returned: 1 
.20:44:42.391 [http-nio-8080-exec-146] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.AuthenticatedVoter@2120921a, returned: 1 
.20:44:42.391 [http-nio-8080-exec-146] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful 
.20:44:42.391 [http-nio-8080-exec-146] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful 
.20:44:42.391 [http-nio-8080-exec-146] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object 
.20:44:42.391 [http-nio-8080-exec-146] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object 
.20:44:42.391 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 reached end of additional filter chain; proceeding with original chain 
.20:44:42.391 [http-nio-8080-exec-146] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password&client_id=kma-client&username=admin@kma.com&password=123 reached end of additional filter chain; proceeding with original chain 
.20:44:42.392 [http-nio-8080-exec-146] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally 
.20:44:42.392 [http-nio-8080-exec-146] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally 
.20:44:42.392 [http-nio-8080-exec-146] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed 
.20:44:42.392 [http-nio-8080-exec-146] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed