当前位置: 首页 > 面试题库 >

Spring OAuth2每个对令牌端点的请求都会生成访问令牌

暴向笛
2023-03-14
问题内容

是否可以使用client_credentials或每个请求的密码授予类型来生成多个有效的访问令牌?

使用以上授权类型生成令牌仅在每个请求当前令牌过期时才提供一个新令牌。

我可以使用密码授予类型来生成刷新令牌,然后生成多个访问令牌,但是这样做会使以前的所有访问令牌无效。

知道如何更改以允许对/ oauth / token端点的每个请求生成访问令牌,并确保以前的所有令牌都不会无效吗?

以下是我的oauth服务器的XML配置。

<!-- oauth2 config start-->
  <sec:http pattern="/test/oauth/token" create-session="never"
              authentication-manager-ref="authenticationManager" > 
        <sec:intercept-url pattern="/test/oauth/token" access="IS_AUTHENTICATED_FULLY" />
        <sec:anonymous enabled="false" />
        <sec:http-basic entry-point-ref="clientAuthenticationEntryPoint"/>
        <sec:custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" /> 
        <sec:access-denied-handler ref="oauthAccessDeniedHandler" /> 
    </sec:http>


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

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

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

    <bean id="clientDetails" class="org.security.oauth2.ClientDetailsServiceImpl"></bean>

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

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

    <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="userAuthenticationManager"/>
    </oauth:authorization-server>

    <sec:authentication-manager id="userAuthenticationManager">
        <sec:authentication-provider  ref="customUserAuthenticationProvider">
        </sec:authentication-provider>
    </sec:authentication-manager>

    <bean id="customUserAuthenticationProvider"
          class="org.security.oauth2.CustomUserAuthenticationProvider">
    </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="300"></property>
        <property name="clientDetailsService" ref="clientDetails" />
    </bean>

    <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
        <constructor-arg ref="jdbcTemplate" />
    </bean>

    <bean id="jdbcTemplate"
           class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/oauthdb"/>
        <property name="username" value="root"/>
        <property name="password" value="password"/>
    </bean>
    <bean id="oauthAuthenticationEntryPoint"
          class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    </bean>

问题答案:

当我仔细检查时,发现InMemoryTokenStore使用OAuth2Authentication的哈希字符串作为serveral的键Map。当我使用相同的用户名,client_id,scope
..时,我得到了key。因此,这可能会导致一些问题。因此,我认为不赞成使用旧方法。以下是我为避免该问题所做的操作。

创建另一个AuthenticationKeyGenerator可以计算唯一密钥的密钥,称为UniqueAuthenticationKeyGenerator

/*
 * Copyright 2006-2011 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

/**
 * Basic key generator taking into account the client id, scope, resource ids and username (principal name) if they
 * exist.
 * 
 * @author Dave Syer
 * @author thanh
 */
public class UniqueAuthenticationKeyGenerator implements AuthenticationKeyGenerator {

    private static final String CLIENT_ID = "client_id";

    private static final String SCOPE = "scope";

    private static final String USERNAME = "username";

    private static final String UUID_KEY = "uuid";

    public String extractKey(OAuth2Authentication authentication) {
        Map<String, String> values = new LinkedHashMap<String, String>();
        OAuth2Request authorizationRequest = authentication.getOAuth2Request();
        if (!authentication.isClientOnly()) {
            values.put(USERNAME, authentication.getName());
        }
        values.put(CLIENT_ID, authorizationRequest.getClientId());
        if (authorizationRequest.getScope() != null) {
            values.put(SCOPE, OAuth2Utils.formatParameterList(authorizationRequest.getScope()));
        }
        Map<String, Serializable> extentions = authorizationRequest.getExtensions();
        String uuid = null;
        if (extentions == null) {
            extentions = new HashMap<String, Serializable>(1);
            uuid = UUID.randomUUID().toString();
            extentions.put(UUID_KEY, uuid);
        } else {
            uuid = (String) extentions.get(UUID_KEY);
            if (uuid == null) {
                uuid = UUID.randomUUID().toString();
                extentions.put(UUID_KEY, uuid);
            }
        }
        values.put(UUID_KEY, uuid);

        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("MD5");
        }
        catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("MD5 algorithm not available.  Fatal (should be in the JDK).");
        }

        try {
            byte[] bytes = digest.digest(values.toString().getBytes("UTF-8"));
            return String.format("%032x", new BigInteger(1, bytes));
        }
        catch (UnsupportedEncodingException e) {
            throw new IllegalStateException("UTF-8 encoding not available.  Fatal (should be in the JDK).");
        }
    }
}

最后,将它们连接起来

<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
    <constructor-arg ref="jdbcTemplate" />
    <property name="authenticationKeyGenerator">
        <bean class="your.package.UniqueAuthenticationKeyGenerator" />
    </property>
</bean>

下面的方式可能会导致一些问题,请参阅更新的答案!!!

