Nach dem Anmelden mit Spring Security auf andere Seiten umleiten

Nach der Anmeldung mit Spring Security auf andere Seiten umleiten

1. Überblick

Eine häufige Anforderung für eine Webanwendung istredirect different types of users to different pages after login. Ein Beispiel hierfür wäre beispielsweise die Umleitung von Standardbenutzern auf eine/homepage.html-Seite und von Administratorbenutzern auf eine/console.html-Seite.

Dieser Artikel zeigt, wie Sie diesen Mechanismus mit Spring Security schnell und sicher implementieren können. Der Artikel baut auch auf denSpring MVC tutorial auf, die sich mit dem Einrichten des für das Projekt erforderlichen MVC-Kernmaterials befassen.

2. Die Spring-Sicherheitskonfiguration

Spring Security bietet eine Komponente, die direkt dafür verantwortlich ist, zu entscheiden, was nach einer erfolgreichen Authentifizierung zu tun ist - dieAuthenticationSuccessHandler.

Mal sehen, wie wir dies in einer@Configuration-Klasse konfigurieren können:

@Configuration
@EnableWebSecurity
public class SecSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean("authenticationManager")
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        // @formatter:off
        auth.inMemoryAuthentication()
            .withUser("user1").password("{noop}user1Pass").roles("USER")
            .and()
            .withUser("admin1").password("{noop}admin1Pass").roles("ADMIN");
        // @formatter:on
    }

    @Bean
    public AuthenticationSuccessHandler myAuthenticationSuccessHandler(){
        return new MySimpleUrlAuthenticationSuccessHandler();
    }

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/anonymous*").anonymous()
            .antMatchers("/login*").permitAll()
            .anyRequest().authenticated()

            .and()
            .formLogin()
            .loginPage("/login.html")
            .loginProcessingUrl("/login")
            .successHandler(myAuthenticationSuccessHandler())
            // ...
    }
}

Die Teile dieser Konfiguration, auf die man sich konzentrieren muss, sind die Definitionen von the custom authentication success handler bean and using the successHandler() method to add the bean to the security configuration.

Der Rest der Konfiguration ist ziemlich Standard: Ein einzelnes, einfacheshttp-Element, das alles sichert und nur nicht authentifizierten Zugriff auf/login* ermöglicht, und der Standard-In-Memory-Authentifizierungsanbieter, um die Dinge einfach zu halten.

Und die äquivalente XML-Konfiguration:


    
    

    
    





    
        
            
            
        
    

3. Der benutzerdefinierte Authentifizierungserfolgshandler

Neben derAuthenticationSuccessHandler-Schnittstelle bietet Spring auch einen sinnvollen Standard für diese Strategiekomponente - dieAbstractAuthenticationTargetUrlRequestHandler und eine einfache Implementierung - dieSimpleUrlAuthenticationSuccessHandler. In der Regel ermitteln diese Implementierungen die URL nach der Anmeldung und leiten sie zu dieser URL weiter.

Der Mechanismus zum Ermitteln dieser Ziel-URL ist zwar etwas flexibel, ermöglicht jedoch keine programmgesteuerte Ermittlung. Daher werden wir die Schnittstelle implementieren und eine benutzerdefinierte Implementierung des Erfolgshandlers bereitstellen. This implementation is going to determine the URL to redirect the user to after login based on the role of the user:

public class MySimpleUrlAuthenticationSuccessHandler
  implements AuthenticationSuccessHandler {

    protected Log logger = LogFactory.getLog(this.getClass());

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
      HttpServletResponse response, Authentication authentication)
      throws IOException {

        handle(request, response, authentication);
        clearAuthenticationAttributes(request);
    }

    protected void handle(HttpServletRequest request,
      HttpServletResponse response, Authentication authentication)
      throws IOException {

        String targetUrl = determineTargetUrl(authentication);

        if (response.isCommitted()) {
            logger.debug(
              "Response has already been committed. Unable to redirect to "
              + targetUrl);
            return;
        }

        redirectStrategy.sendRedirect(request, response, targetUrl);
    }

    protected String determineTargetUrl(Authentication authentication) {
        boolean isUser = false;
        boolean isAdmin = false;
        Collection authorities
         = authentication.getAuthorities();
        for (GrantedAuthority grantedAuthority : authorities) {
            if (grantedAuthority.getAuthority().equals("ROLE_USER")) {
                isUser = true;
                break;
            } else if (grantedAuthority.getAuthority().equals("ROLE_ADMIN")) {
                isAdmin = true;
                break;
            }
        }

        if (isUser) {
            return "/homepage.html";
        } else if (isAdmin) {
            return "/console.html";
        } else {
            throw new IllegalStateException();
        }
    }

    protected void clearAuthenticationAttributes(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session == null) {
            return;
        }
        session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
    }

    public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
        this.redirectStrategy = redirectStrategy;
    }
    protected RedirectStrategy getRedirectStrategy() {
        return redirectStrategy;
    }
}

DiedetermineTargetUrl - das ist der Kern der Strategie - betrachten einfach den Benutzertyp (von der Behörde festgelegt) undpicks the target URL based on this role.

Daher wird einadmin user - bestimmt durch die Autorität vonROLE_ADMIN - nach der Anmeldung auf die Konsolenseite umgeleitet, währendthe standard user - bestimmt durchROLE_USER - an die umgeleitet wird Startseite.

4. Fazit

Wie immer ist der in diesem Artikel vorgestellte Codeover on Github verfügbar. Dies ist ein Maven-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein.