根据存储cookie来进行判断。实现单点登录。以及基于redis进行缓存数据
一、创建SSO登录页面,进行其他服务时都会跳转到登陆页面中在idea中创建 login.html 登陆页面
Login Module
欢迎来到登陆页面
在idea中创建 logout.html 退出页面
退出成功
退出成功,欢迎下次光临
SSO单点项目依赖
4.0.0 com.jt sso-springbootCS1.0-SNAPSHOT org.springframework.boot spring-boot-dependencies2.3.2.RELEASE pom import org.springframework.cloud spring-cloud-dependenciesHoxton.SR9 pom import com.alibaba.cloud spring-cloud-alibaba-dependencies2.2.6.RELEASE pom import org.springframework.boot spring-boot-starter-data-rediscom.alibaba fastjsoncom.baomidou mybatis-plus-boot-starter3.3.1.tmp org.springframework.boot spring-boot-starter-weborg.springframework.boot spring-boot-starter-thymeleafmysql mysql-connector-javaorg.projectlombok lombokprovided org.springframework.boot spring-boot-starter-testorg.junit.jupiter junit-jupiter-enginecom.alibaba fastjson1.2.60 compile org.apache.maven.plugins maven-compiler-plugin3.8.1 8 8
application.yml 配置
#配置端口号
server:
port: 8091
#管理数据源
spring:
datasource:
#高版本驱动使用
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/sso?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
#设定用户名和密码
username: root
password: root
#链接-----redis
redis:
host: 192.168.232.126
port: 6379
#SpringBoot整合Mybatis
mybatis:
#指定别名包
type-aliases-package: com.jt.pojo
#扫描指定路径下的映射文件
mapper-locations: classpath:/mapper
@Slf4j
@Controller
@RequestMapping("/ds")
public class qqqqController {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private UserMapper userMapper;
@PostMapping("/login") //从页面获取账号密码 判断没有token时跳转到登陆页面
public String login(HttpSession session,HttpServletRequest request,HttpServletResponse response) {
// String userName = jsonObject.get("username").toString();
// String password = jsonObject.get("password").toString();
String userName = "admin";
String password = "admin";
try {
//获取重定向的页面
String target = session.getAttribute("target").toString();
Map user = userMapper.findByUserName(userName);// 根据账号获取信息
String name = user.get("username");
String word = user.get("password");
if (password.equals(word)) {
//添加到----------------redis------------------服务器redis
String token = UUID.randomUUID().toString();
redisTemplate.opsForValue().set(token,user.toString()); //将用户信息存入redis中
//需要添加时效 -----添加cookie-----------------客户端 要是再子系统间访问的话,域是必须相同的
Cookie c = new Cookie("ssoToken", token.toString());// 新建一个Cookie对象
//c.setDomain("localhost");
c.setPath("/");
response.addCookie(c);//通过response响应数据
String value = c.getValue();
System.out.println("valueA = " + value);
return "redirect:" + target;//重定向地址,target地址 前面的字符串必须写对,否则报错
} else {
//登陆失败
session.setAttribute("msg","用户名或密码错误");
return "login";
}
}catch (NullPointerException e){
String target = "http://localhost:8092/wy/index";
return "redirect:" + target;
}
}
@GetMapping("/info") //点击任何页面功能时,先调用此方法进行验证token 此处将token传过来
@ResponseBody
public ResponseEntity checkToken(String token) throws JsonProcessingException {
if (!StringUtils.isEmpty(token)){
try {
String s = redisTemplate.opsForValue().get(token).toString();
System.out.println("s = " + s);
}catch (NullPointerException e){
User user = new User("admin","admin");//此处获取用户信息 此处简写了
return ResponseEntity.ok(user);
}
User user = new User("admin","admin");
return ResponseEntity.ok(user);
}
else {
return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);//错误的请求,要token没得到
}
}
}
创建sso页面跳转逻辑controller
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@Controller
@RequestMapping("/view")
public class ViewController {
@Autowired
private RedisTemplate redisTemplate;
@GetMapping("/login")
public String tologin(@RequestParam(required = false,defaultValue = "") String target
, HttpSession session,
@CookieValue(required = false,value = "ssoToken")Cookie cookie,
HttpServletResponse response) {
if (StringUtils.isEmpty(target)){
target = "http://localhost:8092/wy/index";//如果为空设定地址到首页
}
//如果是已经登陆的用户再次访问登录系统时,就要重定向
if (cookie!=null){
String value = cookie.getValue();//获取token
System.out.println("value = " + value);
try {
String s = redisTemplate.opsForValue().get(value).toString(); //没有设置过期时间,后期可以加上
System.out.println("s = " + s);
if (s != null){
System.out.println("ok");
return "redirect:" + target;
}
}catch (NullPointerException e){
session.setAttribute("target",target);
return "login";//跳转到登陆页面
}
}
// cookie.setMaxAge(0);
// response.addCookie(cookie);
//TODO:此处应该有校验地址是否合法的校验
//重定向的地址
session.setAttribute("target",target);
return "login";//跳转到登陆页面
}
@GetMapping("/logout") //清除缓存 token
public String logout(@CookieValue(required = false,value = "ssoToken")Cookie cookie,
HttpServletResponse response) {
String value = cookie.getValue();
System.out.println("value = " + value);
redisTemplate.opsForValue().get(value);
redisTemplate.delete(value);
//将cookie的有效期设置为0,命令浏览器删除该cookie
cookie.setMaxAge(0);
response.addCookie(cookie);
System.out.println("cookie = " + cookie);
return "logout";
}
}
创建User类,链接数据库,验证登陆用户账号密码信息。
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@TableName("user")
public class User implements Serializable {
@TableField(value = "username")
private String username; //账号
@TableField(value = "password")
private String password; //密码
}
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
@Mapper
public interface UserMapper {
Map findByUserName(String username);
}
启动项目进行网页浏览
二、创建wy服务页面创建 index.html 链接跳转到sso登陆页面
wy
欢迎来到wy
登陆
退出登录
启动类中添加 RestTemplate 方法
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class wyApplication {
public static void main(String[] args) {
SpringApplication.run(wyApplication.class, args);
}
@LoadBalanced//通过这个注解描述对象。底层会调用一个拦截器并进行负载均衡的算法
@Bean
public RestTemplate loadBalanced1() {
return new RestTemplate();
}
@Primary //在配置类配置RestTemplate时,分别配置负载均衡与默认优先选择,即写两个RestTemplate方法 (因为调用报错)
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
创建wy的controller
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Map;
@Controller
@RequestMapping("/wy")
public class WyController {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private RestTemplate restTemplate;//发送http请求的工具
@Value("${spring.application.name:sso-springbootCS}")
String appname;//获得执行的服务对象的名字
@GetMapping("/index")
public String index(@CookieValue(required = false,value = "ssoToken")Cookie cookie, HttpSession session) {
if (cookie!=null){
String token = cookie.getValue();
System.out.println("校验token = " + token);
if (!StringUtils.isEmpty(token)){
//通过骨架给其赋值 会自动拦截 并且根据要进行调用的服务的名字匹配端口号和id
String url = String.format("http://localhost:8091/ds/info?token=",appname);
//此处发送请求到校验地址 、ds/info 携带token 进行校验
String result = restTemplate.getForObject(url + token, String.class);
// session.setAttribute("loginUser",s); 将数据返回给前端 获得登录账号信息
System.out.println("result = " + result);//查看数据
}
}
return "index"; //返回的原因是要跳转到index页面
}
}
查看页面
多个服务都可同上 ,此处是两个 sso-wy1 ssp-vip
以上代码完成后进行启动所有的服务。然后进行验证http://localhost:8092/wy/index
http://localhost:8093/wy/index
当登陆第一个8092,输入账号密码确认后再登陆8093即不会再进行跳转到登陆页面。
如果登陆成功则会跳转到目标页面,target携带目标页面。
进来后,一直点击登陆不会再进行跳转到登陆页面了。因为验证了cookie中的token
当其中一个点击退出时,所有的服务就需要重新登陆才行



