it-swarm.com.de

Problemloses Einrichten des Access-Control-Allow-Origin-Filters in Spring Security 3.2

Ich versuche, meinen Spring-Server mit Spring Security 3.2 einzurichten, um eine Ajax-Anmeldeanforderung ausführen zu können.

Ich habe das Spring Security 3.2 Video und ein paar Posts verfolgt, aber das Problem ist, dass ich es bekomme 

 No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:9000' is therefore not allowed access. 

Für die Login-Anfragen (siehe unten). 

Ich habe ein CORSFilter-Setup erstellt und kann auf die ungeschützten Ressourcen in meinem System zugreifen, indem die entsprechenden Header der Antwort hinzugefügt werden. 

Meine Vermutung ist, dass ich die CORSFilter nicht zur Sicherheitsfilterkette hinzufüge oder dass es zu spät in der Kette ist. Jede Idee wird geschätzt. 

WebAppInitializer

public class WebAppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) {
        WebApplicationContext rootContext = createRootContext(servletContext);

        configureSpringMvc(servletContext, rootContext);

        FilterRegistration.Dynamic corsFilter = servletContext.addFilter("corsFilter", CORSFilter.class);
        corsFilter.addMappingForUrlPatterns(null, false, "/*");
    }

    private WebApplicationContext createRootContext(ServletContext servletContext) {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();

        rootContext.register(SecurityConfig.class, PersistenceConfig.class, CoreConfig.class);

        servletContext.addListener(new ContextLoaderListener(rootContext));
        servletContext.setInitParameter("defaultHtmlEscape", "true");

        return rootContext;
    }


    private void configureSpringMvc(ServletContext servletContext, WebApplicationContext rootContext) {
        AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext();
        mvcContext.register(MVCConfig.class);

        mvcContext.setParent(rootContext);
        ServletRegistration.Dynamic appServlet = servletContext.addServlet(
                "webservice", new DispatcherServlet(mvcContext));
        appServlet.setLoadOnStartup(1);
        Set<String> mappingConflicts = appServlet.addMapping("/api/*");

        if (!mappingConflicts.isEmpty()) {
            for (String s : mappingConflicts) {
                LOG.error("Mapping conflict: " + s);
            }
            throw new IllegalStateException(
                    "'webservice' cannot be mapped to '/'");
        }
    }

SecurityWebAppInitializer:

public class SecurityWebAppInitializer extends AbstractSecurityWebApplicationInitializer {
}

SecurityConfig:

Anfragen an / api/users - funktionieren gut und die Access-Control-Allow-Header werden hinzugefügt. Ich habe csrf und Header deaktiviert, nur um sicherzustellen, dass dies nicht der Fall ist 

@EnableWebMvcSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
    protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .headers().disable()                
            .authorizeRequests()
                    .antMatchers("/api/users/**").permitAll()
                    .anyRequest().authenticated()
                    .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

CORFilter:  

@Component
public class CORSFilter implements Filter{
    static Logger logger = LoggerFactory.getLogger(CORSFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
        chain.doFilter(request, response);
    }

    public void destroy() {}
}

Loginanfrage:  

Request URL:http://localhost:8080/devstage-1.0/login
Request Headers CAUTION: Provisional headers are shown.
Accept:application/json, text/plain, */*
Cache-Control:no-cache
Content-Type:application/x-www-form-urlencoded
Origin:http://127.0.0.1:9000
Pragma:no-cache
Referer:http://127.0.0.1:9000/
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36
Form Dataview sourceview URL encoded
username:user
password:password
13
special0ne

Alles, was mir fehlte, war AddFilterBefore beim Konfigurieren der Sicherheitskonfiguration. 

Die endgültige Version war also:

@EnableWebMvcSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
        .withUser("user").password("password").roles("USER");
  }


  @Override
  protected void configure(HttpSecurity http) throws Exception {
      http
          .addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class)

          .formLogin()
              .loginPage("/login")
              .and()
          .authorizeRequests()
              .anyRequest().authenticated();

Und entfernen Sie den CORSFilter aus WebAppInitializer

17
special0ne

Ich weiß, es ist zu spät, um Ihre Frage zu beantworten. In Ihrer ursprünglichen Konfiguration haben Sie die Konfigurationsmetadaten des Spring Security-Initialisierers im Stammkontext registriert:

rootContext.register(SecurityConfig.class, PersistenceConfig.class, CoreConfig.class);

Wenn Sie dies tun können, müssen Sie dies nicht tun, da die Sicherheitsfilterkette mit dem Webanwendungskontext gekoppelt wird, der nicht erforderlich ist. Stattdessen können Sie die Filterkette einfach wie gewohnt hinzufügen, indem Sie den DelegatingFilterProxy als Filter registrieren. Natürlich müssen Sie die Reihenfolge beibehalten, indem Sie den Cors-Filter hinzufügen, bevor Sie die Federsicherheitsfilterkette hinzufügen.

Auf diese Weise können Sie den Standard-CorsFilter (einfach durch Hinzufügen von init-Parametern) verwenden, der im Paket org.Apache.catalina.filters enthalten ist. Trotzdem können Sie auch bei Ihrer eigenen Konfiguration bleiben! :)

0
Aaron Stone