Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> SpringSecurity custom authentication manager 
V
    Опции темы
check
Дата 14.12.2010, 21:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 610
Регистрация: 3.4.2006

Репутация: 2
Всего: 23



Цель - определить свой authentication manager. Ну и заставить его работать. Пишу в ...-security.xml следующее:

Код

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">

<http auto-config="true">
    <intercept-url pattern="/*.htm" access="ROLE_USER" />
    <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
</http>


<authentication-manager alias="authenticationManager" />
  
 
<beans:bean id="customizedFormLoginFilter" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter" >
<custom-filter position="AUTHENTICATION_PROCESSING_FILTER"/><!--replace the default one-->
<beans:property name="defaultTargetUrl" value="/hello.htm"/><!--After a successful login, the user will be taken to this page-->
<beans:property name="authenticationFailureUrl" value="/home.htm?error=true" /><!--Authentication failed? take him to error page-->
<beans:property name="authenticationManager" ref="myAuthenticationManager"/> <!--Here it is the custom authenticationManager, login magic goes here -->
<beans:property name="allowSessionCreation" value="true" /> <!--Allow the application to create sessions-->
</beans:bean>

<beans:bean id="myAuthenticationManager" class="springapp.security.SampleAuthenticationManager" />

<beans:bean id="loggerListener" class="org.springframework.security.event.authentication.LoggerListener"/>

<beans:bean id="myAuthenticationEntryPoint" class="springapp.security.CustomAuthenticationEntryPoint" >
<beans:property name="loginFormUrl" value="/home.htm"/>
</beans:bean>


</beans:beans>



Ошибка - No UserDetailsService registered.   Я так понимаю, что нужно ещё указать AuthenticationProvider, а в нём указать ссылку на authenticationManager и на UserDetailsService.
Никак не найду - как это правильно сделать в данном случае. 
PM MAIL   Вверх
MisterCleric
Дата 15.12.2010, 12:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



Привет.
Вот тебе пример как конфигурятся AuthenticationProvider и UserDetailsService:
Код

 <bean id="userCache" class="org.springframework.security.providers.dao.cache.EhCacheBasedUserCache">
        <property name="cache">
            <bean name="userCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
                  p:overflowToDisk="false"
                  p:diskPersistent="false"/>
        </property>
    </bean>

    <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
        <security:custom-authentication-provider/>
        <property name="userDetailsService" ref="myUserService"/>
        <property name="userCache" ref="userCache"/>
        <property name="saltSource">
            <bean class="org.springframework.security.providers.dao.salt.SystemWideSaltSource"
                  p:systemWideSalt="hash_key"/>
        </property>
        <property name="passwordEncoder">
            <bean class="org.springframework.security.providers.encoding.Md5PasswordEncoder"/>
        </property>
    </bean>

    <bean id="myUserService" class="com.my.pr.security.MyJdbcDaoImpl"
          p:dataSource-ref="dataSource"
          p:rolePrefix="ROLE_"
          p:usersByUsernameQuery="${users-by-username-query}"
          p:authoritiesByUsernameQuery="${authorities-by-username-query}"/>


И встречный вопрос: зачем тебе кастомный AuthenticationManager? По-умолчению используется org.springframework.security.providers.ProviderManager, который ищет в конфиге все бины, которые являются провайдерами. В моем примере такой бин помечен хинтом <security:custom-authentication-provider/>

Это сообщение отредактировал(а) MisterCleric - 15.12.2010, 12:06


--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
check
Дата 15.12.2010, 21:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 610
Регистрация: 3.4.2006

Репутация: 2
Всего: 23



Цитата(MisterCleric @  15.12.2010,  12:06 Найти цитируемый пост)
И встречный вопрос: зачем тебе кастомный AuthenticationManager? По-умолчению используется org.springframework.security.providers.ProviderManager, который ищет в конфиге все бины, которые являются провайдерами. В моем примере такой бин помечен хинтом <security:custom-authentication-provider/>
Собственно, кастомный AuthenticationManager, наверное, не нужен.
Я сейчас просто рассматриваю возможные варианты "кастомизации" SpringSecurity.  Прежде использовал org.springframework.security.userdetails.jdbc.JdbcDaoImpl, который делает всё сам.

Вот, наткнулся в интернете на пример кастомного AuthenticationManager-а,  но он у меня не совсем работает...

Но, как я понял, прямой путь - своя реализация UserDetailsService.  Так и делаю, в общем, работает.

