Einfaches Single Sign-On mit Spring Security OAuth2 (Legacy-Stack)

1. Übersicht

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

Wir werden drei separate Anwendungen verwenden:

  • Ein Autorisierungsserver - dies 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 zuerst zur Authentifizierung umgeleitet.

Und wir werden den Grant-Typ des Autorisierungscodes aus OAuth2 verwenden, um die Delegierung der Authentifizierung voranzutreiben.

Hinweis : In diesem Artikel wird das Spring OAuth-Legacy-Projekt verwendet. Die Version dieses Artikels mit dem neuen Spring Security 5-Stack finden Sie in unserem Artikel Simple Single Sign-On mit Spring Security OAuth2.

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 unserer pom.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 Annotation @ EnableOAuth2Sso , mit der wir Single Sign On aktivieren.

Beachten Sie, dass wir den WebSecurityConfigurerAdapter erweitern müssen - ohne ihn 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 eine RequestContextListener- Bean definiert , um Anforderungsbereiche zu verarbeiten.

Und die application.yml :

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

Ein paar kurze Anmerkungen:

  • Wir haben die Standard-Standardauthentifizierung deaktiviert
  • accessTokenUri ist der URI zum Abrufen der Zugriffstoken
  • userAuthorizationUri ist der Autorisierungs-URI, zu dem Benutzer umgeleitet werden
  • userInfoUri der URI des Benutzerendpunkts, um aktuelle Benutzerdetails abzurufen

Beachten Sie auch, dass wir in unserem Beispiel hier unseren Autorisierungsserver 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. Wir werden uns hier nicht darauf konzentrieren, hauptsächlich, weil wir bereits auf der Website behandelt haben.

Unsere Kundenanwendung hier hat ein sehr einfaches Frontend; Hier ist die index.html :

 Login

Und die SecuredPage.html :

 Welcome, Name

Die securedPage.html Seite benötigt der Benutzer authentifiziert werden. Wenn ein nicht authentifizierter Benutzer versucht, auf SecurePage.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 unserer pom.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 einzelne bereitstellbare Einheit ausführen.

Beginnen wir mit der Konfiguration unseres Ressourcenservers, der gleichzeitig unsere primäre Boot-Anwendung 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( "//localhost:8082/ui/login","//localhost:8083/ui2/login"); } }

Beachten Sie, dass wir nur einen einfachen Client mit dem Berechtigungstyp authorisation_code aktivieren .

Beachten Sie außerdem, wie autoApprove 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 unsere application.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 einen benutzerdefinierten userDetailsService ersetzen können .

3.4. Benutzerendpunkt

Schließlich 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 finden Sie den vollständigen Quellcode auf GitHub.