而不是
.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!): Stringinput 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()ORhasRole("USER")")。


