基於Sa-Token實現微服務之前的單點登入

2023-07-02 12:00:17

修改組態檔,準備好四個域名

127.0.0.1  auth.server.com
127.0.0.1  user.server.com
127.0.0.1  third.server.com
127.0.0.1  eureka.server.com

註冊中心:eureka-server服務

pom依賴

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            <version>3.1.1</version>
        </dependency>
        <!--web專案驅動-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot-start-version}</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.5.0</version>
        </dependency>

設定web專案啟動類

/**
 * @description: Eureka 伺服器端註冊中心:剔除資料來源操作
 * @author: GuoTong
 * @createTime: 2023-06-26 21:50
 * @since JDK 1.8 OR 11
 **/
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableEurekaServer
public class EurekaApplication {

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

設定跨域支援和靜態資源過濾

/**
 * @description: SpringBoot-Web設定
 * @author: GuoTong
 * @createTime: 2023-06-05 15:37
 * @since JDK 1.8 OR 11
 **/
@Configuration
public class SpringBootConfig implements WebMvcConfigurer {

    /**
     * Description:  新增全域性跨域CORS處理
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 設定允許跨域的路徑
        registry.addMapping("/**")
                //設定允許跨域請求的域名
                .allowedOriginPatterns("*")
                // 是否允許證書
                .allowCredentials(true)
                // 設定允許的方法
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                // 設定允許的header屬性
                .allowedHeaders("*")
                // 跨域允許時間
                .maxAge(3600);
    }


    /**
     * Description: 靜態資源過濾
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //ClassPath:/Static/** 靜態資源釋放
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        //釋放swagger
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
        //釋放webjars
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

}

組態檔基礎設定

server:
  port: 10086
spring:
  application:
    name: eureka-server
  security:
    user:
      name: eureka
      password: eureka
  mvc:
    static-path-pattern: classpath:/static/**
eureka:
  client:
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
    register-with-eureka: false #自己不向註冊中心註冊自己
    fetch-registry: false  # 自己是註冊中心
  instance:
    hostname: 127.0.0.1
    prefer-ip-address: true

啟動註冊中心驗證

準備Sa-Token認證中心server

https://sa-token.cc/doc.html 可以自己參考官方網站客製化

引入依賴

knife4j / mysql / mybatis / sa-token / commons / thymeleaf / loadbalancer / bootstrap /eureka-client / lombok

 <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--Knife4j(增強Swagger)-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>${knife4j.version}</version>
        </dependency>

        <!--Mysql資料庫-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql-version}</version>
        </dependency>


        <!--Mybatis-plus 程式碼生成器-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatisplus.verison}</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>${mybatisplus.verison}</version>
        </dependency>

        <!-- Sa-Token 許可權認證,線上檔案:https://sa-token.cc -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-spring-boot-starter</artifactId>
            <version>1.33.0</version>
        </dependency>

        <!-- Sa-Token 外掛:整合SSO -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-sso</artifactId>
            <version>1.33.0</version>
        </dependency>

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

        <!--新版的移除了Ribbon的負載策略,所需改用新版的loadbalancer-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
            <version>${spring-cloud-starter-version}</version>
        </dependency>

        <!-- bootstrap最高階啟動設定讀取 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
            <version>${spring-cloud-starter-version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>3.1.1</version>
        </dependency>

核心Sa-Token的介面


/**
 * @description: 統一認證中心 SSO-Server用於對外開放介面:
 * @author: GuoTong
 * @createTime: 2022-11-26 23:03
 * @since JDK 1.8 OR 11
 **/
@RestController
public class SsoServerController {


    private AuthLoginUserService authLoginUserService;

    /**
     * Description: 構造器注入
     */
    public SsoServerController(AuthLoginUserService authLoginUserService) {
        this.authLoginUserService = authLoginUserService;
    }


