谷粒商城——单点登录流程

SSO(单点登录)

Single Sign On 一处登录、处处可用

单点登录
在这里插入图片描述

一、 单点登录业务介绍

早期单一服务器,用户认证

在这里插入图片描述

缺点:单点性能压力,无法扩展

WEB应用集群,session共享模式

在这里插入图片描述

解决了单点性能瓶颈。

问题:

1、 多业务分布式数据独立管理,不适合统一维护一份session数据。

2、 分布式按业务功能切分,用户、认证解耦出来单独统一管理。

3、 cookie中使用jsessionId 容易被篡改、盗取。

4、 跨顶级域名无法访问。

分布式,SSO(single sign on)模式

在这里插入图片描述

解决 :

用户身份信息独立管理,更好的分布式管理;可以自己扩展安全策略;跨域不是问题

缺点:认证服务器访问压力较大。

业务流程图
在这里插入图片描述

二、示例

1、分布式单点登录框架XXL-SSO
2、自行搭建

创建springboot项目 gulimall-sso-server gulimall-sso-client

gulimall-sso-server 服务

登录服务器

1、引入依赖
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </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-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
2、application.yaml配置
server:
  port: 8080
#redis配置
  redis: 
    host: xxx
    port: 6379
  
3、resource下添加login页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页</title>
</head>
<body>
    <form action="/doLogin" method="post">
        用户名:<input type="text" name="username" /><br />
        密码:<input type="password" name="password" /><br />
        <input type="hidden" name="redirect_url" value="http://localhost:8081/employees" />
        <input type="submit" value="登录">
    </form>
</body>
</html>
4、LoginController
package com.xunqi.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.StringUtils;
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(value = "token") String token) {
        String s = redisTemplate.opsForValue().get(token);
        return s;
    }

    /**
    如果携带了cookie,登录成功
    */
    @GetMapping("/login.html")
    public String loginPage(@RequestParam("redirect_url") String url,
                            Model model, 
                            @CookieValue(value = "sso_token", required = false) String sso_token) {
        if (!StringUtils.isEmpty(sso_token)) {
            return "redirect:" + url + "?token=" + sso_token;
        }
		//前端页面数据需要
        model.addAttribute("url", url);
        //跳到登录页
        return "login";
    }

    /**
      登录
      redirect_url:重定向到客户端的url
    */
    @PostMapping(value = "/doLogin")
    public String doLogin(@RequestParam("username") String username, 
                          @RequestParam("password") String password, 
                          @RequestParam("redirect_url") String url,
                          HttpServletResponse response) {

        //登录成功,携带token 跳回到客户端页面
        if (!StringUtils.isEmpty(username) && !StringUtils.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";
    }
}
gulimall-sso-client
package com.xunqi.gulimall.ssoclient.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
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 {
    @GetMapping(value = "/employees")
    public String employees(Model model,
                            HttpSession session,
                            @RequestParam(value = "token", required = false) String token) {

        if (!StringUtils.isEmpty(token)) {
            //登录成功
            RestTemplate restTemplate=new RestTemplate();
            //获取用户信息
            ResponseEntity<String> forEntity = restTemplate.getForEntity("http://sso.mroldx.cn:8080/userinfo?token=" + token, String.class);
            String body = forEntity.getBody();
            session.setAttribute("loginUser", body);
        }
        Object loginUser = session.getAttribute("loginUser");
        if (loginUser == null) {
            //session里没登录信息,跳到登录服务器,携带参数redirect_url
            return "redirect:" + "http://sso.mroldx.cn:8080/login.html"+"?redirect_url=http://localhost:8081/employees";
        } else {
            List<String> emps = new ArrayList<>();
            emps.add("张三");
            emps.add("李四");
            model.addAttribute("emps", emps);
            return "employees";
        }
    }
}
2.1 业务流程图

在这里插入图片描述

  • 17
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值