当前位置: 首页 > 知识库问答 >
问题:

Resteasy / Spring Security Oauth 2.0 - 错误 404

冯宏放
2023-03-14

我正在尝试使用Resteasy和Spring构建一个REST服务器/提供程序,并希望使用OAuth 2保护一些API。据我了解,我应该让 API 公开一个 URI 来生成 OAuth 令牌(例如 /oauth/token),然后使用它来访问安全部分。

下面是我使用 Spring Security 及其 OAuth2 支持的代码,我尝试在保护 /ws/v1/oauth/** 的同时公开单个 /oauth/token URI。当我尝试在不发送凭据的情况下访问任何这些 URI 时,我会收到安全“错误凭据请求”(如我所期望的那样),但是当我尝试在 /oauth/token URI 上实际输入相应的凭据(通过 POST 方法)时,我遇到了 HTTP 404 错误。

我的web.xml代码。

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

<!-- RestEasy Bootstrap -->
<listener>
    <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>

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

<listener>
    <listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class>
</listener>

<!-- RestEasy Servlet -->
<servlet>
    <servlet-name>Resteasy</servlet-name>
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>Resteasy</servlet-name>
    <url-pattern>/ws/*</url-pattern>
</servlet-mapping>

<!-- OAuth2 / Spring Security -->
<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>

还有我的安全背景。(我在堆栈溢出的一个例子中找到并进行了一些调整)

<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices">
    <oauth:client-credentials />
</oauth:authorization-server>

<sec:authentication-manager alias="clientAuthenticationManager">
    <sec:authentication-provider user-service-ref="clientDetailsUserService" />
</sec:authentication-manager>

<http pattern="/oauth/token" create-session="stateless"
        authentication-manager-ref="clientAuthenticationManager"
        xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
    <anonymous enabled="false" />
    <http-basic entry-point-ref="clientAuthenticationEntryPoint" />

    <!-- include this only if you need to authenticate clients via request parameters -->
    <custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

<oauth:resource-server id="resourceServerFilter"
        resource-id="rest_server" token-services-ref="tokenServices" />

<oauth:client-details-service id="clientDetails">
    <oauth:client client-id="the_client" authorized-grant-types="client_credentials" 
            authorities="ROLE_READ" secret="1234567890" />
    <oauth:client client-id="password_client" authorized-grant-types="password" 
            authorities="ROLE_READ" secret="1234567890" />
</oauth:client-details-service>


<http pattern="/**" create-session="never"
        entry-point-ref="oauthAuthenticationEntryPoint"
        access-decision-manager-ref="accessDecisionManager"
        xmlns="http://www.springframework.org/schema/security">
    <anonymous enabled="false" />

    <intercept-url pattern="/ws/v1/oauth/**" access="ROLE_READ" method="GET" />
    <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" />

<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
    <property name="tokenStore" ref="tokenStore" />
    <property name="supportRefreshToken" value="false" />
    <property name="clientDetailsService" ref="clientDetails" />
    <property name="accessTokenValiditySeconds" value="400000" />
    <property name="refreshTokenValiditySeconds" value="0" />
</bean>

<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"
        xmlns="http://www.springframework.org/schema/beans">
    <constructor-arg>
        <list>
            <bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
            <bean class="org.springframework.security.access.vote.RoleVoter" />
            <bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
        </list>
    </constructor-arg>
</bean>


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

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

<bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
    <property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>


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

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


<sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
    <sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>

<oauth:expression-handler id="oauthExpressionHandler" />

<oauth:web-expression-handler id="oauthWebExpressionHandler" />

我看到了一些类似的问题,Spring Security 无法将 http 路径注册到上下文中,因为它没有被传递,但我不知道如何在我的 Web 中做到这一点.xml因为我使用 SpringContextLoaderListener 而不是 ContextLoaderListener(这似乎存在于我发现的所有示例/问题中)。

关于如何消除这个404错误的任何提示?

编辑——为了澄清,我用POST和GET测试了/oauth/token URL

获取示例:

http://127.0.0.1:9999/oauth/token?client_id=the_client&client_secret=1234567890&grant_type=client_credentials

在这两种情况下,我都得到了错误的凭据/错误404

共有1个答案

陶征
2023-03-14

TokenEndpoint 是一个 Spring MVC @Controller,所以你需要一个 DispatcherServlet 来处理请求。这可能意味着你需要完全放弃ContextLoaderListener(但我不知道SpringContextLoaderListener正在做什么)并将你的配置移动到servlet(这里的例子)。幸运的是,默认的 servlet 映射 “/” 似乎是开放的,所以如果你安装了 servlet 并加载了你的配置文件,一切应该都可以工作。

 类似资料:
  • 我只是试图得到一个RESTEasy的例子工作,它看起来我有一些麻烦设置我需要的环境。 这是我正在使用的简单示例:http://examples.javacodeGeeks.com/enterprise-/rest/resteasy/resteasy-hello-world-example/ 我不想在Tomcat-Server上运行这个示例,而是想在Eclipse(?)附带的本地J2EE预览服务器上

  • 当我在本地运行应用程序时,我使用GETlocalhost:8080/resources/sqlData/projects访问Rest资源没有问题,但是出于某种原因,当我在AWS服务器上尝试时,我使用my-app.elasticbeanstalk.com/resources/sqlData/projects. Amazon Web服务是否需要某种版本的Resteasy或其他东西?这是我的日志: 17

  • JBoss RESTEasy 是一个用来使用Java语言开发 RESTFul Web服务的框架。 RESTEasy 项目是 JAX-RS 的一个实现,集成的一些亮点: 不需要配置文件,只要把JARs文件放到类路径里面,添加 @Path 注解就可以了。 完全的把 RESTEeasy 配置作为Seam 组件来看待。 HTTP 请求由Seam来提供,不需要一个额外的Servlet。 Resources

  • 我认为这个客户机库很方便,并希望继续使用它,但我如何驯服它或重写它,以便返回真正的错误消息?

  • 我正在使用quarkus中的框架为mandrill API构建一个rest客户端 这是application.properties的相关部分 我的示例资源 我看到的是,如果我正在调用的API(在这种情况下是Madrill)返回错误响应(例如,如果我的密钥是错误的),那么我用来存储响应的变量不会得到响应。相反,我向我的应用程序公开的REST API围绕着它,填充了来自Madrill的响应。 这是预期

  • 我有一个项目,它使用RESTEasy REST对象 jar包含一个名为resteasy-client.js的文件,该文件被添加到web页面中,使创建HTTP调用变得更加容易。有虫子!一旦文件发送到客户机,服务器将在方法:WriteJavaScript中:jsapiWriter.java中添加一行