Einfaches Single Sign-On mit Spring Security OAuth2

Einfaches Single Sign-On mit Spring Security OAuth2

1. Überblick

In diesem Tutorial wird erläutert, wie Sie SSO - Single Sign On - mithilfe von Spring Security OAuth und Spring Boot implementieren.

Wir verwenden drei separate Anwendungen:

  • Ein Autorisierungsserver - das ist der zentrale Authentifizierungsmechanismus

  • Zwei Client-Anwendungen: Die Anwendungen, die SSO verwenden

Ganz einfach ausgedrückt: Wenn ein Benutzer versucht, auf eine gesicherte Seite in der Client-App zuzugreifen, wird er über den Authentifizierungsserver zur Authentifizierung umgeleitet.

Und wir werden den Grant-TypAuthorization Codeaus OAuth2 verwenden, um die Delegierung der Authentifizierung voranzutreiben.

Weitere Lektüre:

Spring Security 5 - OAuth2-Anmeldung

In Spring Security 5 erfahren Sie, wie Sie Benutzer mit Facebook, Google oder anderen Anmeldeinformationen mithilfe von OAuth2 authentifizieren.

Read more

Neu in Spring Security OAuth2 - Ansprüche überprüfen

Schneller praktischer Einstieg in die neue Claim Verification-Unterstützung in Spring Security OAuth.

Read more

Ein sekundäres Facebook-Login mit Spring Social

Ein kurzer Blick auf die Implementierung einer Facebook-gesteuerten Authentifizierung neben einer Standard-Spring-App für die Formularanmeldung.

Read more

 

Bevor wir anfangen - ein wichtiger Hinweis. Denken Sie daran, dassthe Spring Security core team is in the process of implementing a new OAuth2 stack - mit einigen Aspekten bereits und einige noch in Bearbeitung.

Hier ist ein kurzes Video, das Ihnen einen Kontext zu diesen Bemühungen gibt:

 

Okay, lass uns gleich einsteigen.

2. Die Client-App

Beginnen wir mit unserer Client-Anwendung. Wir werden natürlich Spring Boot verwenden, um die Konfiguration zu minimieren:

2.1. Maven-Abhängigkeiten

Zunächst benötigen wir die folgenden Abhängigkeiten in unserenpom.xml:


    org.springframework.boot
    spring-boot-starter-web


    org.springframework.boot
    spring-boot-starter-security


    org.springframework.security.oauth.boot
    spring-security-oauth2-autoconfigure
    2.0.1.RELEASE


    org.springframework.boot
    spring-boot-starter-thymeleaf


    org.thymeleaf.extras
    thymeleaf-extras-springsecurity4

2.2. Sicherheitskonfiguration

Als nächstes der wichtigste Teil, die Sicherheitskonfiguration unserer Client-Anwendung:

@Configuration
@EnableOAuth2Sso
public class UiSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**")
          .authorizeRequests()
          .antMatchers("/", "/login**")
          .permitAll()
          .anyRequest()
          .authenticated();
    }
}

Der Kern dieser Konfiguration ist natürlich die@EnableOAuth2Sso-Anmerkung, die wir zum Aktivieren von Single Sign On verwenden.

Beachten Sie, dass wir dieWebSecurityConfigurerAdapter erweitern müssen - ohne sie werden alle Pfade gesichert - damit die Benutzer umgeleitet werden, um sich anzumelden, wenn sie versuchen, auf eine Seite zuzugreifen. In unserem Fall sind die Index- und Anmeldeseiten die einzigen Seiten, auf die ohne Authentifizierung zugegriffen werden kann.

Schließlich haben wir auch eineRequestContextListener-Bean definiert, um Anforderungsbereiche zu verarbeiten.

Und dieapplication.yml:

server:
    port: 8082
    servlet:
        context-path: /ui
    session:
      cookie:
        name: UISESSION
security:
  basic:
    enabled: false
  oauth2:
    client:
      clientId: SampleClientId
      clientSecret: secret
      accessTokenUri: http://localhost:8081/auth/oauth/token
      userAuthorizationUri: http://localhost:8081/auth/oauth/authorize
    resource:
      userInfoUri: http://localhost:8081/auth/user/me
spring:
  thymeleaf:
    cache: false

