zoukankan      html  css  js  c++  java
  • 单点登录详解(token简述)(七)

    前言

    为什么整理单点登录?

    主要的原因还是自己以前学习的时候曾经用过,但是时间太久,忘记了里面用到了哪些技术、及如何实现的,每次想到单点登录总是感觉即会又不会,这次整理session时,又涉及到了单点登录,而且单点登录里面还用到了redis,也是我这次要整理的内容,故而单独把单点登录抽出来,系统的梳理下,以备下次忘记时重温。

    顺便也把以前学习分布式项目中用到的相关技术:double、zookeeper等统一梳理一遍,加强对现在项目的整理架构的理解。

    其实,无论是单一的应用,还是分布式项目乃至现在的微服务技术,其实说到底,思想都是相通的,技术也是相通,只有从底层了解始末,融汇贯通,才会对技术的整体有一个把控,不至于迷失在技术进步的潮流中。       

    一、什么是单点登录

     SSO(Single Sign On)单点登录是实现多个系统之间统一登录的验证系统,简单来说就是:有A,B,C三个系统,在A处登录过后,再访问B系统,B系统就已经处于了登录状态,C系统也是一样。举个生活中栗子:你同时打开天猫和淘宝,都进入login界面,都要求你登录的,现在你在淘宝处登录后,直接在天猫处刷新,你会发现,你已经登录了,而且就是你在淘宝上登录的用户。说明他们实现了SSO,并且持有相同的信息。

    二、为什么要用到单点登录

    一次登录,多处使用。

    三、单点登录的实现

    3.1自己什么时候用过单点登录

    培训时,做的ego项目里搭建过一个单点登录的子系统。说白了,就是类似于京东、淘宝这样的一个电商项目。因为采用的是分布式项目结构,各个模块分别是一个单独的应用,分属不同的服务器,想要实现一处登录,多处使用,肯定不能再用session了。

    3.2 实现思路

    我们这里的实现思路如下:

    Redis+Cookie实现模拟Session功能,实现登录功能。

    • 适应场景 :分布式系统中,才会使用单点登录!
    • 说明:在分布式项目中,一次登录,项目之间共享登录状态。
    • 思路:
      • 单独有一个登录(还包含注册等)项目;
      • 所有其他项目需要登录,或需要使用用户登录后状态都向登录项目进行请求。

    3.3为什么不能用session与cookie实现

    1、跨服务器了,所以不能用session;

    2、cookie的话,是存放在浏览器端的,不安全;而且用户也可以禁用cookie(这里指的是存放在本地的cookie,不是会话cookie)。

    3、放到注册中心,zookeeper:不行,如果挂了就不知道用户是否登录了。(联想到了dubbo的健壮性)

     4、放到redis里,redis可以搞集群,一个宕机了也没事。

    3.3 代码

    1、关于代码不再进行copy,相关的具体实现已经看过代码及视频了,这里只对实现的思路及过程进行说明。

    2、思路

    1.用户登录
        1.1 用户登录的时候,向cookie中添加了一个TT_TOKEN值。
        1.2 同时,还需要向redis中添加一个user对象  key = user:token value = user对象的json字符串
    2.一处登录多处使用    
        2.1 每个页面加载的时候,需要check。当前Cookie[TT_TOKEN]中是否有值
        2.2 如果有TT_TOKEN,从redis中将对象取出来!
    3.退出的时候:
        3.1 删除cookie 中 TT_TOKEN
        3.2 删除redis中的值!

    详细的代码参看下面的部分主要代码。

    3、发送请求时相关参数,可以看到有cookie信息。

    4、redis存的用户信息

    3.3.1 登录功能

    登录的功能是在一个单独的项目ego1-passport中实现的。

    具体步骤

    1.    需求分析:将登录的信息存放到redis中,目的是想做sso!
    1.1 登录控制器接收接收两个参数username和password
    1.2 调用Dubbo服务判断用户是否登录成功.
    1.3 产生Cookie,存放UUID
    1.4 把用户信息放入到Redis中.
    1.5     从哪里跳转到登录页面,再跳转回去那个页面.
    2.    实现过程,新建一个项目ego-passport,选择war类型。
    3.    导入相关的配置文件。Pom.xml,web.xml,spring相关配置文件。

    详细代码可以看笔记、视频去。

    1、登录方法部分代码

    @Value("${redis.user.key}")
        private String key;
        
        @Override
        public EgoResult login(TbUser user, HttpServletRequest request, HttpServletResponse response) {
            EgoResult er = new EgoResult();
            // 根据数据库查询,查询出来之后,需要放到Redis中
            TbUser user2 = tbUserDubboService.selByUser(user);
            if (user2!=null) {
                String uuid = UUID.randomUUID().toString();
                // cookieName 是根据前台js来确定。
                CookieUtils.setCookie(request, response, "TT_TOKEN", uuid);
                // 需要存储到redis 中 key组成是由key+uuid  user:uuid  user:65bedb06-9931-4fe8-9eb7-7fe1f8846d0b
                // value:实体类对象登录对象
                jedisPoolDaoImpl.set(key+uuid, JsonUtils.objectToJson(user2));
                // 返回值是根据易购商城接口sso登录来确定
                er.setMsg("OK");
                er.setStatus(200);
            }
            return er;
        }

    可以看出来,在登录时,实现了如下操作:

    • 先查库,看有没有这个用户;
    • 用户存在的话,会在cookie里添加新值,key为token(这里命名为TT_TOKEN),value为uuid。
    • 将用户信息放在redis中,key为user:uuid,value为用户对象转译的json串。

    为什么会用到cookie?

    如下截图,其他服务页面在访问时,会通过cookie,获取token,来校验,如果不存在token的话,会返回,跳转到登录界面。

     

     需要理解到的是,这里的cookie是一个会话cookie。

    为什么要用token?

    校验用户是否登录;

    通过token,从redis中获取用户信息;

    说白了,token就相当于一张通票,一处登陆(相当于买了一张通票,有了它,各个分园都可以去),处处使用(各个服务器都无需再次登录,并且可以通过token去redis中获取到用户信息)。

    token是什么?

    在下面的延伸里有说明。其实,这里的token值,就是自己编写的一个随机uuid,然后放到了cookie中。它在这个分布式项目中就是起到了一个唯一标识并记录(存在cookie里了)用户信息的作用。是用户登录的凭证。

    1、用户登录的请求及返回信息简略

    3.3.2 在ego-portal中当用户登录成功后,在最上面显示用户信息

    通过token,从redis中获取用户信息。

    请求及返回参数示例:

    3.3.3 退出功能

    删除redis,同时删除cookie。

    关于sso的介绍与使用,也可以参考下面的链接:https://blog.csdn.net/zhangjingao/article/details/81735041

    四、延伸

    4.1 复习HttpSession和Cookie

    4.1.1 HttpSession

    2.1 session中文名称:会话.浏览器开启到关闭的这段时间!

    2.2 如何产生的?

    2.2.1 在request.getSession();才能产生Session,产生完成后占用系统内存的.

    2.3  Session原理.

    1、创建Session的时候,服务器将生成一个唯一的sessionid然后用它生成一个关闭浏览器就会失效的cookie[JSESSIONID是cookie产生]。
    
     
    
    2、然后再将一个与这个sessionid关联的数据项加入散列表。
    
        例如这样一段代码:Session["UserName"]=23;
    
        假设sessionid为123那么散列表中会追加一行
    
         sessionid          username
    
         123                  23
    
     
    
    3、当浏览器端提交到服务器时,会通过sessionid=123去散列表中寻找属于该用户的Session信息。

    4.1.2 cookie

    1.1 解释:客户端存值技术。

    1.1.1 存储位置:内容存放在客户端浏览器中。

    1.1.2 可以存储什么类型的值:只能存储文本数据(字符串)。

    1.2 Cookie流程

    1.2.1 步骤1: 客户端向服务器端发送请求时,浏览器会自动携带所有能获取的Cookie内容.放在请求对象中。

    1.2.2 步骤2:所有Cookie产生位置都是服务器端.在服务器端可以创建任意和key-value形式的Cookie对象.并把cookie对象放入到response对象中。

    1.2.2.1 在servlet或jsp脚本中Cookie c=new Cookie(“”,””)。

    1.2.2.2服务器端通过request.getCookies()获取cookie。

    1.2.3 步骤3:把Cookie响应给客户端(重定向)。

    1.2.4 步骤4:浏览器接收到响应后,会从响应对象中获取到Cookie内容,并把Cookie内容存储在指定位置。

    1.3Cookie几个概念。

    1.3.1 有效时间:

    1.3.1.1 默认与Session对象有效时间相同.

    1.3.1.2 手动设置Cookie有效时间,固定有效时间.不刷新

    //有效时间秒
     c.setMaxAge(10);

    1.3.2 可访问路径问题.

    1.3.2.1 设置完成后cookie只能被当前目录及子目录进行访问。

    /cookie/jsp/ : cookie表示项目名称jsp表示在WebContent目录下的文件夹

    c.setPath("/cookie/jsp/");

    1.3.3 设置可访问域名问题。

     //防止其他网站获取cookie内容
    
         c.setDomain("localhost");

    案例:

    @WebServlet("/TCookie")
    public class TCookie extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        // servlet : 中核心方法:service() 方法是处理请求的method="post/get"。
        // 如果请求的是get,则会有service()方法,将请求发送给doGet()方法处理,post---doPost();
        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 1.创建cookie
            Cookie cookie = new Cookie("name", "admin");
    
            // 设置cookie 的生命周期
            // cookie.setMaxAge(10);
            // 设置一个访问路径
            // cookie.setPath("/testcookie/jsp/");
            // 设置一个域名方法
            cookie.setDomain("localhost");
            // 2.将cookie添加到response中
            response.addCookie(cookie);
            // 3.将cookie发送到客户端
            response.sendRedirect("index.jsp");
        }
    }

    前端:

    /testcookie/jsp/index1.jsp
    <body>
    <h1>index1 ------------</h1>
        <!-- 取cookie -->
        <!-- 使用小脚本来取得cookie对象 -->
        <%
        /* 数组定义:  数据类型 [] 数组名称 = new 数据类型[长度] 基本数据类型,引用数据类型 */
            Cookie [] c = request.getCookies();    
            /* 增强for循环 for(数据类型 变量名 : 数组/集合){} */
            for(Cookie cookie:c){
                /* jsp九大内置对象。谁是输出out */
                out.println(cookie.getName()+"======"+cookie.getValue()+"<br/>");
            }
        %>
    </body>

    4.2 token

     令牌。
    在计算机身份认证中是令牌(临时)的意思,在词法分析中是标记的意思。一般作为邀请、登录系统使用。

    token是计算机术语:令牌,令牌是一种能够控制站点占有媒体的特殊帧,以区别数据帧及其他控制帧。token其实说的更通俗点可以叫暗号,在一些数据传输之前,要先进行暗号的核对,不同的暗号被授权不同的数据操作。基于 Token 的身份验证方法

    使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:

    1.客户端使用用户名跟密码请求登录

    2.服务端收到请求,去验证用户名与密码

    3.验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端

    4.客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里

    5.客户端每次向服务端请求资源的时候需要带着服务端签发的 Token

    6.服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
    如果错过太阳时你流了泪,那你也要错过群星了。
    在所有的矛盾中,要优先解决主要矛盾,其他矛盾也就迎刃而解。
    不要做个笨蛋,为失去的郁郁寡欢,聪明的人,已经找到了解决问题的办法,或正在寻找。
  • 相关阅读:
    最快的进程间通信方式你get了么
    【Java】简易Socket连接实现
    【Java】基于RXTX的Java串口通信
    【Android】WebDav For Android
    【Java】Swing实现一个简单的计算器
    (未完成)【Android】MVP模式初见(一)
    【编译原理】TEST递归下降演示
    【Android】LitePal的基础
    【Flutter】Demo1一个名字生成器
    【Flutter】环境搭建以及HelloWorld创建
  • 原文地址:https://www.cnblogs.com/szrs/p/14406422.html
Copyright © 2011-2022 走看看