Как изменить роль пользователя в CustomUserDetails?

Я написал свою реализацию 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;
    }
}

Можете ли вы показать таблицу счетов тоже

Sumit 15.10.2022 03:42
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
60
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

В случае, если у вас еще нет службы, которая хранила бы ваши объекты 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:/";
    }

Таким образом мне удалось добиться динамической смены ролей для пользователя. Если у вас есть какие-либо предложения по улучшению моего метода, я буду рад их услышать.

Другие вопросы по теме