Spring Boot: кому писать собственный префильтр, учитывая роль пользователя? - PullRequest
0 голосов
/ 08 октября 2018

Мне нужно что-то вроде @preFilter (или, если это невозможно, чем @postFilter), чтобы отфильтровать результаты моего REST API.Я не могу использовать аннотацию preFilter, потому что мне нужно учитывать роль пользователя.У меня есть три разные роли:

  • user обычный пользователь, который предоставляет доступ только к тем данным, которым он владеет

  • teamleader эта рольдолжен получить доступ ко всем данным своей команды

  • admin, которые могут получить доступ ко всем данным.

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

Фрагмент работает только для ролей user и admin.Для лидера команды это будет сложнее, тогда будет набор masterDataId, который должен быть связан с or.

Вот некоторый псевдокод, надеюсь, его не смущает:

public class RoleFilter {

    DimensionAttributeValueRepository dimensionAttributeValueRepository;


    public void doFilter(Collection<AllDatas> data) {
        if (user.getRole() != "admin") {
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();

            DimensionAttributeValue tmpValue = dimensionAttributeValueRepository.findByChrValue(auth.getUsername());

            MasterData masterData = tmpValue.getMasterData();

            data.filter(data.masterDataId == masterData.getMasterDataID());
        }
    }
}

Обновление: пример

Допустим, у меня есть два пользователяПользователь A - это обычный пользователь с ролью «пользователь».Пользователь B является администратором с ролью «admin».

Существует таблица базы данных, в которой хранятся userData.Таблица выглядит следующим образом.

| ID | username | name | email |

Они оба отправляют простой аутентифицированный GET запрос на /userData.

Теперь мой бэкэнд обнаруживает на основев заголовке authentication пользователей и добавьте роли.

В зависимости от роли, пользователь A должен получить только ответ, содержащий его личные данные, пользователь B должен получить все доступные данные, хотя /userData.

Ответ для пользователя A:

{
   "res":[
      {
         "id":1,
         "username":"userA",
         "name":"A",
         "email":"userA@mail.com"
      }
   ]
}

Ответ для пользователя B:

{
   "res":[
      {
         "id":1,
         "username":"userA",
         "name":"A",
         "email":"userA@mail.com"
      },
      {
         "id":2,
         "username":"userB",
         "name":"B",
         "email":"userB@mail.com"
      },
      {
         "id":3,
         "username":"userC",
         "name":"C",
         "email":"userC@mail.com"
      }
   ]
}

1 Ответ

0 голосов
/ 08 октября 2018

В вашем случае я бы порекомендовал использовать пользовательский фильтр и интегрировать его в цепочку фильтров spring-security. Здесь - учебник, объясняющий его в целом.Вы можете настроить свой собственный фильтр так, чтобы он проверял ваши сложные роли в базе данных, а затем перезаписывал текущий объект аутентификации пользователей новым.

Пример реализации:

public class CustomFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
    throws IOException, ServletException {
            // HERE GOES YOUR CODE

            // Depending on the extracted authentication details of the current user, you can now overwrite the users GrantedAuthorities

            Collection<SimpleGrantedAuthority> oldAuthorities = (Collection<SimpleGrantedAuthority>)SecurityContextHolder.getContext().getAuthentication().getAuthorities();
            SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_TEAMLEADER");
            List<SimpleGrantedAuthority> updatedAuthorities = new ArrayList<SimpleGrantedAuthority>();
            updatedAuthorities.add(authority);
            updatedAuthorities.addAll(oldAuthorities);

            SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(     
                SecurityContextHolder.getContext().getAuthentication().getPrincipal(),      
                SecurityContextHolder.getContext().getAuthentication().getCredentials(),
                updatedAuthorities));

            chain.doFilter(request, response);
    }
}

После этого вы можете проверить свои роли с помощью этого оператора: @PreAuthorize("hasRole('ROLE_TEAMLEADER')")

Затем вы можете просто получить доступ к ролям пользователей с помощью объекта spring-security-context: SecurityContextHolder.getContext().getAuthentication().getAuthorities()

На основании его результатов вы теперь можете настроить свой ответ на роли, которые хранятся в этом объекте.Например, вы можете реализовать RestCall на /userData следующим образом:

@GetMapping("/userData")
public List<Object> getUserData() {
  List<SimpleGrantedAuthority> roles = (List<SimpleGrantedAuthority>) SecurityContextHolder.getContext().getAuthentication().getAuthorities();
  SimpleGrantedAuthority authorityTeamLeader = new SimpleGrantedAuthority("ROLE_TEAMLEADER");

  List<Object> result = new ArrayList<>();

  if (roles.contains(authorityTeamLeader)) {
    result = getAllUsers();
  } else {
    result = getPersonalUser(roles);
  }

  return result;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...