首页 文章

如何使刷新令牌有效期长并且每次在spring security oauth2中出现新的refresh_token grant_type时都会发出新的刷新令牌

提问于
浏览
0

我使用spring security oauth2对我的android应用程序客户端进行身份验证 . 当客户端请求带有grant_type作为密码时,服务器会发出访问令牌并刷新令牌 . 如果访问令牌过期,我可以通过发送请求来发出新的访问令牌grant_type as refresh_token.Now如果我的刷新令牌到期我该怎么办?我不想提示用户使用他的凭证再次进行身份验证 . 那么有没有办法发布新的刷新令牌和新的访问令牌?或者是否有任何规定来发出具有无限有效性的刷新令牌,或者通过仅使用一次性发送刷新令牌并刷新每个refresh_token grant_type请求中的刷新令牌 . 下面是我的spring security oauth2的配置文件 .

<?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:context="http://www.springframework.org/schema/context"
    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-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://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd ">


    <!-- This is default url to get a token from OAuth -->
    <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>
    <!-- This is where we tells spring security what URL should be protected 
      and what roles have access to them -->
    <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_APP" />
      <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>
    <authentication-manager alias="authenticationManager"
      xmlns="http://www.springframework.org/schema/security">
      <authentication-provider  user-service-ref="userService">
      </authentication-provider>
    </authentication-manager>

    <bean id="userService"
      class="com.example.myproject.ser.UserService">
    </bean>

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


    <!-- This defined token store, we have used inmemory tokenstore for now 
      but this can be changed to a user defined one -->
    <bean id="tokenStore"
      class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" />

    <!-- This is where we defined token based configurations, token validity 
      and other things -->
    <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="120" />  <!-- 2 hour 3600 -->
      <property name="refreshTokenValiditySeconds" value="420"></property>   <!-- 2 month 5270400 -->
      <property name="clientDetailsService" ref="clientDetails" />
    </bean>

    <bean id="userApprovalHandler"
      class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
      <property name="tokenServices" ref="tokenServices" />
    </bean>
    <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>

在我的Android应用程序中,我有从多个设备验证同一用户的规定 . 如果已经在其他设备中对其进行了身份验证,那么可以在任何设备中进行身份验证 . 因此解决方案不会影响这种情况 .

2 回答

  • 0

    您可以在客户端级别设置刷新令牌的有效期(请参阅org.springframework.security.oauth2.provider.ClientDetails和org.springframework.security.oauth2.provider.ClientDetailsService) . 您需要在客户端详细信息服务加载的客户端上设置此项 .

    public classs MyClientDetailsService implements ClientDetailsService {
        @Override
        public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
            BaseClientDetails client = new BaseClientDetails();
            client.setRefreshTokenValiditySeconds(Integer.MAX_VALUE);
            ...
            return client;
        }
    }
    

    或者,您可以在授权服务器配置中的org.springframework.security.oauth2.provider.token.DefaultTokenServices(假设这是您在服务器中使用的实现)上设置默认有效性 . 您可以通过将以下方法添加到授权服务器配置类来完成此操作 .

    @Bean
    public AuthorizationServerTokenServices authorizationServerTokenServices() throws Exception {
            DefaultTokenServices tokenServices = new DefaultTokenServices();
            tokenServices.setTokenStore(tokenStore);
            tokenServices.setSupportRefreshToken(true);
            tokenServices.setClientDetailsService(clientDetailsService);
            tokenServices.setRefreshTokenValiditySeconds(Integer.MAX_VALUE);
            return tokenServices;
    }
    

    一旦刷新令牌已经过期,我相信获得新令牌的唯一方法是让用户重新进行身份验证 .

  • 4

    根据 DefaultTokenServicesspring-security-oauth 的源代码传递一个小于或等于零的值,因为刷新令牌的有效性应足以使其永久持续 . 看看here .

    那么授权服务器配置中的代码应该是这样的:

    @Bean    
    fun tokenServices(): DefaultTokenServices {
        val defaultTokenServices = DefaultTokenServices()
        defaultTokenServices.setTokenStore(tokenStore())
        defaultTokenServices.setRefreshTokenValiditySeconds(0)
    
        return defaultTokenServices
    }
    

    或者,如果您有 JdbcClientDetailsService ,则可以在 oauth_client_details 表中设置刷新令牌到期日 .

相关问题