Spring security configuration does not apply with Spring SimpleUrlHandlerMapping

为君一笑 提交于 2020-06-26 19:52:47

问题


I am writing a spring boot application in which I am registering a URL to a bean via the SimpleUrlHandlerMapping configuration. Why am I not using the @Controller or @RequestMapping classes to do this ?!! Because I want to dynamically register URL's during runtime.

I am using the following code to register a simple URL to a controller

    @Bean
    public SimpleUrlHandlerMapping sampleServletMapping() {
        SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
        mapping.setOrder(Integer.MAX_VALUE - 2);

        Properties urlProperties = new Properties();
        urlProperties.put("/index", "myController");

        mapping.setMappings(urlProperties);

        return mapping;
    }

The above code is working fine, I am able to hit the controller bean registered with the name "myController".

The issue appears when I use spring security. I introduced spring security and configured InMemoryAuthentication, and set my configuration as follows.

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/index").permitAll()
                .anyRequest()
                .permitAll();
    }

After doing this when I try to access /index path, it throws a 403, forbidden error. I have tried with permitAll() and fullyAuthenticated() configurations. It doesn't seem to work. However, any Controller class registered with the @Controller and @RequestMapping annotations are perfectly working fine with Security.

So, my assumption is that Spring Security is not aware of the dynamically registered URL's via the SimpleUrlHandlerMapping.

How do I solve this ? Is there a way I can tell spring security to include my dynamic URL registrations ? Unable to find any article on this online.

Suggestions and help much appreciated.


回答1:


UPDATE:

Why csrf().disable() does works

CSRF stands for Cross Site Request Forgery

In simple words, it is one kind of token that is sent with the request to prevent the attacks. In order to use the Spring Security CSRF protection, we'll first need to make sure we use the proper HTTP methods for anything that modifies the state (PATCH, POST, PUT, and DELETE – not GET).

CSRF protection with Spring CookieCsrfTokenRepository works as follows:

  1. The client makes a GET request to Server (Spring Boot Backend), e.g. request for the main page
  2. Spring sends the response for GET request along with Set-cookie header which contains securely generated XSRF Token
  3. The browser sets the cookie with XSRF Token
  4. While sending a state-changing request (e.g. POST) the client (might be angular) copies the cookie value to the HTTP request header
  5. The request is sent with both header and cookie (browser attaches the cookie automatically)
  6. Spring compares the header and the cookie values, if they are the same the request is accepted, otherwise, 403 is returned to the client

The method withHttpOnlyFalse allows angular to read XSRF cookie. Make sure that Angular makes XHR request with withCreddentials flag set to true.

For more details, you may explore the following

  • Will Spring Security CSRF Token Repository Cookies Work for all Ajax Requests Automatically?

  • AJAX request with Spring Security gives 403 Forbidden

  • Basic CSRF Attack Simulation & Protection with Spring Security

Updated method configure(HttpSecurity http)

 http
            .csrf()
            .ignoringAntMatchers("endpoint-to-be-ignored-for-csrf")
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .and()
            .authorizeRequests()
            .antMatchers("/index").permitAll() 
            .anyRequest().authenticated();

Endpoint specified in antMatchers with permitAll() should not required authentication and antMatchers("/index").permitAll() should work fine.

  • Make sure your security configuration class is annotated with @EnableWebSecurity and @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
  • The security configuration class is in follows the package structure and scanned by Spring. spring-component-scanning

You may find the minimal working example here


SecurityConfiguration.java

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // https://stackoverflow.com/a/56389047/10961238 -> WebSecurity vs HttpSecurity

    // Add this method if .antMatchers("/index").permitAll() does not work
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.debug(true);
//        web
//            .ignoring()
//            .antMatchers("/index");
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
            .antMatchers("/index").permitAll() //commenting this line will be results in 403
            .anyRequest().authenticated();
    }

}

SampleController.java

import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller("myController")
public class SampleController extends AbstractController {
    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("::::::::::::::::::::::::::::::::Controller:::::::::::::::::::::::::::::::::");
        response.getWriter().print("Hello world!");
        return null;
    }
}

MainApplication.java

import com.example.mappings.controller.SampleController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;

import java.util.Properties;

@SpringBootApplication
public class MappingsApplication {

    public static void main(String[] args) {
        SpringApplication.run(MappingsApplication.class, args);
    }

    @Bean
    public SimpleUrlHandlerMapping sampleServletMapping() {
        System.out.println("::::::::::::::::::::::::::::::::SimpleUrlHandlerMapping:::::::::::::::::::::::::::::::::");
        SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
        mapping.setOrder(Integer.MAX_VALUE - 2);

        Properties urlProperties = new Properties();
        urlProperties.put("/index", sampleController());
        mapping.setMappings(urlProperties);

        return mapping;
    }

    @Bean
    public SampleController sampleController() {
        System.out.println("::::::::::::::::::::::::::::::::Setting SampleController:::::::::::::::::::::::::::::::::");
        return new SampleController();
    }
}

application.properties

spring.security.user.name = user
spring.security.user.password = user
spring.security.user.roles = ADMIN


来源:https://stackoverflow.com/questions/62340704/spring-security-configuration-does-not-apply-with-spring-simpleurlhandlermapping

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!