6

Основная информация и информация о данных в моем API связаны с проектом (Entity), Что такое хороший подход для потока паролей: управлять определенным разрешением, связанным с проектом, с весенняя безопасность и OAuth2?Oauth2/Разрешение пароля для проверки подлинности для определенного объекта

В этом приложении вы имеете 5 микро обслуживание:

  • UAA microservice: сервер авторизации
  • Каталог microservice
  • Заказать microservice
  • microservice Счет
  • microservice Клиент

Увеличить разрешение:

UUAMICROSERVICE

Каждый пользователь может иметь много проекта, и может иметь разрешение для каждого проекта:

  • CAN_MANAGE_CATALOG
  • CAN_VIEW_CATALOG
  • CAN_MANAGE_ORDER
  • CAN_VIEW_ORDER
  • CAN_MANAGE_INVOICE
  • CAN_VIEW_INVOICE
  • ...

У меня есть много идеи, но я не уверен, если у меня есть хороший подход:

использование: Я хочу securise конечной точки:

http://catalog-service/{project_key}/catalogs 

только пользователи, имеющие разрешение VIEW_CATALOG ИЛИ MANAGE_CATALOG для проекта {project_key} может список всех каталогов, присутствующий в проекте

Моя первая мысль: USE ProjectAccessExpression с предварительного блокирования средств на

CatalogController.java

@Controller 
public class CatalogController { 
    @PreAuthorize("@projectAccessExpression.hasPermission(#projectKey, 'manageCatalog', principal)" + 
     " or @projectAccessExpression.hasPermission(#projectKey, 'viewCatalog', principal)") 
    @RequestMapping(
      value = "/{projectKey}/catalogs", 
      method = RequestMethod.GET, 
      produces = MediaType.APPLICATION_JSON_VALUE 
    ) 
    public @ResponseBody List<Catalog> findByProject(@PathVariable("projectKey") String projectKey) { 
     return catalogService.find(); 
    } 
} 

ProjectAccessExpression.Java

@Component 
public class ProjectAccessExpression { 

     private RestTemplate restTemplate; 
     public boolean havePermission(String projectKey, String permission , String username) { 
      Boolean havePermission = restTemplate.getForObject(String.format("http://uaa-service/permission/check?project=%1&permission=%2&username=%3", 
        projectKey, permission, username 
        ), Boolean.class); 
      return havePermission; 
     } 
} 

Неудобство: это нужно вызвать UAA службу каждый раз

Вторая идея: USE USER_ROLE

С USER_ROLE

  • пользователя | роль
  • mylogin1 | SHOP1 .CAN_MANAGE_CATALOG
  • mylogin1 | SHOP1 .CAN_VIEW_CATALOG
  • mylogin1 | SHOP2 .CAN_MANAGE_CATALOG
  • mylogin1 | SHOP2 .CAN_VIEW_CATALOG
  • mylogin1 | SHOP2 .CAN_MANAGE_ORDER
  • mylogin1 | Shop2 .CAN_VIEW_ORDER
  • ...

SHOP1 является Shop2 является projectKey

Неудобства: я не уверен, но если разрешения изменения пользователя, мне нужно отменить все лексемы ассоциировать

Третья идея: добавить специальное разрешение при аутентификации blob

Я не знаю, как это сделать для хранения ...

И в контроллере аннотации:

@PreAuthorize("@ProjectAccessExpression.hasPermission(authentication, 'manageCatalog||viewCatalog', #projectKey) 

Неудобства: такой же неудобный второй идее

ответ

0

Этого решением я использую и работа штраф

** 1 - Загрузка бизнес-логики безопасности, когда пользователь знаком **

Этот пример найти пользователя с ролью упорствовать в базе данных, и добавить все в зависимости ролевого проекта. После операции у меня есть ключ аутентификации с GrantedAuthority: ROLE_USER, ROLE_MANAGE_CATALOG: project1, ROLE_VIEW_PROFILE: project1, ROLE_MANAGE_PROJECT: project2 ...

@Service 
public class CustomUserDetailsService implements UserDetailsService { 
@Override 
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
     Optional<User> user = userService.findByLogin(username); 

     if (!user.isPresent()) { 
      Object args[] = {username}; 
      throw new UsernameNotFoundException(
      messageSource.getMessage("user.notexist", args, "User {0} doesn't not exist", LocaleContextHolder.getLocale()) 
      ); 
     } 
     if (!user.get().isActivated()) { 
      //throw new UserNotActivatedException(String.format("User %s was not activated!", username)); 
      Object args[] = {username}; 
      throw new UserNotActivatedException(
        messageSource.getMessage("user.notactivated", args, "User {0} was not activated", LocaleContextHolder.getLocale())); 
     } 
     //Here implement your proper logic 
     //Add busness logic security Roles 
     // eg ROLE_MANAGE_PROJECT:{project_key}, ROLE_MANAGE_CATALOG:{project_key} 
     List<Role> bRoles = projectService.getRolesForUser(username) 
     user.get().getRoles().addAll(
      bRoles 
      ); 

     UserRepositoryUserDetails userDetails = new UserRepositoryUserDetails(user.get()); 
     return userDetails; 
    } 
} 

** 2 проверки безопасности с выражением предварительного блокирования средств **

