SSO单点登录集成魔方 - xinwu-yang/cube-java GitHub Wiki

以下使用so-token中SSO模式二 URL重定向传播会话

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

 用户在 子系统 点击 [登录] 按钮。
户跳转到子系统登录接口 /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 页面。

集成步骤:

- 搭建授权服务

1. 添加依赖
<!-- Sa-Token 权限认证, 在线文档:http://sa-token.dev33.cn/ -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot-starter</artifactId>
    <version>1.30.0</version>
</dependency>

<!-- Sa-Token 插件:整合SSO -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-sso</artifactId>
    <version>1.30.0</version>
</dependency>

<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-dao-redis-jackson</artifactId>
    <version>1.30.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.ejlchina</groupId>
     <artifactId>okhttps</artifactId>
     <version>3.1.1</version>
</dependency>

2. 开放认证接口

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

    /*
     * SSO-Server端:处理所有SSO相关请求 (下面的章节我们会详细列出开放的接口) 
     */
    @RequestMapping("/sso/*")
    public Object ssoRequest() {
        return SaSsoHandle.serverRequest();
    }

    /**
     * 配置SSO相关参数 
     */
    @Autowired
    private void configSso(SaSsoConfig sso) {
        // 配置:未登录时返回的View 
        sso.setNotLoginView(() -> {
            String msg = "当前会话在SSO-Server端尚未登录,请先访问"
                    + "<a href='/sso/doLogin?name=sa&pwd=123456' target='_blank'> doLogin登录 </a>"
                    + "进行登录之后,刷新页面开始授权";
            return msg;
        });

        // 配置:登录处理函数 
        sso.setDoLoginHandle((name, pwd) -> {
            // 此处仅做模拟登录,真实环境应该查询数据进行登录 
            if("sa".equals(name) && "123456".equals(pwd)) {
                StpUtil.login(10001);
                return SaResult.ok("登录成功!").setData(StpUtil.getTokenValue());
            }
            return SaResult.error("登录失败!");
        });

        // 配置 Http 请求处理器 (在模式三的单点注销功能下用到,如不需要可以注释掉) 
        sso.setSendHttp(url -> {
            try {
                // 发起 http 请求 
                System.out.println("发起请求:" + url);
                return OkHttps.sync(url).get().getBody().toString();
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        });
    }

}

3.全局拦截配置

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

4.yml配置

# 端口
server:
  port: 9000

# Sa-Token 配置
sa-token:
  sso:
    # Ticket有效期 (单位: 秒),默认五分钟
    ticket-timeout: 300
    # 所有允许的授权回调地址
    allow-url: "*"
    # 是否打开单点注销功能
    is-slo: true
    # ------- SSO-模式三相关配置 (下面的配置在SSO模式三并且 is-slo=true 时打开) -------
    # 是否打开模式三
    isHttp: false
    # 接口调用秘钥(用于SSO模式三的单点注销功能)
    secretkey: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
    # ---- 除了以上配置项,你还需要为 Sa-Token 配置http请求处理器(文档有步骤说明)

spring:
  # Redis配置 (SSO模式一和模式二使用Redis来同步会话)
  redis:
    # Redis数据库索引(默认为0)
    database: 14
    # Redis服务器地址
    host: 25.30.15.85
    # Redis服务器连接端口
    port: 6379
    # Redis服务器连接密码(默认为空)
    password:
    # 连接超时时间
    timeout: 10s
    lettuce:
      pool:
        # 连接池最大连接数
        max-active: 200
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms
        # 连接池中的最大空闲连接
        max-idle: 10
        # 连接池中的最小空闲连接
        min-idle: 0

5.启动项目

访问统一授权地址: http://localhost:9000/sso/auth

在此登录逻辑可以根据系统情况而修改,使用StpUtil.login(username);进行会话登录时推荐使用 username 进行

- 搭建客户端(将魔方作为客户端)

1.创建 SSO-Client 端认证接口

登陆页面可使用前端页面只要登陆url遵循一下返回的格式即可

/**
 * 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 SaSsoHandle.clientRequest();
    }

}

2.增加配置

# sa-token配置
sa-token:
  # SSO-相关配置
  sso:
    # SSO-Server端 统一认证地址
    auth-url: http://sa-sso-server.com:9000/sso/auth
    # 是否打开单点注销接口
    is-slo: true
  # 配置Sa-Token单独使用的Redis连接 (此处需要和SSO-Server端连接同一个Redis)
  alone-redis:
    # Redis数据库索引
    database: 14
    # Redis服务器地址
    host: 25.30.15.85
    # Redis服务器连接端口
    port: 6379
    # Redis服务器连接密码(默认为空)
    password:
    # 连接超时时间
    timeout: 10s

3.启动魔方项目

http://sa-sso-client1.com:9001/

⚠️ **GitHub.com Fallback** ⚠️