单点登录详解(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,如果验证成功,就向客户端返回请求的数据
posted @ 2021-02-19 22:53  慎终若始  阅读(5102)  评论(1编辑  收藏  举报