    /*
     * /*
     * SSO-Server端:處理所有SSO相關請求
     * 		http://{host}:{port}/sso/auth			-- 單點登入授權地址,接受引數:redirect=授權重定向地址
     * 		http://{host}:{port}/sso/doLogin		-- 賬號密碼登入介面,接受引數:name、pwd
     * 		http://{host}:{port}/sso/checkTicket	-- Ticket校驗介面(isHttp=true時開啟),接受引數:ticket=ticket碼、ssoLogoutCall=單點登出回撥地址 [可選]
     * 		http://{host}:{port}/sso/signout		-- 單點登出地址(isSlo=true時開啟),接受引數:loginId=賬號id、secretkey=介面呼叫祕鑰
     */
    @RequestMapping("/sso/*")
    public Object ssoRequest() {
        return SaSsoProcessor.instance.serverDister();
    }

    /**
     * 設定SSO相關引數
     */
    @Autowired
    private void configSso(SaSsoConfig sso) {
        // 設定:未登入時返回的View
        sso.setNotLoginView(() -> new ModelAndView("sa-login.html"));

        // 設定:登入處理常式
        sso.setDoLoginHandle((name, pwd) -> {
            QueryWrapper<AuthLoginUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("username", name);
            queryWrapper.eq("password", pwd);
            AuthLoginUser user = authLoginUserService.getOne(queryWrapper);
            if (user != null) {
                StpUtil.login(user.getId());
                return SaResult.ok("登入成功!").setData(StpUtil.getTokenValue());
            }
            return SaResult.error("登入失敗!");
        });

    }
}

Http對外介面--簡單幾個範例

/**
 * 前後臺分離架構下整合SSO所需的程式碼 (SSO-Server端)
 * <p>(注:如果不需要前後端分離架構下整合SSO,可刪除此包下所有程式碼)</p>
 *
 * @author kong
 */
@RestController
public class H5Controller {

    @Autowired
    private AuthLoginUserService authLoginUserService;

    /**
     * 獲取 redirectUrl
     */
    @RequestMapping("/sso/getRedirectUrl")
    private Object getRedirectUrl(String redirect, String mode) {
        // 未登入情況下,返回 code=401
        if (StpUtil.isLogin() == false) {
            return SaResult.code(401);
        }
        // 已登入情況下,構建 redirectUrl
        if (SaSsoConsts.MODE_SIMPLE.equals(mode)) {
            // 模式一
            SaSsoUtil.checkRedirectUrl(SaFoxUtil.decoderUrl(redirect));
            return SaResult.data(redirect);
        } else {
            // 模式二或模式三
            String redirectUrl = SaSsoUtil.buildRedirectUrl(StpUtil.getLoginId(), redirect);
            return SaResult.data(redirectUrl);
        }
    }


    @RequestMapping("doLogin")
    public SaResult doLogin(String name, String pwd) {
        return authLoginUserService.queryUserNameAndPassword(name, pwd);
    }

    @RequestMapping(value = "isLogin", method = RequestMethod.GET)
    public SaResult isLogin() {
        return SaResult.ok("是否登入:" + StpUtil.isLogin());
    }

    @RequestMapping(value = "tokenInfo", method = RequestMethod.GET)
    public SaResult tokenInfo() {
        return SaResult.data(StpUtil.getTokenInfo());
    }

    @RequestMapping(value = "logout", method = RequestMethod.GET)
    public SaResult logout() {
        StpUtil.logout();
        return SaResult.ok();
    }

}

Sa-Token的攔截器,許可權

/**
 * @description: 獲取當前賬號許可權碼集合
 * @author: GuoTong
 * @createTime: 2022-11-29 20:24
 * @since JDK 1.8 OR 11
 **/
@Component
@Slf4j
public class StpInterfaceImpl implements StpInterface {

    @Autowired
    private AuthLoginUserService authLoginUserService;

