gpt4 book ai didi

spring-security - 使用@PreAuthorize 的 GraphQL 和 Spring Security?

转载 作者:行者123 更新时间:2023-12-04 17:19:51 26 4
gpt4 key购买 nike

我在为 graphql 服务设置 spring security 和禁用/启用对基于角色的 jwt 身份验证用户的访问时遇到问题。所有其他 REST 端点都得到适当保护,JWT 身份验证和基于角色的授权正常工作。

我目前拥有的:

在我的 WebSecurityConfigurerAdapter 类中,我有以下代码:

@Override
protected void configure(HttpSecurity http) throws Exception {

http.csrf().disable().cors()
.and()
.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "**/student-service/auth/**").permitAll().antMatchers("**/student-service/auth/**").authenticated()
.and()
.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "**/graphql/**").permitAll().antMatchers("**/graphql/**").authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(entryPoint).and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);

http.addFilterBefore(authenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
http.headers().cacheControl();

}

graphql 服务上,我有一个 @PreAuthorize:

@Component 
public class UserResolver implements GraphQLQueryResolver{

@Autowired
UserRepo repo;

@PreAuthorize("hasAnyAuthority('ADMIN')")
public User findUser(int id) {
return User.builder()
.id(1)
.email("test@grr.la")
.password("123")
.username("John")
.bankAccount(BankAccount.builder()
.id(1)
.accountName("some account name")
.accountNumber("some account number")
.build())
.build();
}
}

localhost:8080/login 上获取 JWT 并发送 graphql 查询后,使用上述配置和代码,我得到:

org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:73) ~[spring-security-core-5.4.5.jar:5.4.5]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.attemptAuthorization(AbstractSecurityInterceptor.java:238) ~[spring-security-core-5.4.5.jar:5.4.5]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:208) ~[spring-security-core-5.4.5.jar:5.4.5]
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:58) ~[spring-security-core-5.4.5.jar:5.4.5]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.5.jar:5.3.5]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.5.jar:5.3.5]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.3.5.jar:5.3.5]

这是 Postman 请求的样子:

enter image description here

GraphQL 查询:

query {
findUser(id : 1) {
id
email
}
}

和响应:

{
"errors": [
{
"message": "Access is denied",
"locations": [
{
"line": 2,
"column": 1
}
],
"path": [
"findUser"
],
"extensions": {
"type": "AccessDeniedException",
"classification": "DataFetchingException"
}
}
],
"data": {
"findUser": null
}
}

application.yml 文件:

graphql:
servlet:
max-query-depth: 100
exception-handlers-enabled: true
playground:
headers:
Authorization: Bearer TOKEN

query.graphqls 文件:

type Query {

findUser(id: ID): User

}

type User {

id: ID!
username: String
password: String
email: String
bankAccount: BankAccount
}

type BankAccount {
id: ID!
accountName: String
accountNumber: String

}

最佳答案

我花了一天时间想弄清楚这个问题。在您的数据获取环境中,如果您调用

environment.getContext()

您应该取回一个 GraphQLContext 的实例,它具有带有授权的 HTTP 请求和 header 。对我来说,这本质上是一个空的 HashMap,没有关于请求的详细信息。在深入研究并尝试 AOP 更改的所有内容后,我发现了 auth0 的建议,即创建一个实现 GraphQLInvocation 的类。这是我的解决方案,它将 Spring Security 上下文的一个实例放入数据获取环境上下文对象中。我现在至少能够对数据 getter 进行身份验证,因为我有一个 Spring Security 上下文可以使用(具有授权权限等)。我宁愿有一个与 Spring Security 集成的过滤器(我可以获得 preAuthorize 方法,就像你正在做),但我现在正在努力解决这个问题。

@Primary
@Component
@Internal
public class SecurityContextGraphQLInvocation implements GraphQLInvocation {

private final GraphQL graphQL;
private final AuthenticationManager authenticationManager;

public SecurityContextGraphQLInvocation(GraphQL graphQL, AuthenticationManager authenticationManager) {
this.graphQL = graphQL;
this.authenticationManager = authenticationManager;
}

@Override
public CompletableFuture<ExecutionResult> invoke(GraphQLInvocationData invocationData, WebRequest webRequest) {
final String header = webRequest.getHeader("Authorization");
SecurityContext securityContext;
if (header == null || !header.startsWith("Bearer ")) {
securityContext = new SecurityContextImpl();
} else {
String authToken = header.substring(7);
JwtAuthenticationToken authRequest = new JwtAuthenticationToken(authToken);
final var authentication = authenticationManager.authenticate(authRequest);
securityContext = new SecurityContextImpl(authentication);
}

ExecutionInput executionInput = ExecutionInput.newExecutionInput()
.query(invocationData.getQuery())
.context(securityContext)
.operationName(invocationData.getOperationName())
.variables(invocationData.getVariables())
.build();
return graphQL.executeAsync(executionInput);
}
}

关于spring-security - 使用@PreAuthorize 的 GraphQL 和 Spring Security?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66907039/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com