I am developing an application for testing Spring Security resources, and in the current state I need one solution to implement roles and permissions for my methods. I already use this annotation:
@Secured("ROLE_ADMIN")
to determine which role should have access to each method. In my database, I have this structure:

which means that for each role I can have a list of permissions. Can anyone point me to a solution to define both constraints for each of my methods? I am configuring Spring Security code through Java this way:
https://github.com/klebermo/webapp2/tree/master/src/com/spring/webapp/lojavirtual/config/security
UPDATE
Following the suggestions presented, I am changing my AuthenticationService (which extends UserDetailsService):
@Service public class AuthenticationService implements UserDetailsService { @Autowired private UsuarioHome accountDao; @Override @Transactional(readOnly = true, propagation = Propagation.SUPPORTS) public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { Usuario account = accountDao.findByField("login", username); if(account==null) { System.out.println("No such user: " + username); throw new UsernameNotFoundException("No such user: " + username); } else if (account.getAutorizacao().isEmpty()) { System.out.println("User " + username + " has no authorities"); throw new UsernameNotFoundException("User " + username + " has no authorities"); } List<Permission> lista = new ArrayList<Permission>(); for(int i=0; i<account.getAutorizacao().size(); i++) { for(int j=0; j<account.getAutorizacao().get(i).getPermissao().size(); j++) { lista.add(account.getAutorizacao().get(i).getPermissao().get(j)); } } boolean accountIsEnabled = true; boolean accountNonExpired = true; boolean credentialsNonExpired = true; boolean accountNonLocked = true; return new User(account.getLogin(), account.getSenha(), accountIsEnabled, accountNonExpired, credentialsNonExpired, accountNonLocked, getAuthorities(lista)); } public List<String> getRolesAsList(List<Permission> list) { List <String> rolesAsList = new ArrayList<String>(); for(Permission role : list){ rolesAsList.add(role.getNome()); } return rolesAsList; } public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) { List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); for (String role : roles) { authorities.add(new SimpleGrantedAuthority(role)); } return authorities; } public Collection<? extends GrantedAuthority> getAuthorities(List<Permission> list) { List<GrantedAuthority> authList = getGrantedAuthorities(getRolesAsList(list)); return authList; }
and in my methods I go to this:
@Controller @RequestMapping(value="privado") public class PrivadoController { @RequestMapping(value="admin") @Secured("admin_main") public ModelAndView admin() { ModelAndView mav = new ModelAndView(); mav.setViewName("privado/admin"); return mav; } @RequestMapping(value="customer") @Secured("customer_main") public ModelAndView customer() { ModelAndView mav = new ModelAndView(); mav.setViewName("privado/customer"); return mav; } }
But now, when I try to go to the page, I get my no_permit page. what is wrong now?
UPDATE
after some changes, I will finally get to this code:
AuthenticationService.java
@Service public class AuthenticationService implements UserDetailsService { @Autowired private UsuarioHome accountDao; @Override @Transactional(readOnly = true, propagation = Propagation.SUPPORTS) public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { Usuario account = accountDao.findByField("login", username); if(account==null) { System.out.println("No such user: " + username); throw new UsernameNotFoundException("No such user: " + username); } else if (account.getAutorizacao().isEmpty()) { System.out.println("User " + username + " has no authorities"); throw new UsernameNotFoundException("User " + username + " has no authorities"); } List<Permission> lista = new ArrayList<Permission>(); int max = account.getAutorizacao().size(); for(int i=0; i<max; i++) { for(int j=0; j<max; j++) { lista.add(account.getAutorizacao().get(i).getPermissao().get(j)); } } boolean accountIsEnabled = true; boolean accountNonExpired = true; boolean credentialsNonExpired = true; boolean accountNonLocked = true; return new User(account.getLogin(), account.getSenha(), accountIsEnabled, accountNonExpired, credentialsNonExpired, accountNonLocked, getAuthorities(lista)); } public List<String> getRolesAsList(List<Permission> list) { List <String> rolesAsList = new ArrayList<String>(); for(Permission role : list){ rolesAsList.add(role.getNome()); } return rolesAsList; } public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) { List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); for (String role : roles) { authorities.add(new SimpleGrantedAuthority(role)); } return authorities; } public Collection<? extends GrantedAuthority> getAuthorities(List<Permission> list) { List<GrantedAuthority> authList = getGrantedAuthorities(getRolesAsList(list)); return authList; } }
In my controller, I am trying to use the @Secured or @PreAuthorize annotation as follows:
@Controller @RequestMapping(value="privado") public class PrivadoController { @RequestMapping(value="admin") //@Secured("admin_main") @PreAuthorize("hasRole('admin_main')") public ModelAndView admin() { ModelAndView mav = new ModelAndView(); mav.setViewName("privado/admin"); return mav; } @RequestMapping(value="customer") //@Secured("customer_main") @PreAuthorize("hasRole('customer_main')") public ModelAndView customer() { ModelAndView mav = new ModelAndView(); mav.setViewName("privado/customer"); return mav; } }
But I do not get access to any user, despite the fact that he informs about the relevant creditors. What is wrong with this current scenario?
UPDATE 2
Well, it happens that the access denial issue was caused by a code error in my CustomAuthenticationSuccessHandler, which now looks like this:
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth) throws IOException, ServletException { HttpSession session = request.getSession(); SavedRequest savedReq = (SavedRequest) session.getAttribute(WebAttributes.ACCESS_DENIED_403); boolean isAdmin = false; boolean isUser = false; if (savedReq == null) { Collection<? extends GrantedAuthority> authorities = auth.getAuthorities(); for (GrantedAuthority grantedAuthority : authorities) { if(grantedAuthority.getAuthority().equals("admin_main")) isAdmin = true; else if(grantedAuthority.getAuthority().equals("customer_main")) isUser = true; } if(isAdmin) response.sendRedirect(request.getContextPath() + "/privado/admin"); else if(isUser) response.sendRedirect(request.getContextPath() + "/privado/customer"); else response.sendRedirect(request.getContextPath() + "/erro/no_permit"); } else { response.sendRedirect(savedReq.getRedirectUrl()); } } }
But now, when I try to enter my application, I get the error described in this section:
SpelEvaluationException: EL1004E: (pos 0): method call: hasPermission method (java.lang.String) not found in MethodSecurityExpressionRoot method
Any ideas on how to solve this problem?