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

Spring Security Oauth-发送令牌请求时需要的基本访问身份验证

松亦
2023-03-14

Spring Security OAuth2.0有一个问题。

spring-security的基本配置来自示例:

<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" />
    <custom-filter ref="clientCredentialsTokenEndpointFilter"
        after="BASIC_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

<http pattern="/path/**" 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="/path/*" access="ROLE_USER" />
    <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

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

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

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

<bean id="clientCredentialsTokenEndpointFilter"
    class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
    <property name="authenticationManager" ref="clientAuthenticationManager" />
</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="oauthAuthenticationProvider" class="my.package.OAuthAuthenticationProvider" xmlns="http://www.springframework.org/schema/beans" />

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

<authentication-manager alias="authenticationManager"
    xmlns="http://www.springframework.org/schema/security">
    <authentication-provider ref="oauthAuthenticationProvider" />
</authentication-manager>

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

<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="true" />
    <property name="clientDetailsService" ref="clientDetails" />
</bean>

<bean id="userApprovalHandler"
    class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
    <property name="tokenServices" ref="tokenServices" />
</bean>

<!-- authorization-server aka AuthorizationServerTokenServices is an interface 
    that defines everything necessary for token management -->
<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 />
</oauth:authorization-server>

<oauth:resource-server id="resourceServerFilter"
    resource-id="test" token-services-ref="tokenServices" />
<!-- ClientsDeailsService: Entry Point to clients database (given is in 
    memory implementation) -->
<oauth:client-details-service id="clientDetails">
    <!-- client -->
    <oauth:client client-id="the_client"
        authorized-grant-types="authorization_code,client_credentials"
        authorities="ROLE_USER" scope="read,write,trust" secret="secret" />

    <oauth:client client-id="my-trusted-client-with-secret"
        authorized-grant-types="password,authorization_code,refresh_token,implicit"
        secret="somesecret" authorities="ROLE_USER" />

</oauth:client-details-service>

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

当我的web.xml文件如下所示时,它就可以工作了:

...
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-security.xml</param-value>
</context-param>
...
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</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>Dispatcher Servlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
...
<servlet-mapping>
    <servlet-name>Dispatcher Servlet</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping> 
