0

In my recent spring project, I am facinf a problem with the configuration of permissions for access to the methods (MethodSecurity). I have this SecurityConfig class:

@Autowired
private CustomAuthenticationProvider authenticationProvider;

public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth
        .authenticationProvider(authenticationProvider);
}

/*@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
     return new CustomAuthenticationManager();
}*/

protected void configure(HttpSecurity http) throws Exception {
    http
        .csrf()
            .disable()
        .authorizeRequests()
            .antMatchers("/erro/login").permitAll()
            .antMatchers("/bootstrap/**", "/jquery/**", "/extra/**", "/publico/**", "/erro/publico/**").permitAll()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/acesso/login").permitAll()
            .loginProcessingUrl("/login").permitAll()
            .usernameParameter("login")
            .passwordParameter("senha")
            .successHandler(new CustomAuthenticationSuccessHandler())
            .failureHandler(new CustomAuthenticationFailureHandler())
            .and()
        .rememberMe()
            .key("lembrete")
            .useSecureCookie(true)
            .and()
        .logout()
            .logoutUrl("/logout")
            .logoutSuccessUrl("/acesso/login").permitAll();
}

/*protected MethodSecurityExpressionHandler createExpressionHandler() {
    DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
    expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
    return expressionHandler;
}*/

In my methods (in controller and service classes), i have this annotations:

@RequestMapping(value="admin")
@PreAuthorize("hasRole('admin_main')")
public ModelAndView admin() {
    ModelAndView mav = new ModelAndView();
    mav.setViewName("privado/admin");
    return mav;
}

@RequestMapping(value="customer")
@PreAuthorize("hasRole('customer_main')")
public ModelAndView customer() {
    ModelAndView mav = new ModelAndView();
    mav.setViewName("privado/customer");
    return mav;
}

Reading some texts over the internet, I learn to use this specific annotation, I should implement a custom PermissionEvaluator, which I did and reference this class in the method createExpressionHandler() of my SecurityConfig (now commented).

But, despite all of that, when I run my project and enter my login credencials, I am being forward to the access denied page I configured for my application. Anyone can point a direction of how configure properly this permission resource in my application?

UPDATE

My CustomPermissionEvaluator.java

public class CustomPermissionEvaluator implements PermissionEvaluator {

    public CustomPermissionEvaluator() {
    }

    @Override
    public boolean hasPermission(Authentication arg0, Object arg1, Object arg2) {
        if (arg0 == null || !arg0.isAuthenticated())
            return false;
        else
            return arg0.getAuthorities().contains(arg1);
    }

    @Override
    public boolean hasPermission(Authentication arg0, Serializable arg1, String arg2, Object arg3) {
        throw new RuntimeException("Id-based permission evaluation not currently supported.");
    }

}

When I uncomment the method createExpressionHandler(), and try run the application, I am informed I will need an custom AuthenticatioManager, but I ahve no idea how implement this last one.

UPDATE

So, I have an idea for my Custom AuthenticationManager, which is working for authenticate the user, but i still can't access the pages from my application.

public class CustomAuthenticationManager implements AuthenticationManager {

    @Autowired
    private CustomAuthenticationProvider authenticationProvider;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        System.out.println("CustomAuthenticationManager.authenticate");
        this.createExpressionHandler();
        return authenticationProvider.authenticate(authentication);
    }

    protected MethodSecurityExpressionHandler createExpressionHandler() {
        System.out.println("CustomAuthenticationManager.createExpressionHandler");
        DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
        return expressionHandler;
    }

}

I try call createExpressionHandler() inside the method createExpressionHandler() from my SecurityConfig, but don't work too.

In both case, the login is done, but i can't access any page.

UPDATE

So, my current situation is that:

My SecurityConfig has a reference to my CustomAuthenticationManager, which call my CustomAuthenticationProvider.

I have one class MethodSecurityConfig, with a reference to my CustomPermissionEvaluator:

@Configuration
@ComponentScan(value="com.spring.webapp.lojavirtual")
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    protected MethodSecurityExpressionHandler createExpressionHandler() {
        System.out.println("MethodSecurityConfig.createExpressionHandler");
        DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
        return expressionHandler;
    }

}

That's my CustomPermissionEvaluator:

@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {

    public CustomPermissionEvaluator() {
    }

    public boolean hasPermission(Authentication arg0, Object arg1) {
        System.out.println("CustomPermissionEvaluator.hasPermission");
        if (arg0 == null || !arg0.isAuthenticated())
            return false;
        else
            return arg0.getAuthorities().contains(arg1);
    }

    @Override
    public boolean hasPermission(Authentication arg0, Object arg1, Object arg2) {
        throw new RuntimeException("Id-based permission evaluation not currently supported.");
    }

    @Override
    public boolean hasPermission(Authentication arg0, Serializable arg1, String arg2, Object arg3) {
        throw new RuntimeException("Id-based permission evaluation not currently supported.");
    }

}

And now I have the error described in the topic:

SpelEvaluationException: EL1004E:(pos 0): Method call: Method hasPermission(java.lang.String) cannot be found on MethodSecurityExpressionRoot type

when I try perform the login in my application. Any ideas about how to solve this?

Community
  • 1
  • 1
Kleber Mota
  • 8,521
  • 31
  • 94
  • 188

1 Answers1

0

Then I solve the problem presented here changing the call for hasPermission in the methods from my controller. The final code for them are:

@Controller
@RequestMapping(value="privado")
public class PrivadoController {

    @RequestMapping(value="admin")
    @PreAuthorize("hasPermission(#usuario, 'admin_main')")
    public ModelAndView admin() {
        ModelAndView mav = new ModelAndView();
        mav.setViewName("privado/admin");
        return mav;
    }

    @RequestMapping(value="customer")
    @PreAuthorize("hasPermission(#usuario, 'customer_main')")
    public ModelAndView customer() {
        ModelAndView mav = new ModelAndView();
        mav.setViewName("privado/customer");
        return mav;
    }

}

(Now I am trying find the correct argument for replace #usuario, which is returning a null value, but this is subject for another topic).

Kleber Mota
  • 8,521
  • 31
  • 94
  • 188