您正在使用DefaultTokenServices。
尝试使用此代码,并确保重新定义您的 tokenServices包com.thanh.backend.oauth2.core;。导入java.util.Date;
导入java.util.UUID; 导入org.springframework.security.core.AuthenticationException;
导入org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken;
导入org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
导入org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken;
导入org.springframework.security.oauth2.common.OAuth2AccessToken;
导入org.springframework.security.oauth2.common.OAuth2RefreshToken;
导入org.springframework.security.oauth2.provider.OAuth2Authentication;
导入org.springframework.security.oauth2.provider.token.DefaultTokenServices;
导入org.springframework。security.oauth2.provider.token.TokenEnhancer;
导入org.springframework.security.oauth2.provider.token.TokenStore; / ** * @author thanh * /公共类SimpleTokenService扩展了DefaultTokenServices {private
TokenStore tokenStore; 私有TokenEnhancer accessTokenEnhancer;
@Override公共OAuth2AccessToken
createAccessToken(OAuth2Authentication身份验证)引发AuthenticationException
{OAuth2RefreshToken refreshToken = createRefreshToken(authentication);;
OAuth2AccessToken accessToken =
createAccessToken(authentication,refreshToken);
tokenStore.storeAccessToken(accessToken,身份验证);
tokenStore.storeRefreshToken(refreshToken,身份验证); 返回accessToken;
}私有OAuth2AccessToken
createAccessToken(OAuth2Authentication身份验证,OAuth2RefreshToken
refreshToken){DefaultOAuth2AccessToken令牌=新的DefaultOAuth2AccessToken(UUID.randomUUID()。toString());
intvaliditySeconds =
getAccessTokenValiditySeconds(authentication.getOAuth2Request());
如果(validitySeconds> 0){token.setExpiration(new
Date(System.currentTimeMillis()+(validitySeconds * 1000L))); }
token.setRefreshToken(refreshToken);
token.setScope(authentication.getOAuth2Request()。getScope());
返回accessTokenEnhancer!= null吗?accessTokenEnhancer.enhance(令牌,身份验证):令牌;
}私有ExpiringOAuth2RefreshToken
createRefreshToken(OAuth2Authentication身份验证){如果(!isSupportRefreshToken(authentication.getOAuth2Request())){返回null;}
intvaliditySeconds =
getRefreshTokenValiditySeconds(authentication.getOAuth2Request());
ExpiringOAuth2RefreshToken refreshToken = new
DefaultExpiringOAuth2RefreshToken(UUID.randomUUID()。toString(),new
Date(System.currentTimeMillis()+(validitySeconds * 1000L)));; 返回refreshToken;
} @Override public void setTokenEnhancer(TokenEnhancer
accessTokenEnhancer){super.setTokenEnhancer(accessTokenEnhancer);
this.accessTokenEnhancer = accessTokenEnhancer; } @Override public void
setTokenStore(TokenStore tokenStore){super.setTokenStore(tokenStore);
this.tokenStore = tokenStore; }}



 类似资料:
  • 问题内容: 是否可以使用每个请求的client_credentials或密码授予类型来生成多个有效的访问令牌? 使用以上授权类型生成令牌仅在每个请求当前令牌过期时才提供一个新令牌。 我可以使用密码授予类型来生成刷新令牌,然后生成多个访问令牌,但是这样做会使以前的所有访问令牌无效。 知道如何更改以允许对/ oauth / token端点的每个请求生成访问令牌,并确保以前的所有令牌都不会无效吗? 以下

  • 客户端通过使用按附录B“application/x-www-form-urlencoded”格式在HTTP请求实体正文中发送下列UTF-8字符编码的参数向令牌端点发起请求: grant_type 必需的。值必须设置为“client_credentials”。 scope 可选的。如3.3节所述的访问请求的范围。 客户端必须如3.2.1所述与授权服务器进行身份验证。 例如,客户端使用传输层安全发起如

  • 客户端通过使用按附录B“application/x-www-form-urlencoded”格式在HTTP请求实体正文中发送下列UTF-8字符编码的参数向令牌端点发起请求: grant_type 必需的。值必须设置为“password”。 username 必需的。资源所有者的用户名。 password 必需的。资源所有者的密码。 scope 可选的。如3.3节所述的访问请求的范围。 如果客户端类

  • 客户端通过使用按附录B“application/x-www-form-urlencoded”格式在HTTP请求实体正文中发送下列UTF-8字符编码的参数向令牌端点发起请求: grant_type 必需的。值必须被设置为“authorization_code”。 code 从授权服务器收到的授权码。 redirect_uri 必需的,若“redirect_uri”参数如4.1.1节所述包含在授权请求

  • 我一直在尝试使用简单的REST客户端以及Mozilla的REST插件。我收到“HTTP/1.1 401未授权”响应,正文中带有“{”error:“unauthorized_client”、“error_description”:“客户端未授权”}。 我已经成功获取了auth码,下面是访问令牌的POST请求,(范围r_fullprofile) https://www.linkedin.com/uas

  • https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=your_app_client_id&response_type=code&redirect_uri=https%3a%2f%2flogin.microsoftonline.com%2fcommon%2foauth2%2fnativeclient&res