У меня пока нет никакого datasource, есть один единственный пользователь petya))
Но у него есть пароль.

Вопрос: что мне нужно сделать, чтобы в методе loadUserByUsername проверялся не только логин, но и пароль?
Вот как сейчас выглядит мой UserDetailsService 

Код

public class MyUserDetailsService implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException, DataAccessException {
        User user = null;
        if (username.equals("petya")) {
            user = new User(username, username, true, true, true, true, getAuthorities(false));
        }
        return user;
    }
    
    private GrantedAuthority[] getAuthorities(boolean isAdmin) {
        List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2);
        authList.add(new GrantedAuthorityImpl("ROLE_USER"));
        if (isAdmin) {
            authList.add(new GrantedAuthorityImpl("ROLE_ADMIN"));
        }
        return authList.toArray(new GrantedAuthority[] {});
    }


PM MAIL   Вверх
MisterCleric
Дата 16.12.2010, 12:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



Привет. 
Вообще-то пароль проверяется в DaoAuthenticationProvider.additionalAuthenticationChecks...

Вообще там процесс получается такой:
1. При логине вызывается  AbstractUserDetailsAuthenticationProvider.authenticate
2. Он вызывает retrieveUser который делегируется в UserDetailsService.loadUserByUsername
3. В случае успеха вызывается additionalAuthenticationChecks, где уже и происходит сравнение введенного пароля с тем, который получили в юзере.


--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
check
Дата 16.12.2010, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 610
Регистрация: 3.4.2006

Репутация: 2
Всего: 23



В таком случае, мне нужен свой AuthenticationProvider. 
Пишу:
Код

public class MyDaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
    
    private UserDetailsService userDetailsService;
    
    private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();

    private SaltSource saltSource;
    

    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails,
            UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        Object salt = null;

        if (saltSource != null) {
          salt = saltSource.getSalt(userDetails);
        }

        if (!passwordEncoder.isPasswordValid(userDetails.getPassword(), authentication.getCredentials().toString(), salt)
             && !userDetails.getPassword().equals("123")) {
          throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials",
              "Bad credentials"), userDetails);
        }
    }

    @Override
    protected UserDetails retrieveUser(String username,
            UsernamePasswordAuthenticationToken authentication)throws AuthenticationException {
        UserDetails loadedUser;
        try {
            loadedUser = userDetailsService.loadUserByUsername(username);
          }
          catch (DataAccessException repositoryProblem) {
            throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
          }

          if (loadedUser == null) {
            throw new AuthenticationServiceException("AuthenticationDao returned null, which is an interface contract violation");
          }
          return loadedUser;
    }

}



В конфиге пытаюсь прописать AuthenticationProvider двумя способами:
Код

<beans:bean id="daoAuthenticationProvider" class="springapp.security.MyDaoAuthenticationProvider">
          <beans:property name="userDetailsService" ref="myUserService"/>
</beans:bean>


и 
Код

<beans:bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
   <beans:property name="userDetailsService" ref="myUserService"/>
</beans:bean>


Но в обоих случаях методы моего провайдера не вызываются.
PM MAIL   Вверх
MisterCleric
Дата 16.12.2010, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



А я же в своем примере обращал внимание на хинт:
Код

 <security:custom-authentication-provider/>



--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
check
Дата 16.12.2010, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 610
Регистрация: 3.4.2006

Репутация: 2
Всего: 23



Да, я так и подумал... У меня SpringSecurity 2.0.6.   Там префикс security не предусмотрен схемой.  У меня во всяком случае выдаётся SAXParseException.
Ищу аналог для своей версии, пока не нашёл.

PM MAIL   Вверх
MisterCleric
Дата 16.12.2010, 18:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



У тебя ж security: является namespace по-умолчанию


--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
check
Дата 16.12.2010, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 610
Регистрация: 3.4.2006

Репутация: 2
Всего: 23



Тем не менее эклипс подсвечивает эту строку как ошибку и пишет "The prefix "security" for element "security:custom-authentication-provider" is not bound."

То же самое пишется в иксепшене при попытке задеплоить приложение.


Вот такая схема используется
Код

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">

PM MAIL   Вверх
MisterCleric
Дата 17.12.2010, 00:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



Так убери этот префикс


--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
check
Дата 17.12.2010, 20:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 610
Регистрация: 3.4.2006

Репутация: 2
Всего: 23



А... Я даже и не думал, что его можно просто убрать))
Ну тогда всё работает. Спасибо!
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.0832 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.