【问题标题】:Spring OAuth (OAuth2): How can I get the client credentials in a Spring MVC controller?Spring OAuth (OAuth2):如何在 Spring MVC 控制器中获取客户端凭据?
【发布时间】:2012-09-09 22:50:22
【问题描述】:

在这个sn-p中:

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

principal.getName() 给了我用户标识,但我需要一种方法来接收客户端凭据(客户端 => 正在使用我的 API 的应用程序)。我该怎么做?

【问题讨论】:

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


    【解决方案1】:

    客户端身份可从Authentication 对象获得,您可以将主体强制转换为该对象,也可以直接从线程本地安全上下文中获取。类似的东西

    Authentication a = SecurityContextHolder.getContext().getAuthentication();
    
    String clientId = ((OAuth2Authentication) a).getAuthorizationRequest().getClientId();
    

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

    【讨论】:

    • 不错的答案,除了发布日期有点旧。 spring boot 1.3.3 使用 getOAuth2Request() 而不是 getAuthorizationRequest()
    • 客户端密码怎么样?
    【解决方案2】:

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

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

    【讨论】:

    • 这返回给我的是主要用户,而不是客户端 ID 应用程序
    • 更新版本:auth.getOAuth2Request().getClientId()
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      检索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;
        }
      

      【讨论】:

        【解决方案5】:

        也可以使用org.springframework.security.core.annotation.AuthenticationPrincipal 注释来声明org.springframework.security.oauth2.jwt.Jwt 对象。

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

        【讨论】:

          【解决方案6】:

          使用deprecation of spring-oauth,其他一些答案不再有效。我使用以下内容在 AuthenticationSuccessHandler 中使用 spring-security 5 获取 clientId

          @Autowired
          public OAuth2AuthorizedClientRepository oAuth2AuthorizedClientRepository
          
          protected String getClientId(final Authentication authentication, HttpServletRequest request) {
              OAuth2AuthenticationToken auth = (OAuth2AuthenticationToken) authentication;
              OAuth2AuthorizedClient client = oAuth2AuthorizedClientRepository.loadAuthorizedClient(auth.getAuthorizedClientRegistrationId(), auth, request);
              String clientId = client.getClientRegistration().getClientId();
              return clientId;
          }
          

          【讨论】:

            猜你喜欢
            • 2016-09-28
            • 2023-04-09
            • 2020-02-23
            • 2018-09-15
            • 1970-01-01
            • 2014-05-04
            • 1970-01-01
            • 2019-05-03
            • 1970-01-01
            相关资源
            最近更新 更多