0

I have created a client angular on webstorm and I have a Spring Boot server on Eclipse. The problem is when I try to open the session i get this error message:

OPTIONS http://localhost:8080/allquestions 401 ()
(anonymous) @ angular.js:12410
p @ angular.js:12155
(anonymous) @ angular.js:11908
(anonymous) @ angular.js:16648
$eval @ angular.js:17972
$digest @ angular.js:17786
$apply @ angular.js:18080
(anonymous) @ angular.js:19924
f @ angular.js:6111
(anonymous) @ angular.js:6390


XMLHttpRequest cannot load http://localhost:8080/allquestions. Response for preflight has invalid HTTP status code 401

The WebConfig

@EnableWebMvc
@Configuration
@ComponentScan
public class WebConfig extends WebMvcConfigurerAdapter {

public WebConfig() {
    super();
}

@Override
public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/login").setViewName("login");
    registry.addViewController("/").setViewName("welcome");
    registry.addViewController("/welcome").setViewName("welcome");
    registry.addViewController("/exam").setViewName("exam");
    registry.addViewController("/report").setViewName("report");
    registry.addViewController("/error").setViewName("error");
    registry.addViewController("/editing").setViewName("editing");
}

@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
    super.addResourceHandlers(registry);
    registry.addResourceHandler("/images/**").addResourceLocations("/images/");
    registry.addResourceHandler("/css/**").addResourceLocations("/css/");
    registry.addResourceHandler("/js/**").addResourceLocations("/js/");
}

A part of the Controller :

@RestController
public class HomeController {

@Autowired
private BusinessModel businessModel;
private List<String> messages;

private User currentUser;

@PostConstruct
public void init() {
    messages = businessModel.getMessages();
}

// Communicate informations to client
private void sendOptions(HttpServletResponse response) {
    if (businessModel.getCorsNeeded().booleanValue()) {
        // Fix the header CORS
        response.addHeader("Access-Control-Allow-Origin", "*");
        // Header Authorization
        response.addHeader("Access-Control-Allow-Headers", "Authorization");
    }
}

// questions list via OPTIONS
@RequestMapping(value = "/allquestions", method = RequestMethod.OPTIONS)
public void getAllQuestions(HttpServletResponse response) {
    sendOptions(response);
}

The SecurityConfig :

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private UsersService usersService;

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.httpBasic();
    http.authorizeRequests().antMatchers("/login").permitAll().antMatchers("/**").hasRole("USER").and().formLogin()
            .loginPage("/login").and().logout();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(usersService).passwordEncoder(new BCryptPasswordEncoder());
}
}

I can't add xml file (restriction of my work context)...

I am totally blocked and I need your help!

ReNaR
  • 169
  • 1
  • 2
  • 16

1 Answers1

0

The solution for everyone !

You create a filter who can make the sort :

public class CorsFilter implements Filter {

    @Override
    public void destroy() {
    }

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

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

You can see, the filter create for you all the headers. And the most wanted : httpResponse.setHeader("Access-Control-Allow-Origin", ""*).

Then, you can call the filter in the SecurityConfig :

@EnableAutoConfiguration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UsersService usersService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);
        http.csrf().disable();
        http.httpBasic();
        http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/", "/**").permitAll();
        http.authorizeRequests().antMatchers(HttpMethod.GET, "/", "/**").permitAll();
        //http.authorizeRequests().antMatchers("/login").permitAll().antMatchers("/**").hasRole("USER").and().formLogin().loginPage("/login").and().logout();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(usersService).passwordEncoder(new BCryptPasswordEncoder());
    }
}

There, you can see the filter is call before the request properly : http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class).

This is the best solution I found and the only works for me ! I hope, it can help you !

Peter Keller
  • 7,526
  • 2
  • 26
  • 29
ReNaR
  • 169
  • 1
  • 2
  • 16