Spring-security / Grails app - пользовательские конфигурации WebSecurity не вызывают - PullRequest
0 голосов
/ 08 февраля 2019

Мой проект основан на плагинах Grail 2.5.6 и Spring.Я пытаюсь создать собственного провайдера аутентификации, фильтр и токен, расширяющий их соответствующие базовые классы.

this.getAuthenticationManager().authenticate(authRequest)

В моем фильтре менеджер аутентификации всегда пуст.Таким образом, он не может вызвать authenticate () для нулевого объекта.Когда я выполняю отладку на устройстве authenticationManager, в нем перечислены имена других поставщиков, кроме моего собственного.

Вот мой пользовательский конфиг веб-безопасности

@Configuration
@EnableGlobalMethodSecurity(securedEnabled=true)
public class CustomWebSecurityConfig extends WebSecurityConfigurerAdapter {

OrbisAuthenticationProvider orbisAuthenticationProvider

public CustomWebSecurityConfig() {
    super()

    log.debug "configure custom security"
    print("configure custom security")
}

@Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    print("configure method 1")
    log.debug "configure method 1"
    auth.authenticationProvider(orbisAuthenticationProvider)
}

@Bean(name= BeanIds.AUTHENTICATION_MANAGER)
@Override
AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean()
}

@Bean
OrbisAuthenticationFilter orbisAuthenticationProvider() throws Exception {
    log.debug "orbis Authentication provider"
    OrbisAuthenticationProvider orbisAuthenticationProvider = new OrbisAuthenticationProvider(authenticationManagerBean())
    return orbisAuthenticationProvider
}

@Bean
@Autowired
public OrbisAuthenticationFilter orbisAuthenticationFilter() throws Exception {

    print("configure orbis filtr")

    OrbisAuthenticationFilter oaf = new OrbisAuthenticationFilter()
    oaf.setAuthenticationManager(authenticationManagerBean())
    oaf.setFilterProcessesUrl("j_orbis_security_check")
    oaf.setUsernameParameter("email")
    oaf.setPasswordParameter("password")

    oaf.setAuthenticationSuccessHandler(new SavedRequestAwareAuthenticationSuccessHandler()
            .setDefaultTargetUrl("/oauth/authorize"))

    oaf.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler()
            .setDefaultFailureUrl("/loginWithOrbis"))

    oaf.afterPropertiesSet()

    return oaf
}

}

При отладке не похоже, что какой-либо из этих методов вызывается.Аннотации не кажутся достаточными, чтобы их можно было взять.Я тоже пробовал @ComponentScan.

Нужно ли где-нибудь вводить эту конфигурацию безопасности?Как сделать так, чтобы authManager был доступен в моем фильтре?

OrbisAuthFilter

class OrbisAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

//    @Autowired
OrbisAuthenticationProvider orbisAuthenticationProvider

OrbisAuthenticationFilter() {
    super("/j_orbis_security_check")

    orbisAuthenticationProvider = new OrbisAuthenticationProvider()

}

void afterPropertiesSet() {
    assert authenticationManager != null, 'authenticationManager must be specified'
}

@Override
Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
    String username = request.getParameter("email")
    String password = request.getParameter("password")
    String accessCode = request.getParameter("accessCode")
    OrbisAuthenticationToken authRequestForAuthentication = new OrbisAuthenticationToken(username, password, accessCode)

    // This throws error because getAuthenticationManager returns null
    // authRequestForAuthentication = this.getAuthenticationManager.authenticate(authRequestForAuthentication)

    //This works if I instantiate the orbis provider object in the constructor
    authRequestForAuthentication = this.orbisAuthenticationProvider.authenticate(authRequestForAuthentication)

    SecurityContextHolder.getContext().setAuthentication(authRequestForAuthentication)
    return authRequestForAuthentication
}

protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
    authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
}

@Override
@Autowired
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
    super.setAuthenticationManager(authenticationManager);
    }
}

OrbisAuthProvider

