Spring Security в сочетании с репозиториями Spring для защиты и аутентификации различных частей веб-сайта.

Я искал конкретный, серьезный и полный пример того, как использовать безопасность Spring в приложении Spring Boot, которое использует хранилища данных Spring для доступа к базе данных и, следовательно, для запросов о зарегистрированных пользователях.

Я видел, что он легко защищает ряд веб-страниц с помощью Spring Spring, переопределяя configure метод, например, со следующими параметрами:

http.authorizeRequests()
    .antMatchers("/", "/css/**", "/js/**", "/vendor/**", "/templates/**")
    .permitAll()
    .anyRequest()
    .authenticated()
    .and()
    .formLogin()
    .loginPage("/login")
    .permitAll()
    .and()
    .logout()
    .permitAll();

Этот код защищает пользователей, например, от доступа http://localhost:3000/home/users/, но позволяет затем получить доступ http://localhost:3000/login или просто http://localhost:3000,

Я много читал о безопасности Spring, но не могу понять, как я могу защитить различные части приложения, например, когда пользователь зашел на сайт и запретил ему доступ из примера http://localhost:3000/home/users/another_userи вообще контролировать доступ зарегистрированного пользователя ко всем частям сайта.

Я использую репозитории данных Spring, чтобы манипулировать данными базы данных через сущности.

Знаете ли вы о примере, который использует безопасность Spring в сочетании с репозиториями Spring (и, при необходимости, другими инструментами) для защиты (и аутентификации) различных частей веб-сайта? (Видео) учебник также может быть полезным.

Спасибо за любую помощь.

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

2 ответа

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

Смотрите раздел 15.3.

https://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html

Итак, предположим, что у вас есть URL /users/123, где 123 - текущий пользователь, и который делегирует методу сервисного уровня для загрузки пользователя, тогда как я могу предотвратить вмешательство пользователя в URL и просмотр данных, возвращаемых, например, /users/456?,

Один из подходов заключается в применении безопасности на уровне метода с помощью аннотации @PostAuthorize:

@PostAuthorize("hasPermission(returnObject, null)")
public User findById(Long id) {
    return repository.findOne(id);
}

Проверки безопасности делегируются реализации org.springframework.security.access.PermissionEvaluator.

Реализация может выглядеть следующим образом:

public class BasePermissionsEvaluator implements PermissionEvaluator {

    public boolean hasPermission(Authentication authentication, Object domainObject) {
        return hasPermission(authentication, domainObject, null);
    }

    @Override
    public boolean hasPermission(Authentication authentication, Object domainObject, Object permission) {
        boolean hasPermission = true;

        //User is my custom class representing a logged in user
        //UserEntity is my custom interface implemented by entities associated with specific user
        //If user is an Admin allow access
        //Otherwise allow access if logged in user 'owns' the DomainObject instance
        User user = (User) authentication.getPrincipal();

        if(! user.isAdmin()){
            if (domainObject instanceof UserEntity) {
                User owner = ((UserEntity) domainObject).getOwner();
                hasPermission = user.equals(owner);
            }
        }

        return hasPermission;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType,
            Object permission) {
        return false;
    }
}

Конфигурация PermissionEvaluator выглядит следующим образом в XML, поэтому вам необходимо преобразовать ее в конфигурацию Java:

<security:global-method-security
    pre-post-annotations="enabled">
        <security:expression-handler ref="expressionHandler"/>
</security:global-method-security>

<bean id="expressionHandler"
    class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
    <property name="permissionEvaluator" ref="permissionEvaluator" />
</bean>

<bean id="permissionEvaluator" class="com.mycompany.BasePermissionsEvaluator" />

Ниже приведены схемы преобразования конфигурации XML в конфигурацию Java:

https://spring.io/blog/2013/07/04/spring-security-java-config-preview-method-security/

Таким образом, в вашем существующем классе конфигурации безопасности вы должны добавить:

@EnableGlobalMethodSecurity(prePostEnabled=true) //ADD THIS
public class MySecurityConfig{

  @Override
  protected MethodSecurityExpressionHandler expressionHandler() {
    DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();

    //SET TO OUR CUSTOM PERMISSIONS HANDLER DETAILED ABOVE
    expressionHandler.setPermissionEvaluator(new BasePermissionsEvaluator());

    return expressionHandler;
  }
}

Это называется Контроль доступа или "Безопасность объекта домена" в Spring Security.

http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/

Вам нужно много читать!

Возможно, вы захотите объединить его с Spring Data JPA, чтобы SDJ возвращал только те записи, которые он должен. Пример здесь:

https://github.com/spring-projects/spring-data-examples/tree/master/jpa/security

По сути, вы будете добавлять в таблицы некоторую информацию о владельце строк и заставлять SDJ и SS работать вместе для контроля доступа, например:

@Query("select o from BusinessObject o where o.owner.emailAddress like ?#{hasRole('ROLE_ADMIN') ? '%' : principal.emailAddress}")
List<BusinessObject> findBusinessObjectsForCurrentUser();

Альтернативный вариант - использовать сервер базы данных, который поддерживает Row Security, такой как PostgreSQL, и обрабатывать управление доступом прямо в БД.

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