2013-07-19 3 views
3

Spring Security предполагает, что аутентификация является Принципалом.Весенняя безопасность: почему аутентификация распространяется на Принципала?

public interface Authentication extends Principal, Serializable {} 

HttpServletRequest имеет метод getUserPrincipal, который отвечает за доступ к основному объекту.

Давайте рассмотрим этот случай:

public interface RealPrincipal extends Principal { 
    public Integer getId(); 
} 

Общего модуль А имеет вещественный главный интерфейс и реализацию.

Модуль A использует общий модуль A, Servlet Апи и не зависит от Spring Security:

Модуль B использует общий модуль A, Servlet Апи и настраивает Spring Security. Этот модуль отвечает за безопасность и реализацию UserDetails.

Web А использует модуль A и B. Модуль

Для того чтобы использовать методы запроса, я в конечном итоге с такой реализации:

public ModelAndView someRequestHandler(Principal principal) { 
    User activeUser = (User) ((Authentication) principal).getPrincipal(); 
    ... 
} 

Это вынуждает меня есть зависимость Spring Security для модуля А и других модулей. Я считаю, что правильная абстракция сервлета не должна зависеть от весенней безопасности. request.getUserPrincipal должен возвращать реальный главный.

Пожалуйста, объясните, почему org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper возвращает

аутентификации вместо Real Principal.

Редактировать: я добавил общий модуль A к моему сценарию и обновил, что модуль B отвечает за безопасность.

ответ

3

Как утверждает Люк, Spring Security использует аутентификацию для Принципала, потому что она реализует Принципала. Он не использует аутентификацию # getPrincipal(), поскольку он не гарантированно является Принципалом (это объект). Фактически, в большинстве случаев аутентификация Spring Security # getPrincipal() возвращает пользователя (не реализует Principal), пользовательские UserDetails, предоставляемые пользователями фреймворка, или String.

Если вы хотите, чтобы Spring Security справилась с этим, вам, скорее всего, понадобится реализовать эту логику с помощью HttpServletRequestWrapper, как предложил Люк.Например, вы можете сделать следующее:

public RealPrincipalFilter extends OncePerRequestFilter { 

    public void doFiter(HttpServletRequest request, HttpServletResponse response, FilterChain) { 
     chain.doFilter(new RealPrincipalRequestWrapper(request), response); 
    } 

    private static final class RealPrincipalRequestWrapper 
      extends HttpServletRequestWrapper { 
     public Principal getUserPrincipal() { 
      Authentication auth = (Authentication) super.getPrincipal(); 
      return auth == null ? null : (RealPrincipal) auth.getPrincipal() 
     } 
    } 
} 

@Configuration 
@EnableWebSecurity 
public WebSecurityConfig extends WebSecurityConfigurerAdapter { 
    public configure(HttpSecurity http) { 
     http 
      // ... other config ... 
      .addFilterAfter(new RealPrincipalFilter(), SecurityContextHolderAwareRequestFilter.class); 
    } 
    ... 
} 

С другой стороны, посмотрите на мой ответ на ваш другой вопрос для вариантов интеграции с Spring MVC - Injecting Custom Principal to Controllers by Spring Security

+0

Спасибо, Роб за отличные ответы. Теперь я понял, что Spring Security связана не только с веб-приложением, но и с автономными приложениями. Это означает, что Пользователь не должен быть Принципалом. И для того, чтобы соответствовать Http Api, аутентификация реализовала интерфейс Principal. Пока что так хорошо :) Вот мой вопрос: что, если пользователь Spring Security пользователь уже реализует интерфейс Principal? Это приводит к такой реализации, которая идеально подходит, я думаю: https://gist.github.com/cemo/6041868 что вы думаете? – Cemo

+0

Предлагаемое вами изменение будет не пассивным, поэтому в лучшем случае оно может быть включено в релиз 4.x. Я не думаю, что это прецедент, который нужен большинству, поэтому я не думаю, что он будет включен в 4.x. Это не означает, что у вас нет веских оснований для того, чтобы делать то, что вы делаете, но в качестве рамки нам нужно попытаться нацелиться на 90% -ные сокращения и иметь крючки для других случаев. –

1

Короткий ответ заключается в том, что Authentication является Principal, так что его можно использовать в API (например, упомянутый API-интерфейс сервлета), для которого требуется один.

Что это означает на практике? Не много. Интерфейс Java Principal имеет только один метод getName, поэтому, если вы хотите сделать больше, чем отображать имя пользователя, вам нужно знать что-то еще о реализации.

Возможно, вам стоит подумать о том, что вы имеете в виду, когда используете фразы «настоящий главный» и «правильная абстракция сервлета api». Как бы вы ожидали реализовать свой метод someRequestHandler, если, например, главный был «реальным»?

+0

Рассмотрим RealPrincipal в качестве подкласса принципала. Он имеет все необходимые методы, такие как имя пользователя, адрес электронной почты, пароль и т. Д. Я могу зависеть от него. Нет проблем. Но в зависимости от Spring Security это не приемлемое решение. Есть и другая проблема. Spring MVC вводит Principal с request.getUserPrincipal. Если я объявляю RealPrincipal как аргумент метода контроллера, он не может вставлять. Поскольку аутентификация не является RealPrincipal, а является Принципалом. Это вызывает ошибку. – Cemo

+0

и, пожалуйста, также см. Мой другой вопрос http://stackoverflow.com/questions/17741787/injecting-custom-principal-to-controllers-by-spring-security. – Cemo

+0

Что такое 'RealPrincipal' и откуда вы его ожидаете? то есть кто его предоставляет и как вы можете зависеть от него? –

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