    /**
     * 返回一個賬號所擁有的許可權碼集合
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        AuthLoginUser user = null;
        try {
            user = authLoginUserService.getById(loginId.toString());
        } catch (Exception e) {
            log.info("Id無效--->{}", loginId);
        }
        assert user != null;
        String rule = user.getRule();
        return Collections.singletonList(rule);
    }

    /**
     * 返回一個賬號所擁有的角色標識集合 (許可權與角色可分開校驗)
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        AuthLoginUser user = null;
        try {
            user = authLoginUserService.getById(loginId.toString());
        } catch (Exception e) {
            log.info("Id無效--->{}", loginId);
        }
        assert user != null;
        String rule = user.getRule();
        return Collections.singletonList(rule);
    }

}

自定義攔截器,校驗Sa-Token登入

/**
 * @description: 授權認證:HandlerInterceptor需要註冊攔截地址哦!!!
 * @author: GuoTong
 * @createTime: 2022-11-05 15:40
 * @since JDK 1.8 OR 11
 **/
@Component
public class AuthenticationInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
        //  獲取當前對談是否已經登入,返回true=已登入,false=未登入
        String requestURI = httpServletRequest.getRequestURI();
        // 判斷是否是認證中心對外認證介面
        if (requestURI.contains("/sso")) {
            return true;
        }

        // 如果不是對映到方法直接通過
        if (!(object instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) object;
        Method method = handlerMethod.getMethod();
        //檢查是否有SkipTokenByJWT註釋,有則跳過認證
        if (method.isAnnotationPresent(SkipTokenByJWT.class)) {
            SkipTokenByJWT SkipTokenByJWT = method.getAnnotation(SkipTokenByJWT.class);
            if (SkipTokenByJWT.required()) {
                return true;
            }
        }
        // 否則需要登陸
        if (!StpUtil.isLogin()) {
            throw new NotLoginException(ContextCommonMsg.ERROR_MSG_4);
        }
        //檢查有沒有需要使用者許可權的註解
        if (method.isAnnotationPresent(NeedTokenByJWT.class)) {
            NeedTokenByJWT needTokenByJWT = method.getAnnotation(NeedTokenByJWT.class);
            if (needTokenByJWT.required()) {
                List<String> permissionList = StpUtil.getPermissionList();
                // 檢視當前使用者是否包含當前介面的許可權
                if (!permissionList.contains(needTokenByJWT.rule())) {
                    throw new NotLoginException(ContextCommonMsg.ERROR_MSG_3);
                }
            }
        }
        return true;
    }


    @Override
    public void postHandle(HttpServletRequest httpServletRequest,
                           HttpServletResponse httpServletResponse,
                           Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest,
                                HttpServletResponse httpServletResponse,
                                Object o, Exception e) throws Exception {
    }

}

全域性異常捕獲

/**
 * @description: 全域性例外處理:
 * @author: GuoTong
 * @createTime: 2022-11-27 11:17
 * @since JDK 1.8 OR 11
 **/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    // 全域性異常攔截
    @ExceptionHandler
    public SaResult handlerException(Exception e) {
        e.printStackTrace();
        log.error("服務執行異常---->{}", e.getMessage());
        return SaResult.error(e.getMessage());
    }

    @ExceptionHandler(value = NotLoginException.class)
    public SaResult handlerException(NotLoginException e) {
        log.error("沒有登陸---->{}", e.getMessage());
        return SaResult.error(e.getMessage());
    }

    @ExceptionHandler(value = SQLException.class)
    public SaResult msgMySQLExecuteError(Exception e) {
        e.printStackTrace();
        log.error("Mysql執行異常");
        String message = e.getMessage();
        return SaResult.error(message);
    }

    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    public SaResult msgNotFind(Exception e) {
        e.printStackTrace();
        log.error("請求錯誤");
        String message = e.getMessage();
        return SaResult.error("請求內容未傳遞" + message);
    }
}

Springboot設定-跨域-註冊攔截器-設定靜態資源過濾-RestTemplate負載均衡

/**
 * @description: SpringBoot-Web設定
 * @author: GuoTong
 * @createTime: 2023-06-05 15:37
 * @since JDK 1.8 OR 11
 **/
@Configuration
public class SpringBootConfig implements WebMvcConfigurer {


    /**
     * Description: 增加攔截器
     *
     * @param registry
     * @author: GuoTong
     * @date: 2022-11-30 13:56:44
     * @return:void
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthenticationInterceptor()).addPathPatterns("/authLoginUser/**");
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }


    /**
     * Description:  新增全域性跨域CORS處理
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 設定允許跨域的路徑
        registry.addMapping("/**")
                //設定允許跨域請求的域名
                .allowedOriginPatterns("*")
                // 是否允許證書
                .allowCredentials(true)
                // 設定允許的方法
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                // 設定允許的header屬性
                .allowedHeaders("*")
                // 跨域允許時間
                .maxAge(3600);
    }


    /**
     * Description: 靜態資源過濾
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //ClassPath:/Static/** 靜態資源釋放
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        //釋放swagger
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
        //釋放webjars
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

。。。。其餘的東西詳見專案。。。。。
https://gitee.com/gtnotgod/sa-token-sso-system.git

演示

認證中心登入頁地址

介面管理認證中心使用者

A系統USER-SERVICE

依賴

  <!--lombok-實體類簡化依賴-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- Sa-Token 許可權認證, 線上檔案:https://sa-token.cc -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-spring-boot-starter</artifactId>
            <version>${Sa-Token-version}</version>
        </dependency>
        <!-- Sa-Token 外掛:整合SSO -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-sso</artifactId>
            <version>${Sa-Token-version}</version>
        </dependency>

        <!-- Sa-Token 整合redis (使用jackson序列化方式) -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-dao-redis-jackson</artifactId>
            <version>${Sa-Token-version}</version>
        </dependency>

        <!-- Sa-Token外掛:許可權快取與業務快取分離 -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-alone-redis</artifactId>
            <version>${Sa-Token-version}</version>
        </dependency>

        <!--Open feign 服務間通訊HTTP-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>${spring-cloud-starter-version}</version>
        </dependency>

        <!--Http內建的JDKHttpURLConnection替換為OkHttp-->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-okhttp</artifactId>
            <version>${feign-okhttp-version}</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
            <version>${fastJson-version}</version>
        </dependency>
        <!--web專案驅動-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot-start-version}</version>
        </dependency>
        <!--Knife4j(增強Swagger)-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>${knife4j.version}</version>
        </dependency>

        <!-- bootstrap最高階啟動設定讀取 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
            <version>${spring-cloud-starter-version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>3.1.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

核心 SSO-Client 端認證介面


/**
 * @description: 建立 SSO-Client 端認證介面
 * @author: GuoTong
 * @createTime: 2022-11-27 15:32
 * @since JDK 1.8 OR 11
 **/
@RestController
public class SSOClientController {


