SecurityContextHolder возвращает ноль после того, как я вызываю setAuthentication с токеном аутентификации - PullRequest
0 голосов
/ 08 апреля 2020

У меня есть небольшой проект Spring Boot с аутентификацией по имени пользователя и паролю. Я использую вход в систему Spring-Security с нашим LDAP-соединением. Что я хочу, и мне удалось сделать в нескольких проектах, так это расширить класс AbstractAuthenticationToken, чтобы добавить свои собственные поля.

В моем собственном классе GenericFilterBean я хочу создать свой собственный объект аутентификации и установить в SecurityContextHolder , как показано ниже:

KfsMsgToken kfsMsgToken = new KfsMsgToken(
                    kfsInMessageInfo.getObjId(),
                    new ArrayList<>());

SecurityContextHolder.getContext().setAuthentication(kfsMsgToken);

И, Вот мой пользовательский Аутентификация класс:

public class KfsMsgToken extends AbstractAuthenticationToken {

    String kfsInMsgOid;

    public KfsMsgToken(String kfsInMsgOid, Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.kfsInMsgOid = kfsInMsgOid;
    }

    /**
     * 
     * @return
     */
    @Override
    public Object getCredentials() {
        return null;
    }

    /**
     * 
     * @return
     */
    @Override
    public Object getPrincipal() {
        return null;
    }

    public String getKfsInMsgOid() {
        return kfsInMsgOid;
    }

    public void setKfsInMsgOid(String kfsInMsgOid) {
        this.kfsInMsgOid = kfsInMsgOid;
    }

}

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

Все советы приветствуются!

Моя конфигурация безопасности:

@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Value("${ldap.urls}")
    private String ldapUrl;
    @Value("${ldap.domain}")
    private String ldapDomain;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/css/**", "/fonts/**", "/img/**", "/js/**", "/pdf/**").permitAll()
                .and().formLogin().defaultSuccessUrl("/index", true).loginProcessingUrl("/login").permitAll().and()
                .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .csrf().disable();
    }

    @Bean
    public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
        ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider = new
                ActiveDirectoryLdapAuthenticationProvider(ldapDomain, ldapUrl);

        return activeDirectoryLdapAuthenticationProvider;
    }
}

Как зарегистрировать мой фильтр:

    @Bean
    public FilterRegistrationBean jwtFilter() {
        final FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new KfsInMsgFilter(kfsInMessageService, kfsMsgToken, messageChannelService));

        registrationBean.setOrder(0);
        registrationBean.addUrlPatterns(SECURE);
        registrationBean.setDispatcherTypes(DispatcherType.REQUEST);

        return registrationBean;
    }

Вот что я делаю в своем фильтре:

public class KfsInMsgFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

       ...
            // at this point, Authentication holds UserNamePasswordAuthenticationToken
            KfsMsgToken kfsMsgToken = new KfsMsgToken(
                    kfsInMessageInfo.getObjId(),
                    new ArrayList<>());

            SecurityContextHolder.getContext().setAuthentication(kfsMsgToken);

       ...
    } 
}

Ответы [ 2 ]

0 голосов
/ 10 апреля 2020

Установка аутентифицированного поля поверх моего пользовательского токена,

kfsMsgToken.setAuthenticated(Boolean.TRUE.booleanValue());

решила мою проблему.

Но,

Я думаю, что есть лучший способ. Использование бобов в области видимости более эффективно и практично.

Я изменил свой пользовательский фильтр на bean-объект в области запроса:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
@Scope(value="request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class KfsMsgToken {
    String kfsInMsgOid;
}

С помощью автоматического подключения я могу получить и прочитать нужное значение.

0 голосов
/ 09 апреля 2020

Вам нужно расширить AbstractAuthenticationProcessingFilter, чтобы там была ваша собственная аутентификация LDAP, зарегистрироваться и, наконец, использовать

http.addFilterAfter(
          new CustomFilter(), UsernamePasswordAuthenticationProcessingFilter.class);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...