Maison  >  Article  >  Java  >  Comment résoudre le problème que SpringBoot+Spring Security ne peut pas résoudre sur plusieurs domaines

Comment résoudre le problème que SpringBoot+Spring Security ne peut pas résoudre sur plusieurs domaines

WBOY
WBOYavant
2023-05-16 15:40:551089parcourir

SpringBoot+Spring Security ne peut pas atteindre l'inter-domaine

Inter-domaine lorsque la sécurité n'est pas utilisée :

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.

La solution est la suivante :

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

Points clés à ajouter du code :

   .and()
   .cors()//新加入
   .and()
   .csrf().disable();

Citant le traitement inter-domaines du projet Spring Security

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.

Spring propose de nombreuses façons de résoudre les problèmes inter-domaines. J'utilise personnellement la méthode Crosfilter

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 :

SpringBoot+Spring Security无法实现跨域怎么解决

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 :

SpringBoot+Spring Security无法实现跨域怎么解决

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.

La résolution de ce problème est très simple, vous pouvez utiliser la configuration suivante

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer