1

I try to move from @Configuration based security to JSR 250 method level security. The code below works as follows:

Access to my page is configured in configure(HttpSecurity http) inside SecurityConfiguration.class. Everyone is allowed to access "all" page, if someone try "protected" then the default login page is displayed, if the role is wrong then "Access denied" message is shown. Fine.

Now, I would like to do exactly the same thing but by using JSR 250 Annotations. So:

I have removed configure(HttpSecurity http) method, added to dispatcher servlet context configuration

@EnableGlobalMethodSecurity(jsr250Enabled = true, proxyTargetClass = true, mode = AdviceMode.ASPECTJ, prePostEnabled=true)

and obviously @PermitAll and @RolesAllowed inside the controller.

These changes do not work properly. If I try to access any page I am asked about credentials (default login page), If I fill them then I am able to access any page in any role :(

Have I forgotten about something?

Thank you in advance for any help you can provide, Marek

Application Context:

@Import(SecurityConfiguration.class)
public class AppConfiguration {
  // entityManagerFactory, transactionManager, localValidatorFactoryBean, methodValidationPostProcessor 
}

@Configuration
@EnableWebMvcSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Inject
  public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().withUser("marek").password("123456").roles("USER");
    auth.inMemoryAuthentication().withUser("bill").password("123456").roles("ADMIN");
    auth.inMemoryAuthentication().withUser("james").password("123456").roles("SUPERADMIN");
  }

  @Bean
  @Override
  public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests().antMatchers("/all**").permitAll();
    http.authorizeRequests().antMatchers("/protected/**").access("hasRole('ROLE_ADMIN')");
    http.authorizeRequests().antMatchers("/confidential/**").access("hasRole('ROLE_SUPERADMIN')");
    http.authorizeRequests().and().formLogin();
}

WebApplicationContext:

@Configuration
@EnableWebMvc
@EnableGlobalMethodSecurity(jsr250Enabled = true, proxyTargetClass = true, mode = AdviceMode.ASPECTJ, prePostEnabled=true)
@ComponentScan(basePackages = "xxx.xxx.controllers")
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
  // addInterceptors, addViewControllers, templateResolver, templateEngine, thymeleafViewResolver
}

Controller:

@Controller
public class HomeController {
  @PermitAll
  @RequestMapping(value = "/all**", method = RequestMethod.GET)
  public String allPage(Model model) {
    return "all";
  }

  @RolesAllowed("ADMIN")
  @RequestMapping(value = "/protected**", method = RequestMethod.GET)
  public String protectedPage(Model model) {
    return "protected";
  }

  @RolesAllowed("SUPERADMIN")
  @RequestMapping(value = "/confidential**", method = RequestMethod.GET)
  public String superAdminPage(Model model) {
    return "confidential";
  }
}

Dependencies:

<appengine.target.version>1.9.18</appengine.target.version>
<javax.servlet-api.version>3.1.0</javax.servlet-api.version>
<javax.jsr250-api.version>1.0</javax.jsr250-api.version>
<spring.version>4.1.5.RELEASE</spring.version>
<spring.security.version>3.2.6.RELEASE</spring.security.version>
<spring.thymeleaf.version>2.1.4.RELEASE</spring.thymeleaf.version>
<aspectj.version>1.8.5</aspectj.version>
Marek Raki
  • 3,056
  • 3
  • 27
  • 50

1 Answers1

2

I noticed that your @ EnableGlobalMethodSecurity annotation uses proxy mode AdviceMode.ASPECTJ but your dependencies don't list AspectJ.

If you're trying to use AspectJ proxies, then you need to provide the dependency and add configuration to compile using AspectJ compiler.

If you do not intend to use AspectJ proxies, then try without the 'mode = AdviceMode.ASPECTJ' parameter.

Edit - This might not be obvious. For using AspectJ proxies, you need to:

  1. specify dependencies
  2. provide aspectj plugin configuration to compile with AspectJ compiler

Here's an example of maven configuration: Running JDK8 for aspectj

Here's one for gradle: https://github.com/jigishpa/spring-samples/blob/master/aop/hello/build.gradle

Community
  • 1
  • 1
Jigish
  • 1,764
  • 1
  • 15
  • 20
  • Sorry, I forgot to add this to the post, I missed it while shortlisting I use: org.aspectj aspectjrt ${aspectj.version} – Marek Raki Mar 25 '15 at 08:19
  • but actually.. when I check the stacktrace while execution inside the controller I don't see any aspect in the middle: HomeController.allPage(Model) line: 51 NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57 DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43 Method.invoke(Object, Object...) line: 601 Runtime.invoke(Method, Object, Object[]) line: 130 – Marek Raki Mar 25 '15 at 08:25
  • yeah... and works the same way if I remove this dependency haha so for sure AspectJ does not do its job – Marek Raki Mar 25 '15 at 08:33
  • oki, solved. I have moved to JDK dynamic proxies. Unfortunately this forces me to write interface to every controller that I create, but anyway it is better to use them on very restrictive GAE environment where I am working. The last thing to solve is how to skip login page for @PermiAll methods but that is a separate task. – Marek Raki Mar 25 '15 at 11:03
  • cool :-) I am not using maven but I have a gradle project that uses AspectJ proxies. Take a look if you're interested https://github.com/jigishpa/spring-samples/tree/master/aop/hello. Look at build.gradle. – Jigish Mar 25 '15 at 19:10
  • By the way, you also need to provide configuration to compile your proxies with AspectJ Just providing a maven dependency is not sufficient. Here's an example of such a configuration with Java 8 http://stackoverflow.com/questions/25155905/running-jdk8-for-aspectj That should save you from having to write interface for every controller :-) – Jigish Mar 25 '15 at 19:22