Ein paar kurze Notizen:

  • Wir haben die Standardauthentifizierung deaktiviert

  • accessTokenUri ist der URI zum Abrufen der Zugriffstoken

  • userAuthorizationUri ist der Autorisierungs-URI, zu dem Benutzer umgeleitet werden

  • userInfoUriist der URI des Benutzerendpunkts, um aktuelle Benutzerdetails abzurufen

Beachten Sie auch, dass wir in unserem Beispiel hier unseren Authorization Server eingeführt haben, aber natürlich auch andere Drittanbieter wie Facebook oder GitHub verwenden können.

2.3. Vorderes Ende

Schauen wir uns nun die Front-End-Konfiguration unserer Client-Anwendung an. Darauf werden wir uns hier nicht konzentrieren, hauptsächlich weil wiralready covered in on the site.

Unsere Kundenanwendung hier hat ein sehr einfaches Frontend; Hier sind dieindex.html:

Spring Security SSO

Login

Und diesecuredPage.html:

Secured Page

Welcome, Name

Auf der SeitesecuredPage.htmlmussten die Benutzer authentifiziert werden. Wenn ein nicht authentifizierter Benutzer versucht, aufsecuredPage.html zuzugreifen, wird er zuerst zur Anmeldeseite umgeleitet.

3. Der Auth-Server

Lassen Sie uns nun unseren Autorisierungsserver hier diskutieren.

3.1. Maven-Abhängigkeiten

Zuerst müssen wir die Abhängigkeiten in unserenpom.xml definieren:


    org.springframework.boot
    spring-boot-starter-web


    org.springframework.security.oauth
    spring-security-oauth2
    2.3.3.RELEASE

3.2. OAuth-Konfiguration

Es ist wichtig zu verstehen, dass wir den Autorisierungsserver und den Ressourcenserver hier zusammen als eine einzige bereitstellbare Einheit ausführen.

Beginnen wir mit der Konfiguration unseres Ressourcenservers, der gleichzeitig unsere primäre Startanwendung ist:

@SpringBootApplication
@EnableResourceServer
public class AuthorizationServerApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(AuthorizationServerApplication.class, args);
    }
}

Dann konfigurieren wir unseren Autorisierungsserver:

@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Override
    public void configure(
      AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("permitAll()")
          .checkTokenAccess("isAuthenticated()");
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
          .withClient("SampleClientId")
          .secret(passwordEncoder.encode("secret"))
          .authorizedGrantTypes("authorization_code")
          .scopes("user_info")
          .autoApprove(true)
          .redirectUris(
            "http://localhost:8082/ui/login","http://localhost:8083/ui2/login");
    }
}

Beachten Sie, dass wir nur einen einfachen Client mit dem Grant-Typauthorization_codeaktivieren.

Beachten Sie außerdem, wieautoApprove auf true gesetzt ist, damit wir nicht umgeleitet und heraufgestuft werden, um Bereiche manuell zu genehmigen.

3.3. Sicherheitskonfiguration

Zunächst deaktivieren wir die Standard-Standardauthentifizierung über unsereapplication.properties:

server.port=8081
server.servlet.context-path=/auth

Gehen wir nun zur Konfiguration und definieren einen einfachen Formularanmeldemechanismus:

@Configuration
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatchers()
          .antMatchers("/login", "/oauth/authorize")
          .and()
          .authorizeRequests()
          .anyRequest().authenticated()
          .and()
          .formLogin().permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("john")
            .password(passwordEncoder().encode("123"))
            .roles("USER");
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

Beachten Sie, dass wir die einfache In-Memory-Authentifizierung verwendet haben, diese jedoch einfach durch ein benutzerdefiniertesuserDetailsServiceersetzen können.

3.4. Benutzerendpunkt

Abschließend erstellen wir unseren Benutzerendpunkt, den wir zuvor in unserer Konfiguration verwendet haben:

@RestController
public class UserController {
    @GetMapping("/user/me")
    public Principal user(Principal principal) {
        return principal;
    }
}

Dies gibt natürlich die Benutzerdaten mit einer JSON-Darstellung zurück.

4. Fazit

In diesem kurzen Tutorial haben wir uns auf die Implementierung von Single Sign On mit Spring Security Oauth2 und Spring Boot konzentriert.

Wie immer kann der vollständige Quellcodeover on GitHub gefunden werden.