В этот пример только пользователь, который имеет такое разрешение может сделать эту операцию:

  1. ROLE_ADMIN ИЛИ
  2. ROLE_MANAGE_PROJECT: {PROJ ectKey}

    @PreAuthorize ("@ oauthUserAccess.hasPermission (аутентификация, '" + Constants.PP_MANAGE_PROJECT +', #projectKey)") @RequestMapping ( значение = "/ проекты/{projectKey}", метод = RequestMethod.PUT, производит = MediaType.APPLICATION_JSON_VALUE ) общественного ResponseEntity updateProject (@PathVariable ("projectKey") Строка projectKey, @ Действительный проект @RequestBody Project)

класс OauthUserAccess:

@Component("oauthUserAccess") 
public class OauthUserAccess { 

    /** 
    * Check if it is the administrator of the application IMASTER 
    * @param authentication 
    * @param projectKey 
    * @return 
    */ 
    public boolean hasAdminPermission(OAuth2Authentication authentication, String projectKey) { 
     if(authentication.getOAuth2Request().getAuthorities().contains("ROLE_ADMIN")) return true; 
     return false; 
    } 
    /** 
    * 
    * @param authentication 
    * @param permissionType 
    * @param projectKey 
    * @return 
    */ 
    public boolean hasPermission(OAuth2Authentication authentication, String permissionType, String projectKey) { 
     if (!ProjectPermissionType.exist(permissionType) || 
       projectKey.isEmpty() || 
       !projectKey.matches(Constants.PROJECT_REGEX)) 
      return false; 
     if (authentication.isClientOnly()) { 
      //TODO check scope permission 
      if(authentication.getOAuth2Request().getScope().contains(permissionType+":"+projectKey)) return true; 
     } 
     if (hasAdminPermission(authentication, projectKey)) return true; 
     String projectPermission = "ROLE_" + permissionType + ":" + projectKey; 
     String projectPermissionManage = "ROLE_" + permissionType.replace("VIEW", "MANAGE") + ":" + projectKey; 
     String manageProject = "ROLE_" + Constants.PP_MANAGE_PROJECT + ":" + projectKey; 
     Predicate<GrantedAuthority> p = r -> r.getAuthority().equals(projectPermission) || r.getAuthority().equals(projectPermissionManage) || r.getAuthority().equals(manageProject); 

     if (authentication.getAuthorities().stream().anyMatch(p)) { 
      return true; 
     }; 
     return false; 
    } 

} 

3 - Преимущество/недостаток

Advantage

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

Неудобства

Необходимости обновление аутентификации маркер или отменить маркер при изменении разрешения еще при обновлении разрешения для пользователя, пользователя, необходимого для выхода из системы и Логина.Но у вас такая же проблема без этой логики безопасности, например, когда пользователь отключен или включен.

Мое решение я использовать, например, в контроллере:

newAuthorities = projectService.getRolesForUser(username); 
UsernamePasswordAuthenticationToken newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), newAuthorities); 
     OAuth2Authentication authentication = (OAuth2Authentication)SecurityContextHolder.getContext().getAuthentication(); 
     Collection<OAuth2AccessToken> accessTokens = tokenStore.findTokensByUserName(principal.getName()); 
     OAuth2Authentication auth2 = new OAuth2Authentication(authentication.getOAuth2Request(), newAuth); 

     accessTokens.forEach(token -> { 
      if (!token.isExpired()) { 
       tokenStore.storeAccessToken(token, auth2); 
      } 
     }); 
0

Это в основном выглядит как ваши просто пытается использовать роли с OAuth 2.0 для вашего проекта. Вот отрывок из какой-то весенним документации по OAuth 2.0

Mapping Роли пользователей в Скоупс:http://projects.spring.io/spring-security-oauth/docs/oauth2.html

Иногда полезно ограничить объем маркеров не только области, назначенных к клиенту, но и в соответствии с собственными разрешениями пользователя. Если вы используете DefaultOAuth2RequestFactory в своем AuthorizationEndpoint, вы можете установить флаг checkUserScopes = true, чтобы ограничить разрешенные области только теми, которые соответствуют ролям пользователя. Можно также вводить в OAuth2RequestFactory в TokenEndpoint, но это работает только (т.е. с грантами паролем), если вы также установить TokenEndpointAuthenticationFilter - вам просто нужно добавить, что фильтр после HTTP BasicAuthenticationFilter.Разумеется, вы также можете реализовать свои собственные правила для привязки областей к ролям и установить свою собственную версию OAuth2RequestFactory. AuthorizationServerEndpointsConfigurer позволяет ввести пользовательский OAuth2RequestFactory, чтобы вы могли использовать эту функцию для настройки фабрики, если используете @EnableAuthorizationServer.

Все это в основном сводится к тому, что вы можете защитить свои конечные точки различными областями, сопоставляя области с вашими собственными пользовательскими ролями. Это позволит вам получить очень тонкую защиту от вашей безопасности.

Я нашел очень хорошие проходные вы можете использовать в качестве ссылки: (Очевидно, что вы должны настроить параметры для вашего собственного прецеденту)

https://raymondhlee.wordpress.com/2014/12/21/implementing-oauth2-with-spring-security/

+0

Привет Мэтью, в первую очередь спасибо за ваш ответ, но я не знаю, как ваша ссылка или глава может помочь знать подход или решить эту проблему вопрос «сопоставление ролей пользователей с областями» https://raymondhlee.wordpress.com/2014/12/21/implementing-oauth2-with-spring-security/. У вас есть какой-нибудь прецедент? – timactive

+0

Настоящий трюк здесь - это то, что вы хотели бы получить высококачественную защиту по различным областям вашего приложения. Таким образом, вы можете настроить собственные области для каждой области приложения, а затем сопоставить разные роли пользователей в разных областях. Это даст вам очень тонкий контроль, поскольку вы можете настроить в основном бесконечные комбинации уровней и применить их к различным областям приложений. «реализовать свои собственные правила для отображения областей видимости для ролей» –

+0

Ok Matthew, я думаю, это всего лишь базовая схема, и этот пример не показывает, как динамически определять конкретную авторизацию по моей проблеме. Пример ROLE_MANAGEPRODUCT_ {PROJECTKEY}, ключ проекта создается после пользователя. – timactive

Смежные вопросы