Win10:SpringBoot+SpringSecurity+oauth2单点SSO(一)

发布于:2022-11-09 ⋅ 阅读:(10) ⋅ 点赞:(0) ⋅ 评论:(0)

环境:VMWindows10+IDEA+JDK8+Maven+SpringBoot+SpringSecurity+oauth2

实现:统一认证端sso_oauth2 (8080)双客户端sso_client_demo1(8081)+

          sso_client_demo2(8082),实现单点入门例子,一处登录多处登录。

源码:

目录

一、实现结果

二、Maven 父工程 sso_spring_security创建

三、在父工程 sso_spring_security 中创建子工程(Module)sso_oauth2,统一认证平台

四、客户端Demo01子工程sso_client_demo1创建

五、客户端Demo02子工程sso_client_demo2创建


一、实现结果

1、服务程序结构及端口

2、 Demo1客户端登录

3、点击Login自动跳转到8080统一登录认证页面

 4、输入账号/密码,Sign in到 Demo1客户端页面

5、 修改访问地址为8082,此时不需要重新调整到步骤3中的登录认证界面,默认认证成功

二、Maven 父工程 sso_spring_security创建

只依赖Security、oauth2-autoconfigure,不需要其他,包括不需要web;pom.xml如下:

<?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>org.sso</groupId>
    <artifactId>sso_spring_security</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
        <java.version>1.8</java.version>
        <spring-boot.version>2.1.9.RELEASE</spring-boot.version>
        <spring-security.version>2.1.9.RELEASE</spring-security.version>
    </properties>

    <dependencies>
        <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>

三、在父工程 sso_spring_security 中创建子工程(Module)sso_oauth2,统一认证平台

1、pom.xml内容如下,注意点:指定父工程;需与父工程中的 <groupId><artifactId><version>保持一致;

<?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>
    <parent>
        <groupId>org.sso</groupId>
        <artifactId>sso_spring_security</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath/> <!-- 指定父工程,引用父工程依赖 -->
    </parent>
    <artifactId>sso_oauth2</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>sso_oauth2</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>

2、application.yml指定端口,路径标识

server:
    port: 8080
    servlet:
        context-path: '/auth'

3、启动类SsoOauth2Application增加@EnableResourceServer注解

package com.sso.sso_oauth2;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;

@SpringBootApplication
@EnableResourceServer
public class SsoOauth2Application {

    public static void main(String[] args) {
        SpringApplication.run(SsoOauth2Application.class, args);
    }

}

@EnableResourceServer是为OAuth2资源服务器提供方便的注释,启用Spring Security 过滤器,通过传入的OAuth2令牌对请求进行身份验证。

3、新建AuthServerConfig授权服务器配置

package com.sso.sso_oauth2.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;

/**
 * 授权服务器配置
 * 必须进行redirectUris的配置,否则请求授权码时会报错:error="invalid_request", error_description="At least one redirect_uri must be registered with the client."
 * withClient 与客户端 client-id 一致
 */
@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:8081/login", "http://localhost:8082/login");
    }
}

4、新建 SecurityConfig security基本配置,并指定登录用户名与密码是固定的,实际项目中应该从数据库读取

package com.sso.sso_oauth2.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * security基本配置
 * 本demo中,登录用户名与密码是固定的,实际项目中应该从数据库读取
 */
@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()
                .and().csrf().disable();
    }

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

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

5、新建UserController

package com.sso.sso_oauth2.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.security.Principal;

/**
 * 该接口类中的唯一接口,用于Client01和Client02在登录成功后获取用户信息用
 * 该接口地址可以任意修改,只要与Client01/02中配置的用户信息地址一致即可
 */
@RestController
@RequestMapping(value = "user")
public class UserController {

    @GetMapping(value = "userInfo")
    public Principal me(Principal principal) {
        System.out.println("调用userInfo接口获取用户信息:" + principal);
        return principal;
    }
}

四、客户端Demo01子工程sso_client_demo1创建

1、pom.xml依赖内容如下,同认证平台,需指定父工程

<?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>
    <parent>
        <groupId>org.sso</groupId>
        <artifactId>sso_spring_security</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.sso</groupId>
    <artifactId>sso_client_demo1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sso_client_demo1</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <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>

        <!-- 引入thymeleaf和thymeleaf security的依赖 -->
        <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>

2、新建MySecurityConfig

package com.sso.sso_client_demo1.config;

import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;


@EnableOAuth2Sso
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

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

}

3、页面跳转IndexController

package com.sso.sso_client_demo1.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * 获取页面的接口
 */
@Controller
public class IndexController {

    @GetMapping(value = "")
    public String index() {
        System.out.println("进入Client01首页");
        return "index.html";
    }

    @GetMapping(value = "securedPage")
    public String home() {
        System.out.println("进入Client01 securedPage");
        return "securedPage.html";
    }
}

 4、启动类不动SsoClientDemo1Application

package com.sso.sso_client_demo1;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SsoClientDemo1Application {

    public static void main(String[] args) {
        SpringApplication.run(SsoClientDemo1Application.class, args);
    }

}

5、客户端首页

<!DOCTYPE html>
<html lang="en">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Spring Security SSO</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"
	rel="stylesheet" />
</head>

<body>
<div class="container">
	<div class="col-sm-12">
		<h1>Spring Security SSO 客户端 Demo01</h1>
		<a class="btn btn-primary" href="securedPage">Login</a>
	</div>
</div>
</body>
</html>

6、客户端Demo01访问成功页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Spring Security SSO</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"
	rel="stylesheet" />
</head>

<body>
<div class="container">
	<div class="col-sm-12">
		<h1>Secured Page, Client Demo01</h1>
		Welcome, <span th:text="${#authentication.name}">Name</span>
	</div>
</div>
</body>
</html>

7、客户端Demo01配置文件 application.yml,,注意cookie name保持唯一;client-id,client-secret与认证工程三-3中参数保持一致;路由参数IP:PORT指定认证平台参数

server:
  port: 8081
  servlet:
    session:
      cookie:
        name: CLIENT_1_SESSION

security:
  oauth2:
    client:
      client-id: SampleClientId
      client-secret: secret
      access-token-uri: http://localhost:8080/auth/oauth/token
      user-authorization-uri: http://localhost:8080/auth/oauth/authorize
    resource:
      user-info-uri: http://localhost:8080/auth/user/userInfo

spring:
  thymeleaf:
    cache: false

五、客户端Demo02子工程sso_client_demo2创建

1、同理步骤四,需注意参数的修改