私はGraphQLで春のブートプロジェクトに取り組んでいます。私は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();
}
}
_
.antMatchers("/graphql").authenticated()
の代わりに.antMatchers("/graphql").permitAll()
を使用してから、.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"というセッション属性として保存することです。これが、ログイン操作から取得したセッショントークンの値で「x-auth-token」ヘッダーが設定されたリクエストを作成するときに、Springがコンテキストを自動的に復元できるようにするために必要なすべてです。
.antMatchers("/graphql").permitAll()
のために匿名呼び出しも許可され、サービス層では、パブリックメソッドで次のような注釈を使用できます:@Preauthorize("isAnonymous()
OR hasRole("USER")")
。
permitAll()
を使用する必要がある場合でも、AOPを使用してリゾルバーメソッドに適切なデフォルトを作成できます。
デフォルトで認証を要求するカスタムセキュリティアスペクトを作成できます。
セキュリティで保護されていないメソッドは、たとえば注釈を使用してマークすることができます。
詳細については、私のブログ投稿を参照してください: https://mi3o.com/spring-graphql-security