简单聊一聊单点登录

一、单点登录

  单点登录(SingleSignOn,SSO),就是通过用户的一次性鉴别登录。当用户在身份认证服务器上登录一次以后,就可以获得访问单点登录系统中其他关联系统和应用软件的权限,同时这种实现是不需要管理员对用户的登录状态或其他信息进行修改的,这意味着在多个应用系统中,用户只需一次登录就可以访问所有相互信任的应用系统。这种方式减少了由登录产生的时间消耗,辅助了用户管理,是比较流行的。总结就是一处登录,处处可用。

二、演示步骤

①简单结构(域名的设置)

 Windows里面修改域名的地方:C:\Windows\System32\drivers\etc下面的hosts文件里面,打开hosts文件,在最后加上以下的信息即可。

127.0.0.1  sso.com 
127.0.0.1  client1.com
127.0.0.1  client2.com

在这里插入图片描述
joke:双11的时候,害怕女朋友剁手,把 www.taobao域名映射到本机,一直访问就访问不到。
  核心:三个系统即使域名不一样,想办法给三个系统同步同一个用户的数据;
  1)中央认证服务器:sso.com;
  2)其他系统,想要登录去sso.com登录,登录成功跳转回来;
  3)只要有一个登录,其他都不用登录;
  4)全系统统一一个sso-sessionid;所有系统可能域名都不相同;

②创建项目

  1)利用Spring的初始化向导,创建单点登录服务器,将web、thymeleaf和lombok选中即可。以此创建三个模块。
在这里插入图片描述

1.sso-server 模块代码

在这里插入图片描述

LoginController代码如下

package com.atguigu.gulimall.ssoserver.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

@Controller
public class LoginController {
    
    

    @Autowired
    StringRedisTemplate redisTemplate;
    @ResponseBody
    @GetMapping("/userInfo")
    public String userInfo(@RequestParam("token") String token){
    
    
        String s = redisTemplate.opsForValue().get(token);
        return s;
    }
    @GetMapping("/login.html")
    public String loginPage(@RequestParam("redirect_url") String url, Model model,
                            @CookieValue(value = "sso_token",required = false) String sso_token){
    
    
        if (!ObjectUtils.isEmpty(sso_token)){
    
    
            //说明之前有人登录过,浏览器留下了痕迹
            return "redirect:"+url+"?token="+sso_token;
        }
        model.addAttribute("url",url);
        return "login";
    }
    @PostMapping("/doLogin")
    public String doLogin(@RequestParam("username") String username,
                          @RequestParam("password") String password,
                          @RequestParam("url") String url,
                          HttpServletResponse response){
    
    
        if(!ObjectUtils.isEmpty(username) && !ObjectUtils.isEmpty(password)){
    
    
            //登录成功,跳回之前页面
            //把登录成功的用户存起来
            String uuid= UUID.randomUUID().toString().replace("-","");
            redisTemplate.opsForValue().set(uuid,username);
            Cookie sso_token = new Cookie("sso_token",uuid);
            response.addCookie(sso_token);
            return "redirect:"+url+"?token="+uuid;
        }
        //登录失败,展示登录页
        return "login";
    }
}

GulimallTestSsoServerApplication启动类代码

package com.atguigu.gulimall.ssoserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GulimallTestSsoServerApplication {
    
    

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

}

login.html代码

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>登录页</title>
</head>
<body>
  <form action="/doLogin" method="post">
    用户名:<input name="username" /><br/>
    密码:<input name="password" type="password"/><br/>
      <input type="hidden" name="url" th:value="${url}"/>
    <input type="submit" value="登录"/>
  </form>
</body>
</html>

application.properties配置文件

server.port=8080

spring.redis.host=127.0.0.1

pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.atguigu</groupId>
    <artifactId>gulimall-test-sso-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>gulimall-test-sso-server</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2.sso-client1模块代码

在这里插入图片描述

HelloController代码

package com.atguigu.gulimall.ssoclient1.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;

@Controller
public class HelloController {
    
    
    @Value("${sso.server.url}")
    String ssoServerUrl;
    /**
     * 无需登录就可访问
     * @return
     */
    @ResponseBody
    @GetMapping("/hello")
    public String hello() {
    
    
        return "hello world";
    }

    /**
     * 感知是在登录之后跳转回来的,而不是我们直接访问的
     * @param model
     * @param session
     * @Param token 只要去sso登录成功跳回来就会带上
     * @return
     */
    @GetMapping("/employees")
    public String employees(Model model, HttpSession session,
                            @RequestParam(value = "token",required = false) String token){
    
    
        if(!ObjectUtils.isEmpty(token)){
    
    
            //去sso登录成功跳回来就会带上
            //TODO 1.去sso获取当前token真正对应的用户信息
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> forEntity = restTemplate.getForEntity("http://sso.com:8080/userInfo?token=" + token, String.class);
            String body = forEntity.getBody();
            session.setAttribute("loginUser",body);
        }
        Object loginUser = session.getAttribute("loginUser");
        if (loginUser==null) {
    
    
            //没有登录,就跳转到登录服务器进行登录
            //跳转过去以后,使用url上的查询参数表示我们自己是哪一个页面
            //redirect_url=http://client1.com:8081/employees
            return "redirect:"+ssoServerUrl+"?redirect_url=http://client1.com:8081/employees";
        }else{
    
    
            List<String> emps = new ArrayList<>();
            emps.add("张三");
            emps.add("李四");
            model.addAttribute("emps",emps);
            return "list";
        }
    }
}

GulimallTestSsoClient1Application

package com.atguigu.gulimall.ssoclient1;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GulimallTestSsoClient1Application {
    
    

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

}

list.html代码

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>员工列表</title>
</head>
<body>
    <h1>欢迎:[[${
    
    session.loginUser}]]</h1>
    <ul>
        <li th:each="emp: ${emps}"> 姓名:[[${
    
    emp}]] </li>
    </ul>
</body>
</html>

application.properties

server.port=8081

sso.server.url=http://sso.com:8080/login.html

pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.atguigu</groupId>
    <artifactId>gulimall-test-sso-client1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>gulimall-test-sso-client1</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

3.sso-client2模块

在这里插入图片描述

HelloController代码

package com.atguigu.gulimall.ssoclient2.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;

@Controller
public class HelloController {
    
    
    @Value("${sso.server.url}")
    String ssoServerUrl;
    /**
     * 无需登录就可访问
     * @return
     */
    @ResponseBody
    @GetMapping("/hello")
    public String hello() {
    
    
        return "hello";
    }

    /**
     * 感知是在登录之后跳转回来的,而不是我们直接访问的
     * @param model
     * @param session
     * @Param token 只要去sso登录成功跳回来就会带上
     * @return
     */
    @GetMapping("/boss")
    public String employees(Model model, HttpSession session,
                            @RequestParam(value = "token",required = false) String token){
    
    
        if(!ObjectUtils.isEmpty(token)){
    
    
            //去sso登录成功跳回来就会带上
            //TODO 1.去sso获取当前token真正对应的用户信息
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> forEntity = restTemplate.getForEntity("http://sso.com:8080/userInfo?token=" + token, String.class);
            String body = forEntity.getBody();
            session.setAttribute("loginUser",body);
        }
        Object loginUser = session.getAttribute("loginUser");
        if (loginUser==null) {
    
    
            //没有登录,就跳转到登录服务器进行登录
            //跳转过去以后,使用url上的查询参数表示我们自己是哪一个页面
            //redirect_url=http://client1.com:8081/employees
            return "redirect:"+ssoServerUrl+"?redirect_url=http://client2.com:8082/boss";
        }else{
    
    
            List<String> emps = new ArrayList<>();
            emps.add("张三");
            emps.add("李四");
            model.addAttribute("emps",emps);
            return "list";
        }
    }
}

GulimallTestSsoClient2Application代码

package com.atguigu.gulimall.ssoclient2;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GulimallTestSsoClient2Application {
    
    

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

}

list.html代码

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>员工列表</title>
</head>
<body>
    <h1>欢迎:[[${
    
    session.loginUser}]]</h1>
    <ul>
        <li th:each="emp: ${emps}"> 姓名:[[${
    
    emp}]] </li>
    </ul>
</body>
</html>

application.properties配置文件

server.port=8082

sso.server.url=http://sso.com:8080/login.html

pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.atguigu</groupId>
    <artifactId>gulimall-test-sso-client2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>gulimall-test-sso-client2</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

三、演示流程

测试视频

单点登录

视频地址:https://www.bilibili.com/video/BV1Wa411Y7cr/

猜你喜欢

转载自blog.csdn.net/faramita_of_mine/article/details/124334562