Springboot 权限认证框架 -- SA-Token 单点登录(三)

一、Sa-Token-SSO 简介

Sa-Token-SSO 由简入难划分为三种模式,解决不同架构下的 SSO 接入问题:

系统架构采用模式简介
前端同域 + 后端同 Redis模式一共享 Cookie 同步会话
前端不同域 + 后端同 Redis模式二URL重定向传播会话
前端不同域 + 后端不同 Redis模式三Http请求获取会话

二、搭建统一认证中心 SSO-Server

1、添加依赖

创建 SpringBoot 项目 sa-token-demo-sso-server,引入依赖:

<!-- Sa-Token 权限认证,在线文档:https://sa-token.cc -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot-starter</artifactId>
    <version>1.38.0</version>
</dependency>

<!-- Sa-Token 插件:整合SSO -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-sso</artifactId>
    <version>1.38.0</version>
</dependency>
        
<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-redis-jackson</artifactId>
    <version>1.38.0</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

<!-- 视图引擎(在前后端不分离模式下提供视图支持) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<!-- Http请求工具(在模式三的单点注销功能下用到,如不需要可以注释掉) -->
<dependency>
    <groupId>com.dtflys.forest</groupId>
    <artifactId>forest-spring-boot-starter</artifactId>
    <version>1.5.26</version>
</dependency>

2、开放认证接口

新建 SsoServerController,用于对外开放接口:

/**
 * Sa-Token-SSO Server端 Controller 
 */
@RestController
public class SsoServerController {

    /**
     * SSO-Server端:处理所有SSO相关请求 (下面的章节我们会详细列出开放的接口) 
     */
    @RequestMapping("/sso/*")
    public Object ssoRequest() {
        return SaSsoServerProcessor.instance.dister();
    }
    
    /**
     * 配置SSO相关参数 
     */
    @Autowired
    private void configSso(SaSsoServerConfig ssoServer) {
        // 配置:未登录时返回的View 
        ssoServer.notLoginView = () -> {
            String msg = "当前会话在SSO-Server端尚未登录,请先访问"
                    + "<a href='/sso/doLogin?name=sa&pwd=123456' target='_blank'> doLogin登录 </a>"
                    + "进行登录之后,刷新页面开始授权";
            return msg;
        };
        
        // 配置:登录处理函数 
        ssoServer.doLoginHandle = (name, pwd) -> {
            // 此处仅做模拟登录,真实环境应该查询数据进行登录 
            if("sa".equals(name) && "123456".equals(pwd)) {
                StpUtil.login(10001);
                return SaResult.ok("登录成功!").setData(StpUtil.getTokenValue());
            }
            return SaResult.error("登录失败!");
        };
        
        // 配置 Http 请求处理器 (在模式三的单点注销功能下用到,如不需要可以注释掉) 
        ssoServer.sendHttp = url -> {
            try {
                System.out.println("------ 发起请求:" + url);
                String resStr = Forest.get(url).executeAsString();
                System.out.println("------ 请求结果:" + resStr);
                return resStr;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        };
    }
    
}

全局异常处理:

@RestControllerAdvice
public class GlobalExceptionHandler {
    // 全局异常拦截 
    @ExceptionHandler
    public SaResult handlerException(Exception e) {
        e.printStackTrace(); 
        return SaResult.error(e.getMessage());
    }
}

3、application.yml配置

# 端口
server:
    port: 9000

# Sa-Token 配置
sa-token: 
    # ------- SSO-模式一相关配置  (非模式一不需要配置) 
    # cookie: 
        # 配置 Cookie 作用域 
        # domain: stp.com 
        
    # ------- SSO-模式二相关配置 
    sso-server: 
        # Ticket有效期 (单位: 秒),默认五分钟 
        ticket-timeout: 300
        # 所有允许的授权回调地址
        allow-url: "*"
        
