zoukankan      html  css  js  c++  java
  • 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的单点登陆整合完毕,单次登陆,处处登陆;单次退出,处处退出。

  • 相关阅读:
    css 超出两行省略号,超出一行省略号
    css 去掉i标签默认斜体样式
    Spring 使用单选按钮
    Spring Maven工程引入css,js
    Sping 补充完成修改功能
    Spring 控制器层如何启用验证?
    Spring 控制器层如何调用DAO层
    spring boot工程如何启用 热启动功能
    Spring 视图层如何显示验证消息提示
    Sping POJO中如何添加验证规则和验证消息提示
  • 原文地址:https://www.cnblogs.com/wwjj4811/p/14509864.html
Copyright © 2011-2022 走看看