Spring Security 和 OAuth2 生成具有自定义授权类型的令牌

Posted

技术标签:

【中文标题】Spring Security 和 OAuth2 生成具有自定义授权类型的令牌【英文标题】:Spring Security and OAuth2 generate token with custom grant type 【发布时间】:2015-05-16 01:14:59 【问题描述】:

我正在使用 Spring+Oauth2 来保护 Web 服务,并且我添加了自定义授权类型 (custom-grant):

<bean id="myTokenGranter" class="com.example.oauth2.MyTokenGranter" />

<oauth:authorization-server client-details-service-ref="client-details-service" token-services-ref="tokenServices">
    <oauth:refresh-token/>
    <oauth:password/>
    <oauth:custom-grant token-granter-ref="myTokenGranter" />
</oauth:authorization-server>

Spring 调用实现就好了。但是我不知道我应该如何在这里实际生成一个令牌。我看到他们使用了一个名为“RandomValueStringGenerator”的类,但我不确定是否没有更好的方法,而且我不知道如何生成一个“好”的令牌,它应该有多长,或者 spring 是否检查令牌的唯一性实际上等等。有没有办法可以在这里调用 Spring 自己的生成器部分?

现在这是我的 tokengranter 类:

public class MyTokenGranter implements TokenGranter 

private RandomValueStringGenerator generator = new RandomValueStringGenerator();

@Override
public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) 
    //...logic added here later
    return new DefaultOAuth2AccessToken(generator.generate());

我找不到一个很好的例子,并且在 spring ouath2 源代码中只有一个实现了一半的测试 tokengranter。

【问题讨论】:

还有 org.springframework.security.oauth2.provider.token.AbstractTokenGranter 我可以扩展,但我不知道如何在我的 xml 配置中传递构造函数参数? 【参考方案1】:

好的,所以这实际上可以用org.springframework.security.oauth2.provider.token.AbstractTokenGranter 来完成,要么复制它,要么尝试传递正确的构造函数。我只是将它发布给任何有同样问题的人。你也可以扩展 AbstractTokenGranter 但我没有通过正确的构造函数

这是我的实现:

public class MyTokenGranter implements TokenGranter 

    @Autowired
    private AuthorizationServerTokenServices tokenService;

    @Autowired
    private ClientDetailsService clientDetailsService;
    
    @Autowired
    private DefaultOAuth2RequestFactory defaultOauth2RequestFactory;
    
    private String grantType;
    
    @Override
    public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) 
        if (!this.grantType.equals(grantType)) 
            return null;
        
        String clientId = tokenRequest.getClientId();
        ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
        validateGrantType(grantType, client);
        return getAccessToken(client, tokenRequest);
    
    
    protected OAuth2AccessToken getAccessToken(ClientDetails client, TokenRequest tokenRequest) 
        return tokenService.createAccessToken(getOAuth2Authentication(client, tokenRequest));
    
    
    protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) 
        OAuth2Request storedOAuth2Request = defaultOauth2RequestFactory.createOAuth2Request(client, tokenRequest);
        return new OAuth2Authentication(storedOAuth2Request, null);
    
    
    protected void validateGrantType(String grantType, ClientDetails clientDetails) 
        Collection<String> authorizedGrantTypes = clientDetails.getAuthorizedGrantTypes();
        if (authorizedGrantTypes != null && !authorizedGrantTypes.isEmpty()
                && !authorizedGrantTypes.contains(grantType)) 
            throw new InvalidClientException("Unauthorized grant type: " + grantType);
        
    

    public String getGrantType() 
        return grantType;
    

    public void setGrantType(String grantType) 
        this.grantType = grantType;
    

Xml 配置:

<bean id="myTokenGranter" class="com.example.MyTokenGranter">
  <property name="grantType" value="custom-grant" />
</bean>
<oauth:authorization-server client-details-service-ref="clientDetailsService" token-services-ref="tokenServices">
    <oauth:refresh-token/>
    <oauth:password/>
    <oauth:custom-grant token-granter-ref="myTokenGranter" />
</oauth:authorization-server>

【讨论】:

我知道这是超级旧的,所以这是一个很长的镜头。但是你有没有机会知道如何创建我自己的 Granter 来覆盖 Spring 提供的一个?我想创建自己的客户凭证授予者。我想不通。 对不起,我早就离开了这个项目或一般的 Spring 想通了。值得一试。从春天开始,你对它做了什么?只是好奇 嗯,我现在是一家公司的 CTO,所以我同时处理很多事情,但我们也使用 spring(启动)。那时我继续做 android/ios 开发几年。 Spring 没有问题,我们现在只是使用基于注解的配置。 恭喜升级。我将基于注释的 Java Config 用于我的 Spring Boot 内容。我已经深入 Java 20 多年了,只是想知道人们如何转向技术方面【参考方案2】:

更多仅供参考,但如果您扩展 AbstractTokenGranter,则可以使用构造函数参数。例如:

public class MyTokenGranter extends AbstractTokenGranter

    private static final String GRANT_TYPE = "custom-grant";

    protected MyTokenGranter(
            AuthorizationServerTokenServices tokenServices,
            ClientDetailsService clientDetailsService )
    
        super( tokenServices, clientDetailsService, GRANT_TYPE );
    

    @Override
    protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest clientToken) 
    
        throw new RuntimeException( "Not implemented" );
    

<bean id="myTokenGranter" class="com.example.MyTokenGranter">
    <constructor-arg ref="tokenServices"/>
    <constructor-arg ref="clientDetailsService"/>
</bean>

【讨论】:

以上是关于Spring Security 和 OAuth2 生成具有自定义授权类型的令牌的主要内容,如果未能解决你的问题,请参考以下文章

使用 spring-session 和 spring-cloud-security 时,OAuth2ClientContext (spring-security-oauth2) 不会保留在 Redis

针对授权标头的Spring Security OAuth2 CORS问题

微服务和 Spring Security OAuth2

Spring Security 解析 —— Spring Security Oauth2 源码解析

带有 Jersey 和 Spring Security OAuth2 的 Spring Boot

Spring Cloud Security[微服务安全](一)初识Spring Cloud Security和OAuth2.0