12

I'm trying to configure Spring Security on a Spring Boot application as follows:

@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private RestAuthenticationEntryPoint unauthorizedHandler; @Bean public JwtAuthenticationFilter authenticationTokenFilterBean() throws Exception { JwtAuthenticationFilter authenticationTokenFilter = new JwtAuthenticationFilter(); authenticationTokenFilter.setAuthenticationManager(authenticationManagerBean()); return authenticationTokenFilter; } @Override protected void configure(HttpSecurity httpSecurity) throws Exception { //@formatter:off httpSecurity .csrf() .disable() .exceptionHandling() .authenticationEntryPoint(this.unauthorizedHandler) .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() .antMatchers("/login", "/singup", "/subscribers").permitAll() .anyRequest().authenticated(); // Custom JWT based security filter httpSecurity .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); //@formatter:on } } 

My unauthorizedHandler is:

public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { private static final Logger LOGGER = LoggerFactory.getLogger(RestAuthenticationEntryPoint.class); @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); } } 

Finally, the REST controller for /subscribers is:

@RestController public class SubscriberRestController { @Autowired ISubscribersService subscribersService; @RequestMapping(value = RequestMappingConstants.SUBSCRIBERS, method = RequestMethod.GET) @ResponseBody public Number subscriberCount() { return subscribersService.subscribersCount(); } @RequestMapping(value = RequestMappingConstants.SUBSCRIBERS, method = RequestMethod.POST) public String subscriberPost(@RequestBody SubscriberDocument subscriberDocument) { return subscribersService.subscribersInsert(subscriberDocument); } @RequestMapping(value = "/test", method = RequestMethod.GET) public String test() { return "This is a test"; } } 

I use postman to test endpoints and when I do a POST to "localhost:8080/subscribers", I get:

Postman result

I want to have opened endpoints (/subscribers) without any security control or credentials check, endpoints for singup and login and secured endpoints for authenticated users.

Thanks! :)

5
  • If I do this, it allows me to access /subscribers but also allows me to access secured REST endpoints. @Sobik Commented Dec 12, 2016 at 8:10
  • 1
    That is what you programmed yourself by overriding the requiresAuthentication. It always will now return this. Why are you implementing JWT support yourself? Spring Security already has an extension for that. Commented Dec 13, 2016 at 8:15
  • I'm learning Spring security, my knowledge about spring security is poor. How can use Spring Security default JWT support? @M.Deinum Commented Dec 13, 2016 at 10:00
  • 1
    Thanks a lot for your help @dur ! Log can be found here. I only made bootRun and after, a POST Request to /subscribers. Commented Dec 13, 2016 at 17:07
  • 1
    @dur Thanks a lot!!!!!!! Now it's working. Spring were not taking configuration because config package was not on @ComponentScan(basePackages="...") Commented Dec 15, 2016 at 11:43

4 Answers 4

6

Spring Boot was not applying the configuration because couldn't find it. On Application.java config package was not included with @ComponentScan anotation.

Sign up to request clarification or add additional context in comments.

1 Comment

In default Spring application annotation @Configuration should create configuration bean.
3

After some researching, here is solution:

@SpringBootApplication(exclude = {SecurityAutoConfiguration.class }) @ComponentScan(basePackages = { PackageConstants.PACKAGE_CONTROLLERS_REST, PackageConstants.PACKAGE_SERVICES, PackageConstants.PACKAGE_SERVICES_IMPL, PackageConstants.PACKAGE_MONGO_REPOSITORIES, PackageConstants.PACKAGE_MONGO_REPOSITORIES_IMPL, PackageConstants.PACKAGE_UTILS }) public class Application { // Clase principal que se ejecuta en el bootrun public static void main(String[] args) { SpringApplication.run(Application.class, args); } } 

Main line is @SpringBootApplication(exclude = {SecurityAutoConfiguration.class }) it tells not use Spring Boot Security AutoConfiguration configuration. It is not full answer, because now you have to tell Spring user your Spring Security configuration class. Also i advice you to create Initializer class with init Root Config Classes, ApplicationConfiguration using and refuse to use SpringBoot applications. Something like this:

ApplicationConfig:

@Configuration @EnableWebMvc @ComponentScan("com.trueport.*") @PropertySource("classpath:app.properties") public class ApplicationConfig extends WebMvcConfigurerAdapter { .... } 

ApplicationSecurityConfig:

@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter { .... } 

Initializer:

public class Initializer implements WebApplicationInitializer { private static final String DISPATCHER_SERVLET_NAME = "dispatcher"; @Override public void onStartup(ServletContext servletContext) throws ServletException { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); .... DispatcherServlet dispatcherServlet = new DispatcherServlet(ctx); dispatcherServlet.setThrowExceptionIfNoHandlerFound(true); ctx.register(ApplicationConfig.class); ServletRegistration.Dynamic servlet = servletContext.addServlet(DISPATCHER_SERVLET_NAME, dispatcherServlet); servlet.addMapping("/"); servlet.setLoadOnStartup(1); servlet.setAsyncSupported(true); } } 

5 Comments

Hi @dikkini !! That not works for me, I don't understand where is my error.
I have .antMatchers("/login/**", "/signup/**", "/subscribers").anonymous() and I get 401 Unauthorized on postman response to localhost:8080/subscribers @dikkini
It doesn't work neither. Maybe some auto Spring boot configuration is making it fail?
Full code can be found here. I'm very grateful for your help :)
There are not only advice to refuse Spring Boot, but and solution for your problem with Spring Boot. I advice to refuse Spring Boot because it adds a lot of code which you don't know and there are always several solutions: 1. Learn Spring Boot and read how it works deeply. 2. Do not use Spring Boot and control spring application by yourself.
3

If your application is simply saving APIs, and you have included dependency for spring security - for any other reason (Mine was to enables headers X-Frame and Content-Security-Policy), then by default Spring includes servlet filter for csrf protection. If you do not disable this, all requests fail with HTTP 401 error.

To disable it, You create a Configuration class extending WebSecurityConfigurerAdapter and annotated with EnableWebSecurity

@EnableWebSecurity @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable(); } } 

This article is worthy the read - very detailed.

Comments

1

You need to add the following to your configure method /error is the default fall back when error occurs to the application due to any exception and it is secured by default.

protected void configure(HttpSecurity httpSecurity) throws Exception { //disable CRSF httpSecurity //no authentication needed for these context paths .authorizeRequests() .antMatchers("/error").permitAll() .antMatchers("/error/**").permitAll() .antMatchers("/your Urls that dosen't need security/**").permitAll() 

Also the below code snippet

 @Override public void configure(WebSecurity webSecurity) throws Exception { webSecurity .ignoring() // All of Spring Security will ignore the requests .antMatchers("/error/**") } 

Now you will not get 401 and get 500 exception with details when an exception occurred for permitAll Urls

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.