In this section, the source code at https://github.com/laolunsi/spring-boot-examples, please feel free to eat
This section uses Spring Security Oauth2 to implement single sign-on function of SpringBoot project.
Create three SpringBoot applications: Auth-server, client-a, and client-b. Auth-server is the authorization server used for login and obtaining user information.
This section uses SpringBoot 2.1.9.RELEASE and Spring Security 2.1.9.RELEASE
1. Parent project SSO-Oauth2-Demo
First we create a parent Maven project called Sso-Oauth2-Demo. The three applications mentioned above are sub-applications of this project. The parent project Maven introduces the following configuration:
<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < modelVersion > 4.0.0 < / modelVersion > < groupId > com. Example < / groupId > < artifactId > sso - oauth2 - demo < / artifactId > < version > 1.0 - the SNAPSHOT < / version > < properties > < Java version > 1.8 < / Java version > < spring - the boot version > 2.1.9. RELEASE < / spring - the boot. Version > . < spring ws-security version > 2.1.9. RELEASE < / spring ws-security. Version > < / properties > < dependencies > < the dependency > <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>${spring-security.version}</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <scope>import</scope> <type>pom</type> </dependency> </dependencies> </dependencyManagement> </project>Copy the code
The parent project has a single Maven pom.xml and requires no code. Let’s start by creating the authorization server and client application A/B
Auth-server authorization server auth-server
Create a sub-Springboot project — Auth-server under the SSO-oAuth2-demo project and introduce the following dependencies:
<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" > < modelVersion > 4.0.0 < / modelVersion > < the parent > < groupId > com. Example < / groupId > < artifactId > sso - oauth2 - demo < / artifactId > < version > 1.0 - the SNAPSHOT < / version > < relativePath / > <! -- lookup parent from repository --> </parent> <artifactId> Auth-server </artifactId> <version>0.0.1-SNAPSHOT</version> <name>auth-server</name> <description>Demo project for Spring Boot</description> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>Copy the code
Here we see that the parent sSO-OAuth2-Demo project inherits some common dependencies from the parent project.
Configuration:
server:
port: 8300
servlet:
context-path: '/auth'
Copy the code
PS: The authorization server configuration file is relatively simple and requires nothing else.
Start the class:
@SpringBootApplication
@EnableResourceServer
public class AuthServerApplication {
public static void main(String[] args) {
SpringApplication.run(AuthServerApplication.class, args);
}
}Copy the code
PS: Enable the resource server
There are two classes that need to be configured for Auth and Security:
Authorized server Configuration / * * * * / @ Configuration @ EnableAuthorizationServer public class AuthServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private BCryptPasswordEncoder passwordEncoder; @Override public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenKeyAccess("permitAll") .checkTokenAccess("isAuthenticated()"); } @Override public void configure(final ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("SampleClientId") .secret(passwordEncoder.encode("secret")) .authorizedGrantTypes("authorization_code") .scopes("user_info") .autoApprove(true) .redirectUris("http://localhost:8301/login", "http://localhost:8302/login"); } // redirectUris must be configured, otherwise an error will be reported when requesting authorization code: error="invalid_request", error_description="At least one redirect_uri must be registered with the client." }Copy the code
PS: BCryptPasswordEncoder If you cannot inject, you can directly try new.
In this demo, the login user name and password are fixed. In the actual project * / @ Configuration @ the Order should be read from the database (1) the 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() .and().csrf().disable(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("eknown") .password(passwordEncoder().encode("123")) .roles("USER"); } @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }}Copy the code
At this point, the basic configuration of the authorization server is complete. Now we need to provide an interface to get login user information:
/** * A unique interface in this interface class, used by ClientA and ClientB to obtain user information after successful login. * This interface address can be arbitrarily modified, */ @restController @requestMapping (value = "user") public class UserAction {RestController @requestMapping (value = "user") public class UserAction { @getMapping (value = "me") public Principal me(Principal Principal) {system.out.println (" call me interface to get user information: "+ Principal); return principal; }}Copy the code
PS: The above interfaces are assigned to ClientA and ClientB and are specified in the configuration to obtain the current user information after login.
Ok, let’s create two test applications — client-A and client-b
Client applications Client-A and client-b
Create SpringBoot projects for maven’s children — client-a and client-b. Here we show the creation and configuration of client-A, and the name of client-b is different.
Modify maven file:
<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" > < modelVersion > 4.0.0 < / modelVersion > < the parent > < groupId > com. Example < / groupId > < artifactId > sso - oauth2 - demo < / artifactId > < version > 1.0 - the SNAPSHOT < / version > < relativePath / > <! -- lookup parent from repository --> </parent> <artifactId>client-a</artifactId> <version>0.0.1-SNAPSHOT</version> <name>client-a</name> <description>Demo project for Spring Boot</description> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <! > <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>Copy the code
Configuration, which is more complicated, must be noted:
server: port: 8301 servlet: session: cookie: name: CLIENT_A_SESSION security: oauth2: client: client-id: SampleClientId client-secret: secret access-token-uri: http://localhost:8300/auth/oauth/token user-authorization-uri: http://localhost:8300/auth/oauth/authorize resource: user-info-uri: http://localhost:8300/auth/user/me # currently logged in user information was obtained from the license server address spring: thymeleaf: cache: falseCopy the code
The user-info-URI in the previous auth-server corresponds to the interface.
The startup class does not need to be modified. Here is a configuration class for Security:
@EnableOAuth2Sso @Configuration public class MySecurityConfig extends WebSecurityConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.antMatcher("/**") .authorizeRequests() .antMatchers("/", "/login**") .permitAll() .anyRequest() .authenticated(); }}Copy the code
At this point, the basic configuration is complete. Let’s create the test page and interface:
Create a Templaes folder under the Resources folder, the sibling of application.yml, and place it in two pages:
Index.html:
<! DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Spring Security SSO</title> <link rel="stylesheet" A href = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" / > < / head > < body > < div class = "container" > <div class=" col-SM-12 "> <h1>Spring Security SSO client A</h1> < A class=" BTN bTN-primary "href="securedPage">Login</ A > </div> </div> </body> </html>Copy the code
securedPage.html:
<! DOCTYPE html> <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Spring Security SSO</title> <link rel="stylesheet" A href = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" / > < / head > < body > < div class = "container" > <div class="col-sm-12"> <h1>Secured Page, Client A</h1> Welcome, <span th:text="${#authentication.name}">Name</span> </div> </div> </body> </html>Copy the code
PS: index.html does not require authentication, whereas securedPage or securedPage uses authentication.name, so authorization is required.
Let’s create the interface to get the page:
@controller public class IndexAction {@getMapping (value = "") public String index() { System.out.println(" Enter ClientA home page "); return "index.html"; } @getMapping (value = "securedPage") public String home() {system.out.println (" enter ClientA securedPage"); return "securedPage.html"; }}Copy the code
Then create the client-b project in the same way as above, noting that some of the client-a and client-b related names or configurations are modified.
With that done, we’re ready to test!
4. Start and test
Start these three projects and run them on port 8300/8301/8302 respectively.
First we go to http://localhost:8301 and go to index.html:
Click login, and notice that this interface just opens securedPage.html, and since securedPage.html uses the user information that needs to be authorized, Oauth2 automatically redirected to the auth – the corresponding http://localhost:8300/auth/login server page:
Enter the default user name eknow and password 123 to log in:
The home page of client-B is displayed:
When you click login, instead of being redirected to auth-Server’s login page, you get the user data and go to clientB’s Secured page, indicating that the single sign-on has succeeded!
After ClientA successfully logs in, the ClientB application on the same browser automatically performs authorization authentication and does not need to log in again.
Ok, at this point, our SSO-Oauth2-demo project is complete!
Reference:
- Simple Single Sign-on With Spring Security OAuth2: www.baeldung.com/sso-spring-…