        # ------- SSO-模式三相关配置 (下面的配置在使用SSO模式三时打开)
        # 是否打开模式三 
        is-http: true
    sign:
        # API 接口调用秘钥
        secret-key: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
        # ---- 除了以上配置项,你还需要为 Sa-Token 配置http请求处理器(文档有步骤说明) 
        
spring: 
    # Redis配置 (SSO模式一和模式二使用Redis来同步会话)
    redis:
        # Redis数据库索引(默认为0)
        database: 1
        # Redis服务器地址
        host: 127.0.0.1
        # Redis服务器连接端口
        port: 6379
        # Redis服务器连接密码(默认为空)
        password: 
        
forest: 
    # 关闭 forest 请求日志打印
    log-enabled: false

4、创建启动类

@SpringBootApplication
public class SaSsoServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(SaSsoServerApplication.class, args);

        System.out.println();
        System.out.println("---------------------- Sa-Token SSO 统一认证中心启动成功 ----------------------");
        System.out.println("配置信息:" + SaSsoManager.getServerConfig());
        System.out.println();
    }
}

访问统一授权地址(仅测试 SSO-Server 是否部署成功,暂时还不需要点击登录):

http://localhost:9000/sso/auth

三、SSO 客户端搭建-URL重定向传播会话

如果我们的多个系统:部署在不同的域名之下,但是后端可以连接同一个Redis,那么便可以使用 URL重定向传播会话 的方式做到单点登录。

1. 单点登录流程

  • 用户在 子系统 点击 [登录] 按钮。
  • 用户跳转到子系统登录接口 /sso/login,并携带 back参数 记录初始页面URL。
    形如:http://{sso-client}/sso/login?back=xxx
  • 子系统检测到此用户尚未登录,再次将其重定向至SSO认证中心,并携带redirect参数记录子系统的登录页URL。
    形如:http://{sso-server}/sso/auth?redirect=xxx?back=xxx
  • 用户进入了 SSO认证中心 的登录页面,开始登录。
  • 用户 输入账号密码 并 登录成功,SSO认证中心再次将用户重定向至子系统的登录接口/sso/login,并携带ticket码参数。
    形如:http://{sso-client}/sso/login?back=xxx&ticket=xxxxxxxxx
  • 子系统根据 ticket码 从 SSO-Redis 中获取账号id,并在子系统登录此账号会话。
    子系统将用户再次重定向至最初始的 back 页面。

2. 搭建 Client 端项目

搭建示例在官方仓库的 /sa-token-demo/sa-token-demo-sso/sa-token-demo-sso2-client/,如遇到难点可结合源码进行测试学习

2.1 引入 pom 依赖

<!-- Sa-Token 权限认证, 在线文档:https://sa-token.cc -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot-starter</artifactId>
    <version>1.38.0</version>
</dependency>
<!-- Sa-Token 插件:整合SSO -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-sso</artifactId>
    <version>1.38.0</version>
</dependency>

<!-- Sa-Token 整合redis (使用jackson序列化方式) -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-redis-jackson</artifactId>
    <version>1.38.0</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

<!-- Sa-Token插件:权限缓存与业务缓存分离 -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-alone-redis</artifactId>
    <version>1.38.0</version>
</dependency>

2.2 创建 SSO-Client 端认证接口

同 SSO-Server 一样,Sa-Token 为 SSO-Client 端所需代码也提供了完整的封装,你只需提供一个访问入口,接入 Sa-Token 的方法即可。


/**
 * Sa-Token-SSO Client端 Controller 
 */
@RestController
public class SsoClientController {

    // 首页 
    @RequestMapping("/")
    public String index() {
        String str = "<h2>Sa-Token SSO-Client 应用端</h2>" + 
                    "<p>当前会话是否登录:" + StpUtil.isLogin() + "</p>" + 
                    "<p><a href=\"javascript:location.href='/sso/login?back=' + encodeURIComponent(location.href);\">登录</a> " + 
                    "<a href='/sso/logout?back=self'>注销</a></p>";
        return str;
    }
    
