wake-up-neo.net

Custom Authentication Manager mit Spring Security und Java-Konfiguration

Ich verwende Spring Security mit SpringMVC, um eine Webanwendung zu erstellen (ich werde dies zur Klarheit als WebApp bezeichnen), die auf eine vorhandene Anwendung verweist (ich bezeichne dies als BackendApp).

Ich möchte die Authentifizierungsaufgaben an die BackendApp delegieren (damit ich die beiden Anwendungen nicht synchronisieren muss). 

Um dies zu implementieren, möchte ich, dass die WebApp (Running Spring Security) über REST mit dem Benutzernamen und dem Kennwort, die vom Benutzer in einem Formular bereitgestellt werden, an die BackendApp kommuniziert und sich auf der Grundlage der Antwort der BackendApp-Antwort 200 OK oder 401 authentifiziert Nicht autorisiert.

Ich verstehe, dass ich einen benutzerdefinierten Authentication Manager schreiben muss, um dies zu tun. Ich bin jedoch noch nicht ganz im Frühling und kann keine Informationen zur Implementierung finden.

Ich glaube, ich muss so etwas tun:

public class CustomAuthenticationManager implements AuthenticationManager{

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        String username = authentication.getName();
        String pw       = authentication.getCredentials().toString();

        // Code to make rest call here and check for OK or Unauthorised.
        // What do I return?

    }

}

Setze ich authentication.setAuthenticated (true), wenn erfolgreich, und false, wenn dies nicht der Fall ist?

Wie konfiguriere ich die Frühjahrssicherheit für die Verwendung dieses Authentifizierungsmanagers unter Verwendung einer Java-Konfigurationsdatei?

Vielen Dank im Voraus für jegliche Hilfe.

20
Jeff I

Schauen Sie sich mein Beispiel unten an. Sie müssen ein UsernamePasswordAuthenticationToken zurückgeben. Es enthält den Principal und die GrantedAuthorities. Hoffe ich könnte helfen :)

public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    String username = authentication.getPrincipal() + "";
    String password = authentication.getCredentials() + "";

    User user = userRepo.findOne(username);
    if (user == null) {
        throw new BadCredentialsException("1000");
    }
    if (user.isDisabled()) {
        throw new DisabledException("1001");
    }
    if (!encoder.matches(password, user.getPassword())) {
        throw new BadCredentialsException("1000");
    }
    List<Right> userRights = rightRepo.getUserRights(username);
    return new UsernamePasswordAuthenticationToken(username, password, userRights.stream().map(x -> new SimpleGrantedAuthority(x.getName())).collect(Collectors.toList()));
}

PS: userRepo und rightRepo sind Spring-Data-JPA-Repositorys, die auf meine benutzerdefinierte Benutzer-DB zugreifen

SpringSecurity JavaConfig:

@Configuration
@EnableWebMvcSecurity
public class MySecurityConfiguration extends WebSecurityConfigurerAdapter {

public MySecurityConfiguration() {
    super(false);
}

@Override
protected AuthenticationManager authenticationManager() throws Exception {
    return new ProviderManager(Arrays.asList((AuthenticationProvider) new AuthProvider()));
}

}
30

In seiner einfachsten Form:

@Override
    public Authentication authenticate(Authentication auth) throws AuthenticationException {
        String username = auth.getName();
        String password = auth.getCredentials().toString();
        // to add more logic
        List<GrantedAuthority> grantedAuths = new ArrayList<>();
        grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
        return new UsernamePasswordAuthenticationToken(username, password, grantedAuths);
    }
5
mel3kings

Zuerst müssen Sie die Spring-Sicherheit konfigurieren, um Ihren benutzerdefinierten AuthenticationProvider .. zu verwenden. In Ihrer spring-security.xml-Datei (oder einer entsprechenden Konfigurationsdatei) müssen Sie definieren, welche Klasse diese Funktion implementiert. Zum Beispiel:

<authentication-manager alias="authenticationManager">
    <authentication-provider ref="myAuthenticationProvider" />
</authentication-manager>

<!-- Bean implementing AuthenticationProvider of Spring Security -->
<beans:bean id="myAuthenticationProvider" class="com.teimas.MyAutenticationProvider">
</beans:bean>

Zweitens müssen Sie AuthenticationProvider wie in Ihrem Beispiel implementieren. Speziell die Methode authenticate (Authentication authentication), in der Ihr Rest-Aufruf sein muss. Zum Beispiel:

public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    User user = null;
    try {
        //use a rest service to find the user. 
        //Spring security provides user login name in authentication.getPrincipal()
            user = userRestService.loadUserByUsername(authentication.getPrincipal().toString());
    } catch (Exception e) {
        log.error("Error loading user, not found: " + e.getMessage(), e);
    }

    if (user == null) {
        throw new UsernameNotFoundException(String.format("Invalid credentials", authentication.getPrincipal()));
    } else if (!user.isEnabled()) {
        throw new UsernameNotFoundException(String.format("Not found enabled user for username ", user.getUsername()));
    }
    //check user password stored in authentication.getCredentials() against stored password hash
    if (StringUtils.isBlank(authentication.getCredentials().toString())
        || !passwordEncoder.isPasswordValid(user.getPasswordHash(), authentication.getCredentials().toString()) {
        throw new BadCredentialsException("Invalid credentials");
    }

    //doLogin makes whatever is necesary when login is made (put info in session, load other data etc..)
    return doLogin(user);
} 
3
Ricardo Vila

Meine Lösung ist fast identisch mit der ersten Antwort:

1) Sie benötigen eine Klasse, die den Authentifizierungsanbieter implementiert

@Service
@Configurable
public class CustomAuthenticationProvider implements AuthenticationProvider    {
      @Override
      public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    // Your code of custom Authentication
}
}

2) Im Gegensatz zur ersten Antwort benötigen Sie not folgenden Code in Ihrer WebSecurityConfiguration, wenn Sie nur über diesen benutzerdefinierten Anbieter verfügen.

@Override
protected AuthenticationManager authenticationManager() throws Exception {
     return new ProviderManager(Arrays.asList((AuthenticationProvider) new  AuthProvider()));
}

Das Problem ist, dass Spring nach verfügbaren Providern sucht und den Standardwert verwendet, wenn nichts anderes gefunden wird. Da Sie jedoch die Implementierung des AuthenticationProviders haben, wird Ihre Implementierung verwendet. 

0
Andrew Gans