<servlet-mapping>
    <servlet-name>Dispatcher Servlet</servlet-name>
    <url-pattern>/somepath/*</url-pattern>
</servlet-mapping> 
<servlet-mapping>
    <servlet-name>Dispatcher Servlet</servlet-name>
    <url-pattern>/somepath/*</url-pattern>
    <url-pattern>/*</url-pattern>
</servlet-mapping> 
<http pattern="/somepath/oauth/token" create-session="stateless"
    authentication-manager-ref="clientAuthenticationManager"
    xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/somepath/oauth/token" access="IS_AUTHENTICATED_FULLY" />
    <anonymous enabled="false" />
    <http-basic entry-point-ref="clientAuthenticationEntryPoint" />
    <custom-filter ref="clientCredentialsTokenEndpointFilter"
        after="BASIC_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

>

  • 我正在访问地址(以前工作过):

    https://localhost.server:8443/system/somepath/oauth/token?grant_type=password&client_id=my-trusted-client-with-secret&client_secret=somesecret&username=user&password=pass

    Web浏览器要求登录和密码(基本访问身份验证)。

    我应该改变什么来避免这个基本的auth提示?

  • 共有1个答案

    杜起运
    2023-03-14

    servlet和过滤器映射的问题源于Spring OAuth需要一个DispatcherServlet作为其与OAuth相关的endpoint。我建议您将它们放在默认的servlet映射(/)中,但这取决于您。在任何情况下,您的一站式安全配置都是servlet配置文件,而不是根上下文(因此您需要用DispatcherServlet而不是ContextLoaderListener)加载它。这与示例中的相同(在web.xml中需要一个servlet init param),但是没有什么可以阻止您添加自己的附加servlet(当然,只要映射不冲突)。

    身份验证问题是不同的。OAuth2规范建议使用基本身份验证来保护/tokenendpoint,因此提示符原则上是一件好事,尽管我可以看到您试图避免它。像您正在做的那样将机密放在表单字段中确实不够安全,无法在生产系统中使用,但如果出于某种原因需要,您可以使用ClientCredentialStokenEndpointFilter(就像您所做的那样)。filter不起作用的原因可能是因为您发送的是GET(而不是POST),从安全角度来看,这比首先使用filter更糟糕,但我没有看到在filter中任何地方设置了打开POST only验证的标志(尽管我建议如果您在任何地方愤怒地使用此东西,您可以设置它)。

    您没有显示2个Spring XML文件,但是web.XML引用了2。我认为问题最终将可追溯到这样一个事实,即您将它们混在一起,或者在两者之间重复bean定义。也许您可以澄清这一点(或者按照上面的建议从DispatcherServlet切换到加载单个文件)?

     类似资料:
    • } 要获取令牌,我执行以下步骤: > 使用浏览器转到:http://localhost:9000/oauth/authorize?response_type=code&client_id=test&redirect_uri=http%3a%2f%2flocalhost%3a8080%2f&scope=write 首先,它将我重定向到一个登录表单,在那里我输入用户名和密码:admin abc 请帮我

    • 问题内容: 我想从我的API请求资源时发送身份验证令牌。 我确实使用$ resource实现了服务: 我有一个存储身份验证令牌的服务: 我想通过服务发送的每个请求都发送令牌。通过将其放入特定动作的调用中,我能够发送它。例如,这有效: 但是我宁愿将access_token定义为服务中的参数,因为它必须随每个调用一起发送。并提高干度。但是工厂中的所有内容仅执行一次,因此access_token在定义工

    • 问题内容: 我一直在使用HTTPClient版本4.1.2尝试通过需要基本身份验证的HTTP API访问REST。这是客户端代码: 当我构造一个请求时,像这样: 我在Charles Proxy中 看到有两个请求正在发送。一个不带标题,另一个 带 标题。如您所料,第一个失败的原因是401,但是第二个失败的情况却是201。 有谁知道为什么会这样吗?谢谢! 编辑: 我应该明确指出,我已经看过这个问题了,

    • 我正在尝试向正在运行的本地服务器发出GET请求。我无法返回正确的数据,我看到“未经授权”的响应。如果字符串“token”是正确的,那么任何人都能发现任何明显的问题吗。 }* 我能够从命令行获得一个curl请求:

    • 我在身份验证中使用基于令牌的方法,但在许多博客中,我读到他们将令牌存储在数据库中。 我们需要将令牌存储在DB中的基于令牌的身份验证中吗? https://scotch.io/tutorials/the-ins-and-outs-of-token-based-authentication 在这个博客中,提到我们正在签署令牌而不是存储在数据库中,我认为这应该是实现真正无状态的方法。

    • 我是一个新手开发人员,想学习如何使用人工智能。所以我创建了模型,它根据输入正确响应。因此,我想使用postman对API的调用进行测试,以验证一切正常,并且我的调用中有一个错误:“message”:“请求具有无效的身份验证凭据。应为OAuth 2访问令牌、登录cookie或其他有效的身份验证凭据。请参阅https://developers.google.com/identity/sign-in/w

    • 问题内容: 我必须 使用 HTTP Basic身份验证从http服务器下载和解析XML文件。现在,我这样做: 但是以这种方式,我无法从具有http身份验证的服务器获取xml(或者我只是根本不知道该文档)文档。 如果您能向我展示实现我的目标的最好,最简单的方法,我将不胜感激。 问题答案: 您可以使用。例如: 这将设置默认值,并将在 所有 请求中使用。显然,当您不需要所有请求的凭据或多个不同的凭据(可

    • 我尝试从PHP向Android手机应用发送推送通知 我使用谷歌云消息,但在浏览器中我看到错误: 请求缺少身份验证密钥(FCM令牌)。请参阅FCM文档的“认证”部分,网址为https://firebase.google.com/docs/cloud-messaging/server.错误401 此外,我可以从c#控制台应用程序发送消息推送并在我的手机上接收它(我认为,授权密钥是正确的): 问题:如何