Я разработал REST API, где методы защищены с помощью SpringSecurity.
GITHUB LINK -> Проект
Работает, но не так, как ожидалось
SpringSecurity.config
---------------------------
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
private UserDetailsService userDetailService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailService).passwordEncoder(encode());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable();
http
.authorizeRequests()
.antMatchers("/user/**")
.authenticated()
.anyRequest()
.hasAnyRole("USER","ADMIN")
.and()
.authorizeRequests()
.antMatchers("/admin/**")
.authenticated()
.anyRequest()
.hasRole("ADMIN")
.and()
.formLogin()
.permitAll();
/*http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("USER","ADMIN")
.anyRequest()
.authenticated()
.and()
.formLogin()
.permitAll();*/
}
@Bean
public BCryptPasswordEncoder encode() {
return new BCryptPasswordEncoder();
}
}
AdminController
----------------------
@RestController
@RequestMapping("/admin")
public class AdminController {
@Autowired
private UserRepo userRepo;
@Autowired
private BCryptPasswordEncoder encoder;
@PostMapping("/add")
@PreAuthorize("hasRole('ADMIN')")
public String addUser(@RequestBody User user) {
String encodedPwd= encoder.encode(user.getPassword());
user.setPassword(encodedPwd);
userRepo.save(user);
return "user added sucessfully...";
}
@GetMapping("/demo")
@PreAuthorize("hasRole('ADMIN')")
public String getDemo() {
return "Hi";
}
}
CustomController
-------------------------
@RestController
@RequestMapping("/user")
public class CustomController {
@GetMapping("/access")
@PreAuthorize("hasAnyRole('USER','ADMIN')")
public String showUser() {
return "Url Security Provided";
}
}
CustomUserDetailService
-----------------------------
@Service
public class CustomUserDetailService implements UserDetailsService {
@Autowired
private UserRepo userRepo;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user= userRepo.findByUsername(username);
CustomUserDetails userDetails= null;
if(user!= null) {
userDetails= new CustomUserDetails();
userDetails.setUser(user);
}else {
throw new UsernameNotFoundException("User Not Found");
}
return userDetails;
}
}
CustomUserDetail
-----------------
@Getter
@Setter
public class CustomUserDetails implements UserDetails {
/**
*
*/
private static final long serialVersionUID = 1L;
private User user;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
/*return user.getRoles().stream()
.map(role->new SimpleGrantedAuthority("ROLE_"+ role))
.collect(Collectors.toList());*/
return user.getRoles().stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role))
.collect(Collectors.toList());
}
@Override
public String getPassword() {
// TODO Auto-generated method stub
return user.getPassword();
}
@Override
public String getUsername() {
// TODO Auto-generated method stub
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return true;
}
public CustomUserDetails() {
super();
// TODO Auto-generated constructor stub
}
}
Пользователь
----------
@Entity
@Getter
@Setter
@NoArgsConstructor
public class User {
@Id
@GenericGenerator(name="gen",strategy="increment")
@GeneratedValue(generator="gen")
private int user_id;
private String username;
private String password;
private String email;
@OneToMany(cascade= CascadeType.ALL, fetch= FetchType.EAGER)
@JoinTable(name="user_roles",
joinColumns= @JoinColumn(referencedColumnName= "user_id"),
inverseJoinColumns= @JoinColumn(referencedColumnName="role_id"))
private Set<Roles> roles;
}
Проблема в следующем:
С вышеупомянутой настройкой я могу получить доступ к URL, которые предназначены для пользователя, а не для ADMIN
Если я комментирую
http
/*.authorizeRequests()
.antMatchers("/user/**")
.authenticated()
.anyRequest()
.hasRole("USER")
.and()*/
.authorizeRequests()
.antMatchers("/admin/**")
.authenticated()
.anyRequest()
.hasRole("ADMIN")
.and()
.formLogin()
.permitAll();
Затем я могу получить доступ к URL для ADMIN , но мне не хватает аутентификации на URL для USER
Аналогичным образом, если я комментирую admin / , тогда можно получить доступ к части USER . Он ведет себя как Ordering, который когда-либо находится в первом URL, он признает это, а второй просто дает 403 в браузере, а не что-либо в консоли.
Это что-то вроде «Ордена», к которому первому можно получить доступ
Есть ли где-нибудь, что я делаю не так.
Если я не буду комментировать @EnableGlobalSecurity
, @PreAuthorize
, я не смогу получить доступ ни к одному из URL , которые предназначены для ADMIN и USER просто 403
, поэтому я не могу пропустить @EnableGlobalSecurity
, @PreAuthorize
, поскольку они предназначены для защиты методов REST API