Я написал свою реализацию UserDetails, чтобы изменить логин и роли пользователей. С логином все оказалось довольно просто, а вот с ролями у меня были проблемы. Я не понимаю, что мне нужно сделать, чтобы изменить роль КЛИЕНТА по умолчанию на другую роль ПРОДАВЦА
@ToString
public class CustomUserDetails implements UserDetails {
@ToString.Exclude
private Account account;
private final long serialVersionUID = 1L;
public CustomUserDetails(Account account) {
this.account = account;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_" + this.account.getRole().getAuthority()));
return authorities;
}
public void setRole(Role role) {
this.account.setRole(role);
}
@Override
public String getPassword() {
return this.account.getPassword();
}
@Override
public String getUsername() {
return this.account.getLogin();
}
public void setUsername(String username) {
this.account.setLogin(username);
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}




В случае, если у вас еще нет службы, которая хранила бы ваши объекты CustomUserDetails в БД:
Ваш CustomUserDetails.class должен иметь аннотацию @Entity , так как он должен храниться в виде таблицы в реляционной базе данных. Таким образом, у него должно быть поле id с аннотацией @Id. Следующий:
public interface CustomUserRepo extends
CrudRepository<CustomUserDetails, ID_TYPE> {
CustomUserDetails loadUserByArgThatYouWant (String ARG_THAT_YOU_WANT);
@Transactional
@Modifying
@Query("update CustomUserDetails c set c.role = ?1 where c.id = ?2")
void updatRoleById(String role, ID_TYPE);
}
public class UserService implements UserDetailsService {
@Autowired
private final CustomUserRepo repo;
@Override
CustomUserDetails loadUserByUsername (String arg) {
return repo.loadUserByArgThatYouWant(arg);
}
// down below method that you need
public void updateRoleById (String role, ID_TYPE id){
repo.updateRoleById(role,id);}
}
если вы хотите назначить роль, у вас может быть столбец в ролях базы данных, который вы можете указать во время отправки своих данных, и у вас может быть метод в вашем контроллере для его обновления.
**Сущность **
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private String roles;
//getter and setters
Возможно, я должен был быть более конкретным в своем вопросе. Но. Я нашел решение этой проблемы для себя. Может мой способ кому поможет.
Мой CustomUserDetailsService:
@Service("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private AccountRepository accountRepository;
@Override
public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
Account account = accountRepository.findByLogin(login);
if (account == null) {
throw new UsernameNotFoundException(login);
}
return new CustomUserDetails(account, mapRolesToAuthority(account.getRole()));
}
private Collection<? extends GrantedAuthority> mapRolesToAuthority(Role role) {
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getAuthority()));
authorities.add(new SimpleGrantedAuthority(role.getAuthority()));
return authorities;
}
}
Мои CustomUserDetails:
@ToString
public class CustomUserDetails implements UserDetails {
@ToString.Exclude
private Account account;
private Collection<? extends GrantedAuthority> authorities;
private final long serialVersionUID = 1L;
public CustomUserDetails(Account account, Collection<? extends GrantedAuthority> authorities) {
this.account = account;
this.authorities = authorities;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {
this.authorities = authorities;
}
@Override
public String getPassword() {
return this.account.getPassword();
}
@Override
public String getUsername() {
return this.account.getLogin();
}
public void setUsername(String username) {
this.account.setLogin(username);
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
Метод в контроллере, изменяющий данные в пользовательской сессии (требует рефакторинга):
@PostMapping("/trade")
public String updateAccountRole(Principal principal) {
Account account = accountRepository.findByLogin(principal.getName());
account.setRole(Role.SELLER);
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_" + account.getRole().getAuthority()));
authorities.add(new SimpleGrantedAuthority(account.getRole().getAuthority()));
userDetails.setAuthorities(authorities);
System.out.println("BEFORE -> " + SecurityContextHolder.getContext().getAuthentication());
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
SecurityContextHolder.getContext().getAuthentication().getPrincipal(),
SecurityContextHolder.getContext().getAuthentication().getCredentials(),
userDetails.getAuthorities()
);
token.setDetails(SecurityContextHolder.getContext().getAuthentication().getDetails());
SecurityContextHolder.getContext().setAuthentication(token);
System.out.println("AFTER -> " + SecurityContextHolder.getContext().getAuthentication());
accountRepository.save(account);
return "redirect:/";
}
Таким образом мне удалось добиться динамической смены ролей для пользователя. Если у вас есть какие-либо предложения по улучшению моего метода, я буду рад их услышать.
Можете ли вы показать таблицу счетов тоже