Reputation: 41
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
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
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