Конечная точка Spring всегда возвращает 403 при проверке роли

Я интегрировал role и хочу управлять доступом к конкретной службе на основе роли. Администратор может создать АГЕНТ, и этот агент входит в группу пользователя ADMIN.

По сути, у меня возникла связь с 1 to Many, потому что у моего пользователя могла быть только 1 роль.

@Entity
@Table(name = "role")
public class Role {

    private Long id;
    private String name;
    private Collection<User> users;

    public Role() {
    }

    public Role(String name) {
        this.name = name;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @OneToMany(mappedBy = "role", cascade = CascadeType.ALL)
    public Collection<User> getUsers() {
        return users;
    }

    public void setUsers(Collection<User> users) {
        this.users = users;
    }
}

И здесь у меня есть пользователь, у которого отношение группы, а также группа, также 1 TO MANY, потому что user_admin может иметь несколько агентов, но агент не может иметь нескольких администраторов.

@Entity
@Table(name = "user")
public class User {
    private long id;
    private String username;
    private String password;
    private boolean enabled = false;
    private Role role;
    private UserGroup userGroup;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public User(String username, String password, Role role) {
        this.username = username;
        this.password = password;
        this.role = role;
    }

    public User(String username, String password, boolean enabled, Role role, UserGroup userGroup) {
        this.username = username;
        this.password = password;
        this.enabled = enabled;
        this.role = role;
        this.userGroup = userGroup;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    @NotBlank
    @Column(nullable = false, updatable = false, unique = true)
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @NotBlank
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


    @Column(nullable = false, updatable = true)
    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    @ManyToOne
    @JoinColumn(name = "role_id", referencedColumnName = "id")
    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }

    @ManyToOne
    @JoinColumn(name = "user_group_id", referencedColumnName = "id")
    public UserGroup getUserGroup() {
        return userGroup;
    }

    public void setUserGroup(UserGroup userGroup) {
        this.userGroup = userGroup;
    }
}

При создании пользователя я также указываю роль и группу.

А в SecurityConfig я настроил вот так.

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().and().csrf().disable().authorizeRequests()
            .antMatchers(Constants.BASE_URL_FILE_UPLOADER + Constants.URL_UPLOAD_FILE).hasRole("ADMIN")                                .anyRequest().authenticated()
            .and()
            .addFilter(new JWTAuthenticationFilter(authenticationManager()))
            .addFilter(new JWTAuthorizationFilter(authenticationManager()))
            // this disables session creation on Spring Security
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    http.exceptionHandling().authenticationEntryPoint(new ContentSearcherAuthenticationEntryPoint());
}

Но если я получаю доступ к этой конечной точке с пользователем-администратором, я бросаю запрещенный, а также в функции, когда я получаю доступ к authentication.getAuthorities()it return emptyList

ResponseEntity<JsonNode> uploadFile(@RequestParam("file") MultipartFile file, Authentication authentication) {
    logger.info("Authentication is [{}] and user is [{}]", authentication.getAuthorities(), authentication.getName()); // []
}

Я запутался в UserDetailsService, я также добавил GrantedAuthority, вот так.

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    private UserRepository userRepository;
    private RoleRepository roleRepository;

    public UserDetailsServiceImpl(UserRepository userRepository, RoleRepository roleRepository) {
        this.userRepository = userRepository;
        this.roleRepository = roleRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findUserByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(username + " Not Exists");
        }
        user.setEnabled(true);
        userRepository.save(user);
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), user.isEnabled(),
                true, true, true, getAuthorities(user.getRole()));
    }

    private Collection<? extends GrantedAuthority> getAuthorities(
            Role role) {

        List<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority(Constants.ROLE_PREFIX + role.getName()));

        return authorities;
    }
}

Что мне не хватает, есть ли еще конфигурация, которую я должен добавить?

Я использую JWT для аутентификации, что-то не должно быть добавлено и в это?

Потому что, когда я получаю Authentication в JWT successfulAuthentication, он показывает Authorities.

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
    logger.info("Auth in the successful is [{}]", authResult.getAuthorities()); // [ROLE_ADMIN]
}

Использование ядра Spring-Security 5.0.9.

У вас нет сопоставления между пользователем и ролью, поэтому Hibernate не знает, как получить коллекцию. Поместите аннотации OneToMany и ManyToOne в ваши отношения, и получение данных должно работать.

jprogramista 15.11.2018 08:37

У меня есть, позвольте мне обновить его и добавить полный код.

Root 15.11.2018 08:54

Как вы храните роли в базе данных? Когда вы говорите hasRole("ADMIN");, Spring ожидает, что роль в JWT будет ROLE_ADMIN.

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

Ответы 1

Ответ принят как подходящий

Я сделал это после того, как получил подсказку от вопроса @Reza Nasiri, в основном я не добавлял Authorities при аутентификации токена JWT, теперь то, что я сделал,

return new UsernamePasswordAuthenticationToken(user, null, getAuthorities("ADMIN");

В моей функции getAuthentication в классе JWTAuthorizationFilter.

JWTAuthorizationFilter

Root 06.12.2018 06:03

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

Похожие вопросы