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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12464042/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:23:03  来源:igfitidea点击:

Spring OAuth (OAuth2): How can I get the client credentials in a Spring MVC controller?

springspring-mvcspring-securityoauth-2.0oauth-provider

提问by wandi.darko

In this snippet:

在这个片段中:

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

principal.getName()gives me the user identification but I need a way to receive the client credentials (client => the app who is using my API). How can I do this?

principal.getName()给了我用户标识,但我需要一种方法来接收客户端凭据(客户端 => 使用我的 API 的应用程序)。我怎样才能做到这一点?

采纳答案by wandi.darko

I found a reasonable solution based on @luke-taylor answer.

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

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

回答by Shaun the Sheep

The client identity is available from the Authenticationobject which you can either cast the principal to, or get directly from the thread-local security context. Something like

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

Authentication a = SecurityContextHolder.getContext().getAuthentication();

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

If you don't want to put that code directly into your controller, you can implement a separate context accessor as described in this answerand inject that into it instead.

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

回答by Michael Ressler

Fleshing out the HandlerMethodArgumentResolveroption a bit more. In order to support the following:

进一步充实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
}

We'll need the HandlerMethodArgumentResolverregistered with our Application Context (for me this was inside a WebMvcConfigurerAdapter). My HandlerMethodArgumentResolverlooks like this:

我们需要在HandlerMethodArgumentResolver我们的应用程序上下文中注册(对我来说这是在 a 中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;
    }

}

And the @interfacedefinition:

@interface定义:

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

}

回答by Imtiaz Shakil Siddique

A simple way to retrieve the clientIdis loading the currently authenticated principal. The principalcan be defined directly as a method argument and it will be correctly resolved by the framework.

检索 的一种简单方法clientId是加载当前经过身份验证的principal. 的principal可以直接定义为方法参数,它会被框架正确地解析。

Here is an example:

下面是一个例子:

  @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;
  }