0

我正在使用 Spring-security-oauth 来保护 RESTful 应用程序,并且我正在尝试实现自定义 OAuthProviderTokenServices 类以便将令牌存储在数据库中。我从文档中得到的只是:

创建 OAuthProviderTokenServices 实现时,您可能需要考虑扩展 RandomValueProviderTokenServices,它通过随机值创建令牌并处理除令牌持久性之外的所有内容。还有一个 OAuthProviderTokenServices 的内存实现可能适合 [...]

这很好,所以我创建了一个新的自定义类:

package experiments;

import java.util.concurrent.ConcurrentHashMap;
import org.springframework.security.oauth.provider.token.OAuthProviderTokenImpl;
import org.springframework.security.oauth.provider.token.RandomValueProviderTokenServices;

/**
 * Implementation of TokenServices that stores tokens in a database.
 *
 * @author Seether
 */
public class DatabaseProviderTokenServices extends RandomValueProviderTokenServices {

  protected final ConcurrentHashMap<String, OAuthProviderTokenImpl> tokenStore = new ConcurrentHashMap<String, OAuthProviderTokenImpl>();

  protected OAuthProviderTokenImpl readToken(String token) {
    return tokenStore.get(token);
  }

  protected void storeToken(String tokenValue, OAuthProviderTokenImpl token) {
    tokenStore.put(tokenValue, token);
  }

  protected OAuthProviderTokenImpl removeToken(String tokenValue) {
    return tokenStore.remove(tokenValue);
  }

}

如您所见,它现在与 InMemoryProviderTokenServices 类相同。

我的应用程序使用 sparkl 示例中的 AccessConfirmationController,即:

package experiments;

import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.oauth.provider.ConsumerDetails;
import org.springframework.security.oauth.provider.ConsumerDetailsService;
import org.springframework.security.oauth.provider.token.OAuthProviderToken;
import org.springframework.security.oauth.provider.token.OAuthProviderTokenServices;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

/**
 * Controller for retrieving the model for and displaying the confirmation page for access to a protected resource.
 * 
 * @author Ryan Heaton
 */
@Controller
public class AccessConfirmationController {

    private OAuthProviderTokenServices tokenServices;
    private ConsumerDetailsService consumerDetailsService;

    @RequestMapping("/oauth/confirm_access")
    public ModelAndView getAccessConfirmation(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        String token = request.getParameter("oauth_token");
        if (token == null) {
            throw new IllegalArgumentException("A request token to authorize must be provided.");
        }

        OAuthProviderToken providerToken = tokenServices.getToken(token);
        ConsumerDetails consumer = consumerDetailsService
                .loadConsumerByConsumerKey(providerToken.getConsumerKey());

        String callback = request.getParameter("oauth_callback");
        TreeMap<String, Object> model = new TreeMap<String, Object>();
        model.put("oauth_token", token);
        if (callback != null) {
            model.put("oauth_callback", callback);
        }
        model.put("consumer", consumer);
        return new ModelAndView("access_confirmation", model);
    }

    public void setTokenServices(OAuthProviderTokenServices tokenServices) {
        this.tokenServices = tokenServices;
    }

    public void setConsumerDetailsService(ConsumerDetailsService consumerDetailsService) {
        this.consumerDetailsService = consumerDetailsService;
    }
}

现在的问题是:我如何告诉我的应用程序使用我的 tokenServices 实现而不是默认的实现(我现在相信是 InMemoryProviderTokenServices)?

我试着弄乱控制器,但几次尝试都把我带到了 java.lang.IllegalStateExceptions。

我还注意到配置 XML 中有一行:

<oauth:token-services id="tokenServices"/>

这可能是难题的关键部分,相关帮助如下:

用于声明和配置提供者令牌服务的内存实现的元素。

如果我只是删除它,我会得到:

org.springframework.beans.factory.BeanCreationException:创建 ServletContext 资源 [/WEB-INF/mvc-dispatcher-servlet.xml] 中定义的名称为“accessConfirmationController”的 bean 时出错:设置 bean 属性时无法解析对 bean 'tokenServices' 的引用令牌服务'; 嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'tokenServices' is defined

4

1 回答 1

1

有趣的是,有时答案不知从何而来,尤其是在您开始寻找答案并且刚刚在此处发布之后已经有一段时间了。那好吧。

根据在此处随机找到的代码片段,看来我需要做的就是从 XML 配置文件中注释掉该行:

<!--   <oauth:token-services id="tokenServices"/> -->

并用这个替换它:

<beans:bean id="tokenServices" class="experiments.DatabaseProviderTokenServices" />

课程当然是我的实现。通过这样做,可以使用 DatabaseProviderTokenServices 类代替默认的 InMemoryProviderTokenServices 类。

于 2013-08-27T16:03:09.793 回答