Spring Security в Grails, обеспечивающий авторизацию

Предложение здесь будет глубоко оценено.

Мы используем безопасность объекта домена Spring Security, чтобы заблокировать доступ к определенным объектам в нашем приложении Grails. У нас также есть расширенные разрешения. Мы используем обычную аннотацию @PreAuthorize для управления доступом к объектам домена в зависимости от привилегий, назначенных конкретному пользователю.

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

Учитывая, что объект домена принадлежит первому пользователю, а не второму пользователю, как я могу предоставить второму пользователю доступ к объекту домена с предлагаемыми привилегиями?

Я попытался взломать решение, используя @PreAuthorize("permitAll") в сервисном методе, просто чтобы посмотреть, сработает ли это. Хотя я и не спрашивал «secure» как предоставление объекту привилегии устанавливать привилегии для объекта домена, это, по крайней мере, заставило бы меня двигаться дальше. Но без радости, я продолжаю получать ошибки «accessDenied for class», предположительно потому, что текущий пользователь является вторым пользователем, а не владельцем объекта домена.

Нужно ли мне работать с предложением SpEL здесь? К сожалению, я едва понимаю, как работает распознаватель bean-компонентов.

Изменить: даже когда я проверяю, действительно ли приглашение при вызове, Spring ACL выдает исключение при попытке вставки первого ACE для нового пользователя. Исключение возникает в void setPermissions (идентификатор ObjectIdentity, получатель, разрешения на коллекцию) при вызове insertAce:

void setPermissions (идентификатор ObjectIdentity, получатель, разрешения на сбор) { Sid sid = createSid (получатель)

MutableAcl acl
try {
    acl = aclService.readAclById(oid)
}
catch (NotFoundException e) {
    acl = aclService.createAcl(oid)
}

int deleted = 0
acl.entries.eachWithIndex { AccessControlEntry ace, int i ->
    if (ace.sid == sid) {
        acl.deleteAce(i-deleted)
        deleted++
    }
}

permissions.each {
    acl.insertAce(acl.entries.size(), it, sid, true)
}

aclService.updateAcl acl

}

Я предполагаю, что в доступе отказано, потому что текущий пользователь (которого не существовало на момент выдачи приглашения) не имеет права устанавливать разрешения для объекта, принадлежащего другому пользователю.


person Mike T    schedule 21.08.2013    source источник
comment
Таким образом, @PreAuthorize на самом деле не авторизует все вплоть до ACL. Для доступа к объекту домена, защищенному ACL, требуется, чтобы текущий пользователь имел права доступа. Так что либо я полностью взломаю вставку ACE, либо разработаю, как предоставить разрешение в этом особом случае.   -  person Mike T    schedule 24.08.2013
comment
Могу ли я использовать замену аутентификации RunAs? Похоже, это сделает работу. static.springsource.org/spring-security/ сайт/документы/3.0.x/   -  person Mike T    schedule 26.08.2013
comment
Ну, это должно работать, но это не так. Я создал новую роль RUN_AS_INVITED_USER в БД, включил RUnAss с помощью grails.plugins.springsecurity.useRunAs = true, установил grails.plugins.springsecurity.acl.authority.changeAclDetails = 'ROLE_RUN_AS_INVITED_USER', а затем аннотировал метод с помощью @Secured(['ROLE_USER ', 'RUN_AS_INVITED_USER']), но радости все равно нет. Хуже того, когда я запрашиваю текущие роли в методе с помощью springSecurityService.getPrincipal().getAuthorities(), я не вижу свой новый набор ролей.   -  person Mike T    schedule 28.08.2013


Ответы (2)


Вы можете использовать свой класс Role не только для общих ролей (Admin,User и т. д.), но и для конкретных приложений. Просто позвольте пользователю создать Role для ресурса, а затем разрешите его приглашенным получить эту роль. Spring Security поставляется с удобным методом ifAnyGranted(), который принимает строку имен ролей с разделителями-запятыми. В точке входа ресурса просто убедитесь, что определенная роль предоставлена:

class Conversation{
     Role role
}
class ConversationController{
    def enterConversation(){
       // obtain conversation instance 
       if(!SpringSecurityUtils.ifAnyGranted(conversationInstance.role.authority){response.sendError(401)}
    }
}
person Anatoly    schedule 22.08.2013
comment
Спасибо, но я не уверен, что это то, что мне нужно. Хотя я могу убедиться, что объект (приглашение, поскольку пользователь еще не зарегистрирован в службе) в точке входа в ресурс, я обнаружил, что все еще получаю исключение при настройке разрешений ACL. - person Mike T; 22.08.2013
comment
Поскольку принятие приглашения — это событие, которое может произойти или не произойти в будущем, существует целый отдельный сценарий использования, который необходимо должным образом обработать вне цикла аутентификации. Вы можете взглянуть на плагин подтверждения электронной почты для примера реализации части подтверждения, которая включает в себя класс домена планирования, задание кварца для обработки тайм-аутов и использует API прослушивателя событий для реагирования на различные результаты сценария. В любом случае вам определенно нужен зарегистрированный пользователь, прежде чем назначать ему роль. Надеюсь, что поможет. - person Anatoly; 23.08.2013
comment
Проблема в том, что я не даю новому пользователю роль, я даю новому пользователю доступ к объекту домена. - person Mike T; 24.08.2013

Ответ оказался с помощью RunAs. Для Grails я сделал это следующим образом:

  1. Создайте специальную роль, позволяющую приглашенным пользователям действовать в качестве администратора для доступа к защищенному объекту. В Bootstrap убедитесь, что эта роль загружена в домен SecRole:

    def inventoryRole = SecRole.findByAuthority('ROLE_RUN_AS_INVITED_USER') if (!invitedRole) { приглашаемыйRole = new SecRole() приглашаемыйRole.authority = "ROLE_RUN_AS_INVITED_USER" приглашаемыйRole.save(failOnError:true, flush:true) }

  2. Убедитесь в config.groovy, что роль может изменить цель object:grails.plugins.springsecurity.acl.authority.changeAclDetails = 'ROLE_RUN_AS_INVITED_USER'

  3. Включить запуск от имени в config.groovy

    grails.plugins.springsecurity.useRunAs = true grails.plugins.springsecurity.runAs.key = [ключ]

  4. аннотировать метод службы

@PreAuthorize([проверьте, что это действительно приглашенный пользователь]) @Secured(['ROLE_USER', 'RUN_AS_INVITED_USER'])

и все работает. Хитрость заключалась в том, чтобы ROLE_RUN_AS_INVITED_USER мог изменять ACL.

Ссылка: http://static.springsource.org/spring-security/site/docs/3.0.x/reference/runas.html http://grails-plugins.github.io/grails-spring-security-acl/docs/manual/guide/2.%20Usage.html#2.5%20Run-As%20Authentication%20Replacement

person Mike T    schedule 04.09.2013