使用graphql在Spring Boot中进行身份验证 [英] authentication in spring boot using graphql

查看:119
本文介绍了使用graphql在Spring Boot中进行身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用GraphQL进行Spring Boot项目.我正在使用graphql-java-tools和graphql-spring-boot-starter.正如您在下面的Java配置文件中看到的那样,我设法通过Spring Security配置了安全性和会话管理.

I’m working on a spring boot project with GraphQL. I'm using graphql-java-tools and graphql-spring-boot-starter. I managed to configure security and session management with spring security as you can see in the java config files below.

现在"/graphql"路径是安全的(只能在请求的http头中发送基本http身份验证"或会话令牌(x-auth-token)来访问它).在任何GraphQL操作上使用基本http身份验证"进行身份验证将启动一个新会话,并在标头中发送回新的会话令牌,该令牌可进一步用于继续该会话.

Now the "/graphql" path is secured (it can be accessed only sending the "basic http authentication" or a session token (x-auth-token) in a http header of the request). Authenticating with "basic http authentication" on any GraphQL operation will start a new session and send back the new session token in a header, and that token can be used further to continue that session.

如何授予匿名用户访问一些GraphQL查询/突变的权限,以保持上述行为?

How to give access to anonymous users to some GraphQL queries/mutations keeping the above behavior?

如果为了允许匿名访问而将antMatchers("/graphql").authenticated()更改为antMatchers("/graphql").permitAll(),那么即使我尝试使用基本http身份验证"进行身份验证,也不会再调用我的自定义AuthenticationProvider.

If I change antMatchers("/graphql").authenticated() to antMatchers("/graphql").permitAll() in order to allow anonymous access, then my custom AuthenticationProvider is not called anymore even when I try to authenticate with "basic http authentication".

谢谢!

这是我的配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private AuthenticationProvider authenticationProvider;

    @Override
    public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) {
        authenticationManagerBuilder.authenticationProvider(authenticationProvider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
            .antMatchers("/graphql").authenticated()
            .and()
            .requestCache()
            .requestCache(new NullRequestCache())
            .and()
            .httpBasic()
            .and()
            .headers()
            .frameOptions().sameOrigin() // needed for H2 web console
            .and()
            .sessionManagement()
            .maximumSessions(1)
            .maxSessionsPreventsLogin(true)
            .sessionRegistry(sessionRegistry());
    }

    @Bean
    public SessionRegistry sessionRegistry() {
        return new SessionRegistryImpl();
    }

    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }
}

@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 180)
public class HttpSessionConfig {

    @Bean
    public HttpSessionStrategy httpSessionStrategy() {
        return new HeaderHttpSessionStrategy();
    }

}

推荐答案

我们使用.antMatchers("/graphql").permitAll()代替了.antMatchers("/graphql").permitAll(),然后删除了.httpBasic(),还删除了自定义的AuthenticationProvider.现在,安全配置如下所示:

Instead of .antMatchers("/graphql").authenticated() we used .antMatchers("/graphql").permitAll(), then we removed .httpBasic() and also removed the custom AuthenticationProvider. Now the security configs look like this:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
            .antMatchers("/graphql").permitAll()
            .and()
            .requestCache()
            .requestCache(new NullRequestCache())
            .and()
            .headers()
            .frameOptions().sameOrigin() // needed for H2 web console
            .and()
            .sessionManagement()
            .maximumSessions(1)
            .maxSessionsPreventsLogin(true)
            .sessionRegistry(sessionRegistry());
    }

    @Bean
    public SessionRegistry sessionRegistry() {
        return new SessionRegistryImpl();
    }

    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }
}

然后,我们为登录创建了一个变异,该变异接受用户的凭据并返回会话令牌.这是graphql模式:

Then we created a mutation for login that accepts the user's credentials and returns the session token. Here is the graphql schema:

login(credentials: CredentialsInputDto!): String

input CredentialsInputDto {
    username: String!
    password: String!
}

基本上,我们在自定义AuthenticationProvider中拥有的代码已进入登录操作所调用的服务:

Basically the code we had in our custom AuthenticationProvider went into the service that is called by the login operation:

public String login(CredentialsInputDto credentials) {
    String username = credentials.getUsername();
    String password = credentials.getPassword();

    UserDetails userDetails = userDetailsService.loadUserByUsername(username);

    ... credential checks and third party authentication ...

    Authentication authentication = new UsernamePasswordAuthenticationToken(username, password, userDetails.getAuthorities());
    SecurityContextHolder.getContext().setAuthentication(authentication);
    httpSession.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext());
    return httpSession.getId();
}

关键在于,我们使用经过身份验证的用户的身份验证准备了会话上下文,然后将其保存(以redis格式)作为称为"SPRING_SECURITY_CONTEXT"的会话属性.当您发出一个请求,该请求设置了"x-auth-token"标头并设置了从登录操作获得的会话令牌的值时,spring便能够自动恢复上下文.

The key is that we prepared the session context with the authenticated user's authentication and then we save it (in redis) as a session attribute called "SPRING_SECURITY_CONTEXT". This is all what spring needs to be able to automatically restore the context when you make a request having the "x-auth-token" header set with the value of the session token obtained from the login operation.

由于.antMatchers("/graphql").permitAll()现在也允许匿名调用,并且在服务层中,在公共方法上,我们可以使用如下注释:@Preauthorize("isAnonymous()hasRole("USER")").

Now also anonymous calls are allowed because of .antMatchers("/graphql").permitAll() and in the service layer, on public methods we can use annotations like this: @Preauthorize("isAnonymous() OR hasRole("USER")").

这篇关于使用graphql在Spring Boot中进行身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