Spring Security, annotation @Secured is not working

I am using Spring MVC.

The @Secured annotation does not work.

I've tried many options and nothing seems to work. Tell me, what am I doing wrong ?

I was looking at this page - Spring Security, Method Security annotation (@Secured ) is not working (java config) it didn't help me.

. . .

This is my github code. https://github.com/MyTestPerson/securede

Personal.class

    @Controller
    public class Personal {


        @GetMapping(value = "/personal")
        public ModelAndView personalGet () {

            ModelAndView modelAndView = new ModelAndView("/personal");

            modelAndView.addObject("msg", myMsg());

            return modelAndView;

        }



        @Secured(value = {"ROLE_ADMIN"})
        private String myMsg() {

            return "Hello USER!!!";

        }

    }

SecurityConfig.class

    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {


        @Autowired
        UserDetailsService userDetailsService;


        @Autowired
        public void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
        }


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

            http

                    .authorizeRequests()
                    .mvcMatchers("/").permitAll()
                    .mvcMatchers("/personal/**").hasAnyRole("ADMIN","USER")
                    .mvcMatchers("/login").anonymous()
                    .anyRequest()
                    .authenticated()

                    .and()
                    .formLogin()

                    .and()
                    .logout()
                    .logoutUrl("/logout")
                    .logoutSuccessUrl("/")
                    .deleteCookies("JSESSIONID")
                    .invalidateHttpSession(true);


        }


    }

RootConfig.class

    @EnableWebMvc
    @Configuration
    @ComponentScan("com.securede.security")
    @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
    public class RootConfig implements WebMvcConfigurer {

        @Bean
        public PasswordEncoder encoder() {
            return new BCryptPasswordEncoder();
        }
    }

UserDetail.class

    @Service
    public class UserDetail implements UserDetailsService {

        @Autowired
        PasswordEncoder passwordEncoder;


        @Override
        public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {

            return new org.springframework.security.core.userdetails.User(
                    "user",
                    passwordEncoder.encode("user"),
                    true,
                    true,
                    true,
                    true,
                    getAuthorities());
        }

        private Collection<? extends GrantedAuthority> getAuthorities(){

            List<SimpleGrantedAuthority> authList = new ArrayList<>();
            authList.add(new SimpleGrantedAuthority("ROLE_USER"));

            return authList;

        }

    }        

Upvotes: 1

Views: 1506

Answers (2)

eg04lt3r
eg04lt3r

Reputation: 2610

To achieve what you want, you can also use @PreAuthorization annotation as well on controller method level. Example:

@PreAuthorization("hasRole('ROLE_ADMIN')") 
@GetMapping(value = "/personal")
public ModelAndView personalGet () {..}

The Spring can not apply annotation based logic on the private methods.

Upvotes: 1

Tasos P.
Tasos P.

Reputation: 4114

When you call the secured method at

modelAndView.addObject("msg", myMsg());

you are actually calling the local method (as if you were calling this.myMsg()), completely bypassing annotation processing by Spring Security.

You can achieve your goal if you move the myMsg() method to the service layer (i.e. in UserDetailsService), inject it into your controller and then call the method:


@Controller
public class Personal {


    @Autowired
    UserDetailsService userDetailsService;

    @GetMapping(value = "/personal")
    public ModelAndView personalGet () {

        ModelAndView modelAndView = new ModelAndView("/personal");
        modelAndView.addObject("msg", userDetailsService.myMsg());
        return modelAndView;

    }

}

Upvotes: 4

Related Questions