Spring OAuth(OAuth2):如何在Spring MVC控制器中获取客户端凭据?

时间:2012-09-17 17:08:24

标签: spring spring-mvc spring-security oauth-2.0 oauth-provider

在此片段中:

@RequestMapping(method = GET)
public List<Place> read(Principal principal) {
  principal.getName(); 
}

principal.getName()为我提供了用户身份,但我需要一种方法来接收客户端凭据(client =&gt;使用我的API的应用)。我怎么能这样做?

5 个答案:

答案 0 :(得分:19)

客户端标识可从Authentication对象获得,您可以将该主体转换为或直接从线程本地安全上下文获取。像

这样的东西
Authentication a = SecurityContextHolder.getContext().getAuthentication();

String clientId = ((OAuth2Authentication) a).getAuthorizationRequest().getClientId();

如果您不想将该代码直接放入您的控制器,您可以按this answer中所述实现单独的上下文访问器,并将其注入其中。

答案 1 :(得分:14)

我找到了一个基于@ luke-taylor回答的合理解决方案。

@RequestMapping(method = GET)
public List<Place> read(OAuth2Authentication auth) {
  auth.getOAuth2Request().getClientId()
}

答案 2 :(得分:5)

充实HandlerMethodArgumentResolver选项。为了支持以下内容:

@RequestMapping(
    value = WEB_HOOKS, 
    method = RequestMethod.GET, 
    produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public List<SomeDTO> getThoseDTOs(@CurrentClientId String clientId) 
{
    // Do something with clientId - it will be null if there was no authentication
}

我们需要在我们的应用程序上下文中注册HandlerMethodArgumentResolver(对我而言,这是在WebMvcConfigurerAdapter内)。我的HandlerMethodArgumentResolver看起来像这样:

public class OAuth2ClientIdArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterAnnotation(CurrentClientId.class) != null
                && parameter.getParameterType().equals(String.class);
    }

    @Override
    public Object resolveArgument(
            MethodParameter parameter,
            ModelAndViewContainer mavContainer, 
            NativeWebRequest webRequest,
            WebDataBinderFactory binderFactory) 
        throws Exception 
    {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if(authentication == null) {
            return null;
        }
        String clientId = null;

        if (authentication.getClass().isAssignableFrom(OAuth2Authentication.class)) {
            clientId = ((OAuth2Authentication) authentication).getOAuth2Request().getClientId();
        }

        return clientId;
    }

}

@interface定义:

@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CurrentClientId {

}

答案 3 :(得分:0)

检索clientId的一种简单方法是加载当前已验证的principalprincipal可以直接定义为方法参数,框架会正确解析。

这里是一个例子:

  @RequestMapping(method = RequestMethod.GET)
  public Map<String, String> getUserInfo(Principal principal) {
    OAuth2Authentication oauth = (OAuth2Authentication) principal;

    Map<String, String> userInfo = new LinkedHashMap<>();
    userInfo.put("username", principal.getName());
    userInfo.put("clientId", oauth.getOAuth2Request().getClientId());
    return userInfo;
  }

答案 4 :(得分:0)

也可以通过声明org.springframework.security.oauth2.jwt.Jwt声明org.springframework.security.core.annotation.AuthenticationPrincipal对象。

@GetMapping
public String showClientId(@AuthenticationPrincipal Jwt principal) {
    return principal.getClaimAsString("clientId");
}