hi what i trying to achieve is to protect a url that only one role can access to it, when i try add .hasRole("USER"), still the other role can access it. Here is how i do it :
here is my controller :
@RestController
@RequestMapping("/couponapi")
public class CouponController {
@Autowired
CouponRepository couponRepository;
@PostMapping("/coupons")
public Coupon save(@RequestBody Coupon coupon) {
return couponRepository.save(coupon);
}
@GetMapping("/coupons/{code}")
public Coupon findByCode(@PathVariable("code") String code) {
return couponRepository.findByCode(code);
}
@GetMapping("/something")
public Coupon findByCodeX() {
return couponRepository.findByCode("SUPERSALE");
}
}
i want to protect @GetMapping("/something") only for ROLE_ADMIN, here is how my Spring Security Configuration looked like :
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailServiceImpl userDetailService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic();
http.authorizeRequests()
.antMatchers(HttpMethod.GET,"/couponapi/coupons/**").hasRole("USER")
.antMatchers(HttpMethod.POST,"/couponapi/coupons/**").hasRole("USER")
.antMatchers("/couponapi/something").hasRole("ADMIN")
.antMatchers("/**").authenticated()
.and().httpBasic().and().csrf().disable();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
here is my role class :
@Data
@EqualsAndHashCode(of = "id")
@ToString(of = { "id" })
@Entity
public class Roles implements GrantedAuthority {
private static final long serialVersionUID = -7314956574144971210L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany(mappedBy = "roles")
private Set<Users> users;
@Override
public String getAuthority() {
return null;
}
}
and here is my service that implements UserDetailsService class :
@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
Users users = userRepository.findByEmail(s);
if(users == null) {
throw new UsernameNotFoundException("Username Not Found");
}
return new User(users.getEmail(), users.getPassword(), users.getRoles());
}
}
and here is my database role data :

as you can see i have ROLE_USER and ROLE_ADMIN
and here is my joined database

** i just updated my question and i have answer of half of my issue, please read my answer below to see the latest issue
In spring security the most restrictive rules are defined first, therefore your configuration should look like this
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic();
http.authorizeRequests()
.antMatchers(HttpMethod.GET,"/**/something").hasRole("USER")
.antMatchers("/**").authenticated()
.and().httpBasic().and().csrf().disable();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With