java - OAuth 1.0 中的 Spring-security-oauth OAuthProviderTokenServices 自定义实现

标签 java spring spring-mvc oauth

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

When creating your OAuthProviderTokenServices implementation, you may want to consider extending the RandomValueProviderTokenServices which creates tokens via random value and handles everything except for the persistence of the tokens. There is also an in-memory implementation of the OAuthProviderTokenServices that may be suitable [...]

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

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)?

我尝试摆弄 Controller ,但几次尝试都导致了 java.lang.IllegalStateExceptions。

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

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

这可能是这个难题的关键部分,正如相关帮助中所述:

Element for declaring and configuring an in-memory implementation of the provider token service.

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

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'accessConfirmationController' defined in ServletContext resource [/WEB-INF/mvc-dispatcher-servlet.xml]: Cannot resolve reference to bean 'tokenServices' while setting bean property 'tokenServices'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'tokenServices' is defined

最佳答案

有趣的是,有时答案会突然出现,特别是在您开始寻找答案并刚刚发布到此处之后已经有一段时间了。哦,好吧。

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

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

并将其替换为以下内容:

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

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

关于java - OAuth 1.0 中的 Spring-security-oauth OAuthProviderTokenServices 自定义实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18459793/

相关文章:

java - 如何在 Java 中实例化泛型方法参数的实例?

java - 什么算修改?

java - 在Java中查找URI对应的协议(protocol)

java - 使用 hibernate 进行条件 AND

spring - 如何在 Spring Data REST 中禁止 PUT 而允许 POST 和 PATCH?

java - 如何在对 Spring MVC Controller 的 GET 请求中接受日期参数?

java - 如何使用Java获取div的坐标和尺寸

java - SpringJUnit4ClassRunner - 静态访问EntityManager(Factory)

spring - 如何为 Spring MVC 添加简单的分页

java - Spring Controller 中嵌套方法的@PreAuthorize