首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在DGS查询中启用@AuthenticationPrincipal参数

如何在DGS查询中启用@AuthenticationPrincipal参数
EN

Stack Overflow用户
提问于 2022-07-20 16:23:59
回答 1查看 306关注 0票数 1

我正在开发一个Spring服务,它有一个REST控制器和一个Netflix DGS GraphQL组件。REST方法受到Security的保护,每当需要当前用户名时,我就使用@AuthenticationPrincipal注释添加一个方法参数,它允许我访问经过身份验证的用户信息:

代码语言:javascript
复制
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails; 

@RestController
public class ActionController {

    @GetMapping("/getActions")
    public List<ActionResponse> getActions(@AuthenticationPrincipal UserDetails userDetails) {
        return actionService.getActions(userDetails.getUsername());
    }

}

现在,我希望对通过GraphQL实现的Netflix DGS方法具有相同的功能。但是,当我尝试使用@AuthenticationPrincipal参数(如第一个例子)时,它总是等于null。我找到的解决办法是从SecurityContextHolder手动分配SecurityContextHolder:

代码语言:javascript
复制
import com.netflix.graphql.dgs.DgsComponent;
import com.netflix.graphql.dgs.DgsQuery;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails; 

@DgsComponent
public class ActionDatafetcher {

    @DgsQuery
    public List<Map<String, Object>> actions(@AuthenticationPrincipal UserDetails userDetails) {
        // The following line works well:
        // userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        
        String username = userDetails.getUsername();   // ===>  NullPointerException here
        return actionService.getActionsMap(username);
    }

}

如何让@Authentication主体在DgsComponent中工作?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-09-27 20:02:59

即使Security的AuthenticationPrincipalArgumentResolver在应用程序上下文中,默认情况下它也不会被DGS选中。您可以通过实现DGS自己的ArgumentResolver并将其工作委托给Spring的AuthenticationPrincipalArgumentResolver来实现这一点。

所以你所需要做的就是:

Kotlin

代码语言:javascript
复制
@Component
class DgsAuthenticationPrincipalArgumentResolver : ArgumentResolver {
    private val delegate = AuthenticationPrincipalArgumentResolver()

    override fun supportsParameter(parameter: MethodParameter): Boolean {
        return delegate.supportsParameter(parameter)
    }

    override fun resolveArgument(parameter: MethodParameter, dfe: DataFetchingEnvironment): Any? {
        val request = (DgsDataFetchingEnvironment(dfe).getDgsContext().requestData as DgsWebMvcRequestData).webRequest as NativeWebRequest
        return delegate.resolveArgument(parameter, null, request, null)
    }
}

Java

代码语言:javascript
复制
@Component
public class DgsAuthenticationPrincipalArgumentResolver implements ArgumentResolver {

    private final AuthenticationPrincipalArgumentResolver delegate = new AuthenticationPrincipalArgumentResolver();

    @Nullable
    @Override
    public Object resolveArgument(@NotNull MethodParameter parameter, @NotNull DataFetchingEnvironment dfe) {
        DgsContext context = ((DataFetchingEnvironmentImpl) dfe).getContext();
        DgsWebMvcRequestData requestData = (DgsWebMvcRequestData) context.getRequestData();
        NativeWebRequest request = requestData == null ? null : (NativeWebRequest) requestData.getWebRequest();
        return delegate.resolveArgument(parameter, null, request, null);
    }

    @Override
    public boolean supportsParameter(@NotNull MethodParameter parameter) {
        return delegate.supportsParameter(parameter);
    }

}

在2n和第4个参数上传递nulls是可以的,因为它们在委派的resolveArgument中没有使用,因为您可以检查这里

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73055108

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档