【问题标题】:authentication in spring boot using graphql使用graphql在spring boot中进行身份验证
【发布时间】:2018-02-08 02:21:41
【问题描述】:

我正在使用 GraphQL 开发一个 Spring Boot 项目。我正在使用 graphql-java-tools 和 graphql-spring-boot-starter。正如您在下面的 java 配置文件中看到的那样,我设法使用 spring security 配置安全性和会话管理。

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

如何让匿名用户访问一些保持上述行为的 GraphQL 查询/突变?

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

谢谢!

这是我的配置:

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

}

【问题讨论】:

    标签: authentication spring-boot spring-security graphql graphql-java


    【解决方案1】:

    即使您需要使用permitAll(),您仍然可以使用 AOP 为您的解析器方法创建合理的默认值。

    您可以创建默认需要身份验证的自定义安全方面。

    可以使用注释来标记不安全的方法。

    详情见我的博文:https://michalgebauer.github.io/spring-graphql-security

    【讨论】:

    • 博客文章在这个问题上为我提供了极大的帮助,干得好!
    • 我只想说,我花了一整天的时间寻找解决方案,直到找到您的博文,非常感谢!
    【解决方案2】:

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

    @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 架构:

    login(credentials: CredentialsInputDto!): String
    
    input CredentialsInputDto {
        username: String!
        password: String!
    }
    

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

    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”的会话属性。这就是当您发出请求时,spring 需要能够自动恢复上下文,该请求将“x-auth-token”标头设置为从登录操作获得的会话令牌的值。

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

    【讨论】:

      猜你喜欢
      • 2019-02-08
      • 2018-08-29
      • 2023-03-19
      • 1970-01-01
      • 2022-10-12
      • 2014-09-10
      • 2014-09-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多