Spring Security OAuth2:SSO单点登录


接着上一篇博客:https://www.cnblogs.com/wwjj4811/p/14505886.html

概述

单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任。单点登录在大型网站里使用得非常频繁,例如像阿里巴巴这样的网站,在网站的背后是成百上千的子系统,用户一次操作或交易可能涉及到几十个子系统的协作,如果每个子系统都需要用户认证,不仅用户会疯掉,各子系统也会为这种重复认证授权的逻辑搞疯掉

准备工作

sql

向oauth_client_detials表添加两条数据

INSERT INTO `study-security`.`oauth_client_details`(`client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`) VALUES ('client1', NULL, '$2a$10$fTo73KCRzU3HXcPGtaTmxu9zDIrnoud6GvhlKF0sIxWzm7awSkGOK', 'MEMBER_READ,MEMBER_WRITE', 'authorization_code,refresh_code', 'http://localhost:9001/login', NULL, 50000, NULL, NULL, 'true');
INSERT INTO `study-security`.`oauth_client_details`(`client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`) VALUES ('client2', NULL, '$2a$10$fTo73KCRzU3HXcPGtaTmxu9zDIrnoud6GvhlKF0sIxWzm7awSkGOK', 'MEMBER_READ', 'authorization_code,refresh_code', 'http://localhost:9002/login', NULL, 50000, NULL, NULL, 'true');

SSO 会员客户端1

创建cloud-oauth2-sso-client1模块,pom.xml如下:

    <dependencies>
        <dependency>
            <groupId>com.wj</groupId>
            <artifactId>cloud-oauth2-base</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <!-- 注册到 Eureka
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
       </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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    </dependencies>

application.yml

server:
  port: 9001

spring:
  thymeleaf:
    cache: false

security:
  oauth2:
    client:
      client-id: client1 # 当前客户端id
      client-secret: wj-secret # 客户端的密码
      user-authorization-uri: http://localhost:8090/auth/oauth/authorize #请求认证的地址,获取授权码地址
      access-token-uri: http://localhost:8090/auth/oauth/token # 请求令牌的地址
    resource:
      jwt:
        # 当用户授权之后会响应一个授权码,重定向到当前应用的 http://localhost:9001/login?code=xxx
        # 自动的会对 /login 去获取令牌,获取到令牌后会通过 key-uri 获取到的公钥进行解密然后本地身份认证和授权(Session)
        key-uri: http://localhost:8090/auth/oauth/token_key # 获取公钥

主启动类和控制器

@SpringBootApplication
public class SsoClient1Application {

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

@Controller
public class MainController {

    @GetMapping("/")
    public String index(){
        return "index";
    }

    @GetMapping("/member")
    public String member(){
        return "member";
    }
}

创建前端html,两个页面都放到templates下面

image-20210310093841210

index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>sso1 首页</title>
</head>
<body>
    <h1>
        <a th:href="@{/member}">客户端1-查看会员</a>
    </h1>
</body>
</html>

member.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
    <div>
        <h1>客户端1,欢迎您![[${#authentication.name}]]</h1>
        <h3><a th:href="@{/logout}">退出系统</a></h3>
    </div>
</body>
</html>

sso登陆配置类:

@Configuration
@EnableOAuth2Sso
public class SsoSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //首页所有人可以访问
                .antMatchers("/").permitAll()
                .anyRequest().authenticated();
    }
}

SSO 会员客户端2

创建模块cloud-oauth2-sso-client2

cloud-oauth2-sso-client2和cloud-oauth2-sso-client1基本一样,端口号从9001改成9002,所有client1改成client2

单点登陆测试

先启动认证服务器,再启动sso客户端,否则会直接报错。因为客户端启动时会去发送请求获取公钥。

image-20210310094944486

先进入http://localhost:9001/,点击

image-20210310095133623

因为没有登陆,所以直接跳转到登录页面,这里的登录页是认证服务器的,账号密码是 admin/1234

image-20210310095224851

登陆成功后,跳转到member页面

image-20210310095336165

这时候我们直接访问:http://localhost:9002/member,发现直接访问成功,不需要登陆,sso单点登录整合成功

image-20210310095546311

SSO 退出系统

在单点登陆系统中,我们希望退出登陆当前系统后,将所有客户端都退出,我们修改配置SsoSecurityConfig:

@Configuration
@EnableOAuth2Sso
public class SsoSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //首页所有人可以访问
                .antMatchers("/").permitAll()
                .anyRequest().authenticated()
                .and()
                //当前应用退出
                .logout()
                //退出成功后,跳转到认证服务器退出
                .logoutSuccessUrl("http://localhost:8090/auth/logout")
                .and().csrf().disable();
    }
}

测试:

我们先在sso1客户端中退出,点击退出系统

image-20210310100121849

再点击logout out

image-20210310100143299

然后就跳转到认证服务器的登陆页面了

image-20210310100213193

这时候我们再刷新sso2客户端的页面,就发现需要重新登陆了

image-20210310100241124

至此,Spring Security OAuth2的单点登陆整合完毕,单次登陆,处处登陆;单次退出,处处退出。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM