Определение доступных переменных контроллера из фильтров в Grails - PullRequest
4 голосов
/ 30 января 2009

Я пишу небольшое веб-приложение на Grails и для проверки подлинности всех пользователей использую следующий фильтр:

class LoginFilters {
  static filters = {
    loginCheck(controller:'*', action:'*') {
      before = {
        if (session.user_id) {
          request.user = User.get(session.user_id)
        } else if (!actionName.equals("login")) {
          redirect(controller: "login", action: "login")
          return false
        }
      }
    }
  }
}

И все методы контроллера начинаются с чтения пользовательского свойства объекта запроса:

def actionName = {
   def user = request.user
   ...
}

Приведенный выше код работает, но я бы предпочел избегать дублирования кода во всех методах контроллера. Может ли фильтр привязать объект пользователя к переменной с именем «user» вместо «request.user», которая будет доступна для всех контроллеров?

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

Ответы [ 3 ]

1 голос
/ 08 декабря 2010

Я думаю, что вообще не рекомендуется вставлять объект пользователя в объект запроса каждый раз:

Срок действия запроса очень короткий, поэтому вам может понадобиться совершать циклические обходы кэш-памяти или, что еще хуже, к базе данных при каждом http-запросе для получения объекта, который вам может даже не понадобиться и который впоследствии будет удален без необходимости. Поэтому, если необходимо, лучше хранить весь объект в сеансе, а не только идентификатор.

Как правило, я бы предложил вам написать AuthenticationService с методом isLoggedIn(), который возвращает true при аутентификации пользователя, и методом getLoggedInUser(), который возвращает этот объект.

class AuthenticationService {
    def transactional = false
    boolean isLoggedIn() { return session.user_id }
    def getLoggedInUser() { return User.get(session.user_id) }
}

Затем вы используете Фильтр для перенаправления, если не аутентифицирован, и, возможно, Перехватчик для хранения локальной ссылки user = authenticationService.loggedInUser. Но я также не думаю, что это лучший путь. Я предлагаю вам создать абстрактный AuthenticationAwareController в качестве базового класса для всех ваших контроллеров в src / groovy, и там есть удобный метод, такой как user

class AuthenticationAwareController {
    def authenticationService
    def getUser() { return authenticationService.loggedInUser() }
}

Таким образом, позже вы можете изменить свое решение о сохранении пользователя так, как вам нравится, и вам не нужно менять код. Кроме того, вы получаете выгоду от кэшей в Hibernate, которые совместно используют уже извлеченные экземпляры пользовательских объектов между различными сеансами, поэтому обходные пути db исключаются.

Вы все равно должны проверить полученный объект пользователя на действительность или бросить AuthenticationException в случае, если поиск не удастся. (Может быть что-то вроде AuthenticationService.getLoggedInUser(failOnError = false).)

Вы можете даже сделать этот Service / ControllerBase небольшим плагином для повторного использования в каждом приложении или напрямую с помощью плагина безопасности Spring ...; -)

1 голос
/ 31 января 2009

Использование beforeInterceptor в контроллере может помочь:

class LoginController {

    def user

    def beforeInterceptor = {
        user = request.user
    }

    def index = { 
        render text:"index: ${user}"        
    }

    def test = {
        render text:"test: ${user}"         
    }
}
0 голосов
/ 01 февраля 2009

Я думаю, вы можете сделать это, но стоит ли это того? Мне кажется, ваше единственное преимущество - это печатать «user» вместо «request.user». Не большой выигрыш. В любом случае, я думаю, вы могли бы следовать инструкциям в «12.7 Добавление динамических методов во время выполнения» Руководства пользователя. Я думаю, что если вы создали динамический метод "getUser () {return request.user}", то доступ к получателю / установщику Groovy JavaBeans позволит вам просто ссылаться на "пользователя" так, как вы хотите.

Если вы добавите динамический метод, вы можете пропустить фильтр и сделать все это в динамическом методе.

...