access-token - 请求 oauth2 访问 token 时获取无效范围

标签 access-token spring-security-oauth2 oauth-2.0

我的服务器中有一个oauth服务,它执行身份验证操作,并在有效用户收到请求时发出访问 token 。然后,当我尝试使用命令行curl请求请求此服务时,出现以下错误。

"detailMessage":"Invalid scope: read,write,trust","cause":{"additionalInformation":{"scope":"read trust write"}

以下是我的请求,导致错误。

curl -X POST http://localhost:8080/MyProjectOauth/oauth/token -H “Accept: application/json” -d "grant_type=password&client_id=client1&client_secret=client1&username=user1&password=user1&scope=read,write,trust"

如果我在没有范围的情况下尝试此请求,则会出现以下错误。

"detailMessage":"Bad credentials","cause":{"detailMessage":"Bad credentials"

下面是我的 Spring Security 配置文件。

spring-security.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-2.0.xsd
      http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
      http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd ">

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

      <!-- The OAuth2 protected resources are separated out into their own block so we can deal with authorization and error handling
         separately. This isn't mandatory, but it makes it easier to control the behaviour. -->
      <http pattern="/protected/**" 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="/protected/**" 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="test"/>
      </bean>

      <bean id="clientAuthenticationEntryPoint"
            class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
          <property name="realmName" value="test/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>

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

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

      <authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security">
          <authentication-provider user-service-ref="userService">
              <password-encoder ref="passwordEncoder"/>
          </authentication-provider>
      </authentication-manager>

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

      <!-- Used for the persistenceof tokens (currently an in memory implementation) -->
      <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore">
  <!--         <constructor-arg ref="dataSource"/>    -->
      </bean>

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

      <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="tokenStore" ref="tokenStore"/>
          <property name="requestFactory" ref="oAuth2RequestFactory"/>
      </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"/>

      <bean id="clientDetails"
            class="com.example.myproject.ser.ClientService">
      </bean>

      <sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
          <!--you could also wire in the expression handler up at the layer of the http filters. See https://jira.springsource.org/browse/SEC-1452 -->
          <sec:expression-handler ref="oauthExpressionHandler"/>
      </sec:global-method-security>

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

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

  </beans>

ClientService.java:

      import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.security.oauth2.provider.ClientDetails;
  import org.springframework.security.oauth2.provider.ClientDetailsService;
  import org.springframework.security.oauth2.provider.ClientRegistrationException;
  import org.springframework.security.oauth2.provider.client.BaseClientDetails;
  import org.springframework.stereotype.Component;

  import com.example.myproject.rep.OauthRepository;

  @Component
  public class ClientService implements ClientDetailsService {

      @Autowired
      private OauthRepository oauthRepository;

      @Override
      public ClientDetails loadClientByClientId(String s) throws ClientRegistrationException {
          BaseClientDetails clientDetails = oauthRepository.getByClientId(s);
          return clientDetails;
      }
  }

OauthRepository.java:

      @Repository
  @Transactional
  public class OauthRepository {

    @Autowired
    private SessionFactory sessionFactory;

    private org.hibernate.Session getCurrentSession(){
      return sessionFactory.getCurrentSession();
    }



      public BaseClientDetails getByClientId(String clientId) {
        Query query=getCurrentSession().createQuery("FROM OauthClientDetails WHERE clientId=:clientId");
        query.setParameter("clientId", clientId);
        List<OauthClientDetails> getClient=query.list();

        OauthClientDetails oauthClient=getClient.get(0);
        BaseClientDetails details = new BaseClientDetails(oauthClient.getClientId(),oauthClient.getResourceIds(),oauthClient.getScope(),oauthClient.getAuthorizedGrantTypes(),oauthClient.getAuthorities());
        details.setClientSecret(oauthClient.getClientSecret());

          return details;



      }
       } 

下面是我的数据库客户端表数据。

         CREATE TABLE oauth_client_details (
      client_id varchar(50) NOT NULL,
      resource_ids varchar(256) DEFAULT NULL,
      client_secret varchar(256) DEFAULT NULL,
      scope varchar(256) DEFAULT NULL,
      authorized_grant_types varchar(256) DEFAULT NULL,
      web_server_redirect_uri varchar(256) DEFAULT NULL,
      authorities varchar(256) DEFAULT NULL,
      access_token_validity int(11) DEFAULT NULL,
      refresh_token_validity int(11) DEFAULT NULL,
      additional_information varchar(4096) DEFAULT NULL,
      autoapprove varchar(4096) DEFAULT NULL,
      PRIMARY KEY (client_id)
    );


INSERT INTO oauth_client_details(client_id, resource_ids, client_secret, scope, authorized_grant_types, authorities, access_token_validity, refresh_token_validity)
VALUES ('client1', 'rest_api', 'client1', 'read,write,trust', 'password,authorization_code,refresh_token,implicit', 'ROLE_ANDROID', '5', '1000');

请帮我解决问题

最佳答案

范围参数应以空格分隔。

这应该有效 -curl -X POST localhost:8080/MyProjectOauth/oauth/token -H “Accept: application/json” -d "grant_type=password&client_id=client1&client_secret=client1‌​&username=user1&pass‌​word=user1&scope=rea‌​ d 写信任”

Jim R 在上面的评论中回答了这个问题。我只是将其移至答案,这样会更容易找到。

关于access-token - 请求 oauth2 访问 token 时获取无效范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38216570/

相关文章:

node.js - 尝试在 Electron 桌面应用程序中使用 oauth 流(使用 Spotify API)?

node.js - 如何在数据库中存储OAuth 2访问 token ?

android - 如何使用 play services 8.3 使用新的 google 登录获取访问 token ?

java - Oauth2 客户端凭证流程 + Spring Boot2 抛出 There is no PasswordEncodermapped > for the id "null"错误

android - 具有 spring boot 后端的 android native 应用程序的 oauth 授权类型

使用 cy.request() 使用 Cypress 登录 Azure B2C

ios - OAuth 2.0 access_token 可更新

c# - 从自定义 header 中检索访问 token

带有 OAuth2FeignRequestInterceptor 的 Spring @FeignClient 不起作用

java - 是否可以缓存已验证的 JWT token 以防止在 spring-boot 应用程序中重复验证过程