    /*
     * SSO-Client端:处理所有SSO相关请求 
     *         http://{host}:{port}/sso/login          -- Client端登录地址,接受参数:back=登录后的跳转地址 
     *         http://{host}:{port}/sso/logout         -- Client端单点注销地址(isSlo=true时打开),接受参数:back=注销后的跳转地址 
     *         http://{host}:{port}/sso/logoutCall     -- Client端单点注销回调地址(isSlo=true时打开),此接口为框架回调,开发者无需关心
     */
    @RequestMapping("/sso/*")
    public Object ssoRequest() {
        return SaSsoClientProcessor.instance.dister();
    }

}

2.3 配置SSO认证中心地址

# 端口
server:
    port: 9001

# sa-token配置 
sa-token: 
    # SSO-相关配置
    sso-client: 
        # SSO-Server 端主机地址
        server-url: http://sa-sso-server.com:9000

    # 配置Sa-Token单独使用的Redis连接 (此处需要和SSO-Server端连接同一个Redis)
    alone-redis: 
        # Redis数据库索引 (默认为0)
        database: 1
        # Redis服务器地址
        host: 127.0.0.1
        # Redis服务器连接端口
        port: 6379
        # Redis服务器连接密码(默认为空)
        password: 
        # 连接超时时间
        timeout: 10s

2.4 写启动类

@SpringBootApplication
public class SaSso2ClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(SaSso2ClientApplication.class, args);
        
        System.out.println();
        System.out.println("---------------------- Sa-Token SSO 模式二 Client 端启动成功 ----------------------");
        System.out.println("配置信息:" + SaSsoManager.getClientConfig());
        System.out.println("测试访问应用端一: http://sa-sso-client1.com:9001");
        System.out.println("测试访问应用端二: http://sa-sso-client2.com:9001");
        System.out.println("测试访问应用端三: http://sa-sso-client3.com:9001");
        System.out.println("测试前需要根据官网文档修改hosts文件,测试账号密码:sa / 123456");
        System.out.println();
    }
}

2.5 测试访问

依次启动 SSO-Server 与 SSO-Client,然后从浏览器访问:http://sa-sso-client1.com:9001/

参考:https://sa-token.cc/doc.html#/sso/sso-type2

  • 29
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
sa-token是一个JavaWeb轻量级权限认证框架,它提供了单点登录的功能。具体实现步骤如下: 1.在s1.stp.com的子系统1登录之后,返回一个在父域名stp.com下的Cookie的token。 2.在s2.stp.com的子系统2中,用户点击登录按钮,重定向到sso/auth授权地址。 3.在sso/auth授权地址中,判断用户是否已经登录,如果已经登录,则返回一个包含token的重定向地址。 4.在子系统2中,获取重定向地址中的token,并将其存储在Cookie中。 5.在子系统2中,每次请求时,都需要携带Cookie中的token,以便进行单点登录。 下面是一个示例代码: ```java // 在s1.stp.com的子系统1中,生成token并返回 String token = SaTokenManager.createToken("10001"); Cookie cookie = new Cookie("token", token); cookie.setDomain("stp.com"); response.addCookie(cookie); // 在sso/auth授权地址中,判断用户是否已经登录,并返回重定向地址 String redirectUrl = "http://s2.stp.com/index"; if (SaTokenManager.isLogin(token)) { redirectUrl += "?token=" + token; } response.sendRedirect(redirectUrl); // 在s2.stp.com的子系统2中,获取重定向地址中的token,并存储在Cookie中 String token = request.getParameter("token"); Cookie cookie = new Cookie("token", token); cookie.setDomain("stp.com"); response.addCookie(cookie); // 在s2.stp.com的子系统2中,每次请求时,都需要携带Cookie中的token,以便进行单点登录 String token = request.getCookies()[0].getValue(); SaTokenManager.setToken(token); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值