class OrbisAuthenticationProvider implements AuthenticationProvider {

@Override
Authentication authenticate(Authentication authentication) throws AuthenticationException {

    OrbisAuthenticationToken orbisAuth = (OrbisAuthenticationToken) authentication

    String username = orbisAuth.principal
    String password = orbisAuth.credentials
    String orbisAccessCode = orbisAuth.orbisAccessCode
    def urlToUse = 'https://coopstatus.neu.edu/sail_api/full.aspx?' + 'ac=' + orbisAccessCode + '&e='+ username + '&p=' + password
    HttpClient httpClient = DefaultHttpClient.newInstance()
    HttpGet getRequest = new HttpGet(urlToUse)
    HttpResponse httpResponse = httpClient.execute(getRequest)

    JSONObject orbisResponse = new JSONObject(httpResponse.getEntity().getContent().getText())

//        if(orbisResponse.get("IsFound")) {
//            //Return error not authenticated
//        }

    Collection<GrantedAuthority> orbisUserGrantedAuthorities = getLDAPUserAuthorities(orbisResponse.get("Email"))
    orbisAuth = new OrbisAuthenticationToken(username, password, orbisAccessCode, orbisUserGrantedAuthorities)

    return orbisAuth
}

private Collection<GrantedAuthority> getLDAPUserAuthorities(String username) {
    LDAPUserDetails currentLdapUserDetails
    try {
        currentLdapUserDetails = new LDAPUserDetailsService().loadUserByOrbisUsername(username)
        log.debug currentLdapUserDetails
    } catch(org.springframework.security.core.userdetails.UsernameNotFoundException e) {
        log.error("User " + username + " not found in ldap", e)
    }

    Collection<GrantedAuthority> authorities = new ArrayList<>()
    for (String authority : currentLdapUserDetails.authorities) {
        authorities.add(new SimpleGrantedAuthority(authority))
    }

    return authorities
}

@Override
public boolean supports(Class<?> authentication) {
    return (OrbisAuthenticationToken.class
            .isAssignableFrom(authentication));
}
}

Resources.groovy

import edu.neu.security.OrbisAuthenticationFilter
import edu.neu.security.OrbisAuthenticationProvider
beans = {
    userDetailsService(edu.neu.security.LDAPUserDetailsService)

    orbisAuthenticationProvider(OrbisAuthenticationProvider)

    orbisAuthenticationFilter(OrbisAuthenticationFilter) {
        orbisAuthenticationProvider = ref("orbisAuthenticationProvider")
        requiresAuthenticationRequestMatcher = ref('filterProcessUrlRequestMatcher')
    // This throws error during startup. Unable to init bean 
    // authenicationManager = ref("authenicationManager")
}

    myOAuth2ProviderFilter(OAuth2ProviderFilters) {
      //grailsApplication = ref('grailsApplication')
      // properties
    }
}

Я придерживался некоторых концепций этого проекта: https://github.com/ppazos/cabolabs-ehrserver/

Даже если весь процесс выполняется и securityContext установлен с authenticated, когда я нажимаю oauth / authorize для получения Authorization_Code, он перенаправляет обратно на '/ login/ авт.Он до сих пор не знает, что пользователь уже аутентифицирован.

1 Ответ

0 голосов
/ 09 февраля 2019

Когда вы добавляете провайдера аутентификации в bean-компонент AuthenticationManagerBuilder (который приходит от AuthenticationConfiguration), объявленный вами bean-компонент аутентификации не используется.

Try:

@Configuration
@EnableGlobalMethodSecurity(securedEnabled=true)
public class CustomWebSecurityConfig {

    OrbisAuthenticationProvider lwoAuthProvider;

    public CustomWebSecurityConfig() {
        //
    }


    @Bean(name= BeanIds.AUTHENTICATION_MANAGER)
    AuthenticationManager authenticationManagerBean() throws Exception {
        return new ProviderManager(Arrays.asList(lwoAuthProvider));

}

YourBean-компонент AuthenticationManager должен быть поднят и будет использоваться для обеспечения безопасности метода.Вы также можете @Autowire указать его в своем фильтре, если он управляется Spring, или @Autowire указать его в классе @Configuration, который создает экземпляр вашего фильтра.

ПРИМЕЧАНИЕ: приведенный выше класс НЕ БУДЕТ создать любой из фильтров Spring Security.(Цепочка фильтров все равно не создавалась - вы не аннотировали свой класс с помощью @EnableWebSecurity)

...