Welcome to MLink Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
199 views
in Technique[技术] by (71.8m points)

java - How to use hasRole in Spring Security properly?

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 :

enter image description here

as you can see i have ROLE_USER and ROLE_ADMIN

and here is my joined database

enter image description here

** i just updated my question and i have answer of half of my issue, please read my answer below to see the latest issue


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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();
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to MLink Developer Q&A Community for programmer and developer-Open, Learning and Share
...