Maison >Java >javaDidacticiel >Comment résoudre le problème que SpringBoot+Spring Security ne peut pas résoudre sur plusieurs domaines
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.web.servlet.config.annotation.*; @Configuration @AutoConfigureBefore(SecurityConfig.class) public class MyMvcConfigurer implements WebMvcConfigurer { public void addCorsMappings(CorsRegistry registry){ LOGGER.info("跨域已设置"); registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("*") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); } }
Lors de l'intégration de la sécurité, nous avons constaté qu'il existe toujours des problèmes inter-domaines lorsque l'on utilise uniquement la méthode ci-dessus pour séparer l'avant et l'arrière se termine.
@Configuration @AutoConfigureBefore(Swagger2Configuration.class) @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) @Order(-1) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin() .loginProcessingUrl("/user/login") .loginPage("/singIn.html") .successHandler(moyuAuthenticationSuccessHandler) .failureHandler(moyuAuthenticationFailureHandler) .and() .apply(moyuSocialSecurityConfig) .and() .rememberMe() .tokenRepository(persistentTokenRepository()) .tokenValiditySeconds(3600*24*7) .userDetailsService(userDetailsService) .and() .authorizeRequests() .antMatchers("/user/login","/login","/singIn.html","**","/**").permitAll() .anyRequest() .authenticated() .and() .cors() .and() .csrf().disable(); } }
.and() .cors()//新加入 .and() .csrf().disable();
Le projet récent a adopté un framework avec front-end et back-end. séparation. Les interfaces front-end et back-end ne sont pas déployées sur un site, et des problèmes inter-domaines sont survenus. Qu'est-ce que l'inter-domaine, je ne l'expliquerai pas ici, parlons directement de la solution.
Le code spécifique est le suivant :
@Bean public CorsFilter corsFilter() { final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); final CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.setAllowCredentials(true); corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); return new CorsFilter(urlBasedCorsConfigurationSource); }
Une fois la configuration terminée, testez l'appel et signalez une erreur 401, mais elle persiste. ça ne marche pas. J'ai vérifié les informations en ligne et appris que les demandes inter-domaines seront effectuées deux fois. Le processus spécifique est illustré dans la figure ci-dessous :
Pour chaque requête inter-domaines, avant que la requête réelle n'atteigne le backend, le navigateur lancera d'abord une requête de contrôle en amont. La méthode de requête est OPTIONS pour demander au serveur s'il doit le faire. acceptez la demande inter-domaines. Les paramètres spécifiques sont les suivants Image :
Mais cette demande ne peut pas transporter de cookies et d'en-têtes auto-définis.
Depuis que la sécurité Spring a été introduite dans le projet, la méthode de livraison de jeton que j'ai utilisée consistait à utiliser le champ d'autorisation dans l'en-tête de cette façon, en m'appuyant sur Spring Security pour intercepter la demande de contrôle en amont et en constatant qu'elle ne contient pas de jeton, une erreur 401 sera signalée, indiquant aucune autorisation.
pour que la sécurité Spring ne vérifie pas la demande de contrôle en amont.
@Override public void configure(HttpSecurity http) throws Exception { ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http.authorizeRequests(); registry.requestMatchers(CorsUtils::isPreFlightRequest).permitAll();//让Spring security放行所有preflight request }
Cela a été corrigé après avoir réessayé, mais la configuration directe du backend pour prendre en charge plusieurs domaines entraînera deux requêtes. Une autre façon consiste à utiliser Nginx pour transmettre la demande.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!