    /*
     * 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 SaSsoProcessor.instance.clientDister();
    }


    // 首頁
    @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);\">Login</a> " +
                "<a href='/sso/logout?back=self'>Logout</a></p>";
        return str;
    }
}

攔截器和認證中心的AuthenticationInterceptor一致

核心全域性例外處理

 @ExceptionHandler(value = NotLoginException.class)
    public Resp handlerException(NotLoginException e,
                                 HttpServletRequest request,
                                 HttpServletResponse response) {
        log.error("沒有登陸---->{}", e.getMessage());
        try {
            response.sendRedirect("/sso/login?back=" + request.getRequestURL());
        } catch (IOException ex) {
            log.error("轉到認證中心失敗---->{}", ex.getMessage());
        }
        return Resp.error(e.getMessage());
    }

核心設定

spring:
  redis:
    # Redis資料庫索引(預設為0)
    database: 1
    # Redis伺服器地址
    host: 127.0.0.1
    # Redis伺服器連線埠
    port: 6379
    # Redis伺服器連線密碼(預設為空)
    password: 123456
    timeout: 10s
    lettuce:
      pool:
        # 連線池最大連線數
        max-active: 20
        # 連線池最大阻塞等待時間(使用負值表示沒有限制)
        max-wait: 10000
        # 連線池中的最大空閒連線
        max-idle: 3
        # 連線池中的最小空閒連線
        min-idle: 0
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher  #Springboot2.6以上需要手動設定
    static-path-pattern: classpath:/static/**
  main:
    allow-bean-definition-overriding: true      # 重複定義bean的問題
logging:
  level:
    root: info
    org.springframework: info

# sa-token設定
sa-token:
  # SSO-相關設定
  sso:
    # SSO-Server端 統一認證地址
    auth-url: http://localhost:15001/sso/auth
    # 是否開啟單點登出介面
    is-slo: true
  # 設定Sa-Token單獨使用的Redis連線 (此處需要和SSO-Server端連線同一個Redis)
  alone-redis:
    # Redis資料庫索引
    database: 1
    # Redis伺服器地址
    host: 127.0.0.1
    # Redis伺服器連線埠
    port: 6379
    # Redis伺服器連線密碼(預設為空)
    password: 123456
    # 連線超時時間
    timeout: 10s
    lettuce:
      pool:
        # 連線池最大連線數
        max-active: 200
        # 連線池最大阻塞等待時間(使用負值表示沒有限制)
        max-wait: -1ms
        # 連線池中的最大空閒連線
        max-idle: 10
        # 連線池中的最小空閒連線
        min-idle: 0
forest:
  log-enabled: false   # 關閉 forest 請求紀錄檔列印

。。。。其餘的東西詳見專案。。。。。
https://gitee.com/gtnotgod/sa-token-sso-system.git

演示

輸入測試介面:http://user.server.com:13601/hello/getOne1/100011

被重定向到認證中心去了

登入存取後

同理準備好B服務THIRD-PARTY-SERVICE

選擇登出A服務和B服務的其中一個;前提是沒有登入多個賬號

登出A服務 http://user.server.com:13601/sso/logout
登出B服務http://third.server.com:14302/sso/logout


A服務feign呼叫B服務

具體介面程式碼:

 /**
     * 通過主鍵查詢單條資料
     *
     * @param id 主鍵
     * @return 單條資料
     */
    @GetMapping("/queryOne/{id}")
    public Resp<Object> selectOne(@PathVariable("id") String id) {
        return Resp.Ok(this.openFeignRPCMySQlService.selectOne(id));
    }

fegin介面

/**
 * @description: OpenFegin呼叫third-party-service服務
 * @FeignClient(name = "third-party-service")  name指定呼叫的服務名
 * @author: GuoTong
 * @createTime: 2022-12-02 19:39
 * @since JDK 1.8 OR 11
 **/
@FeignClient(name = "third-party-service")
public interface OpenFeignRPCMySQlService {

    /**
     * Description:  feign呼叫third-party-service服務的介面
     *
     * @author: GuoTong
     * @date: 2022-12-02 20:56:28
     * @return:
     */
    @GetMapping(value = "/hello/getOne2/{id}", produces = "application/json;charset=utf-8")
    Resp<Object> selectOne(@PathVariable("id") String id);


}

輸入地址 http://user.server.com:13601/hello/queryOne/100011

重定向認證中心

登入A系統

fegin呼叫成功B系統

A系統已經登入,B系統未登入,存取B系統介面fegin呼叫A

不再重定向到認證中心,A已經登入,B已完成單點,校驗已持有登入狀態

登出A系統

http://user.server.com:13601/sso/logout

B系統再呼叫本系統的介面

已經重定向到認證中心

fegin呼叫A系統 :http://third.server.com:14302/hello/queryOne/100011

依舊重定向到認證中心

到此單點登入演示實現完畢;

個人專案地址,在gitee:https://gitee.com/gtnotgod/sa-token-sso-system.git

tip: 更多Sa-Token使用教學參考官方地址:https://sa-token.cc/doc.html