一文理解登录鉴权(Cookie、Session、Jwt、CAS、SSO)

1 前言

登录鉴权是任何一个网站都无法绕开的部分,当系统要正式上线前都会要求接入统一登陆系统,一方面能够让网站只允许合法的用户访问,另一方面,当用户在网站上进行操作时也需要识别操作的用户,用作后期的操作审计。

2 Cookie & Session

由于HTTP是无状态的,也就是说,访问某个网站后,下一次再次访问,网站不能够识别出两次访问是否是同一个客户端。因此,为了能够对用户做验证,保障网站只能被合法的用户访问,需要将HTTP改成有状态的,此时就需要Cookie和Session配合使用。

需要识别当前HTTP请求是谁发起,就需要在后端存储用户信息,例如,用户ID、用户名、用户部门等,这些信息就存储在Session中,但是,在一段时间,可能有大量用户访问网站,也就是说,后端应该是存储一个字典,那么,哪一个用户才是当前这个请求的呢?这时就需要使用Cookie,Cookie是存储在客户端(浏览器)中的信息,将Session字典的键存储到客户端,当用户访问网站时,就会携带该Cookie,后端收到请求后,根据Cookie中的键就可以找到Session字典对应的值,也就能够识别当前用户的信息。

请添加图片描述

如上图所示,Cookie的存储形式也相当于KV,因此,最重要的属性就是名字和值。当前浏览器存储了SESSIONID=23456的Cookie,当用户通过该浏览器访问后端服务时,就会携带该Cookie(至于为什么会携带,这是Cookie本身的机制,当然还要看Cookie所属域名),后端服务收到请求后,读取其中的Cookie,然后查询Session,就可以知道当前访问的用户是Hanmeimei。

上述过程只涉及到用户已经登陆,并且通过Session和Cookie关联用户信息,另外一部分比较重要的就是用户登陆,例如,如果后端收到请求后,从后端Session中查询不到用户信息该怎么办呢?

3 SSO & Jwt & CAS

在登陆部分,经常听到或者看到的有三个单词:

  • SSO(Single Sign On):单点登录,当用户登录一个平台后,再去访问关联的其他平台,不需要重新登录,例如,如果登录了OA系统,再登录内部的gitlab、云平台等都可以直接访问。所以,SSO描述的更多的是一种现象,也就是说,符合上述的现象都可以称之为SSO。
  • JWT(Json Web Token):基于Token的WEB认证方式,与上面使用Session存储用户信息的方式不同,这种方式在登陆后会将用户信息经过加密成Token,前端收到后存储到Cookie或者LocalStorage,当下一次访问时,将Token放到请求头的Authorization。所以,JWT指的更多的是用户信息的存放方式,这种方式在发起后端API请求时也经常使用:先调用/api/login接口,返回Token,得到Token后,直接访问其他业务接口。
  • CAS(Central Authentication Service):统一身份认证服务,是SSO的一种实现,在实现过程中,也集成了JWT,将用户信息放到Token中。所以,严格意义上来说,CAS是一套用于实现SSO的系统,或者说,CAS是一个认证服务器,提供用户登陆验证的能力。

根据上面所说的,CAS是一套认证系统,它可以用于生成用户登陆的Token,而客户端可以以JWT的方式进行使用,例如拿到了之后存放到Cookie中。

4 gin中使用SSO

完整的CAS登陆流程在网上有很多,这里也不再赘述。下面就来说说,在gin中如何使用SSO接入公司的单点登录。

系统需要接入单点登录,就需要引入web的中间件:中间件是web框架提供的一种能力,可以在web的请求处理流程中加入业务自己的部分,例如,登陆验证、日志记录、时耗记录等。

具体流程如下:

  • 在中间件中判断用户是否登录,如果没有登录,则跳转到CAS的URL,CAS会判断用户是否登录,如果没有登录会跳转到登录页面
  • 当用户在CAS的登录页面输入用户名和密码登录后,会跳转到业务系统,并且会携带ticket,业务系统根据ticket去CAS验证,如果CAS验证通过,会返回用户信息给业务系统
  • 业务系统将用户信息保存到Session中,后续的请求就通过Session得到用户信息
// main.go 为gin添加中间件
r := gin.Default()
r.Use(Authenticate())// middleware.go
func Authenticate() gin.HandlerFunc {return func(c *gin.Context) {// 从session中获取用户信息session := sessions.Default(c)userName := session.Get("user_name")if userName == nil || userName == "" {// 用户在当前平台没有登录,则需要获取ticket// 这里的逻辑在不同的实现中可能会不一样,// 有的可以直接从query参数获取ticket,有的是直接放在cookie中ticket, _ := c.Cookie("SESSIONID")if ticket == "" {// 没有用户的cookie,说明没有通过登录验证,需要把session中的用户置空session.Set("user_name", "")session.Set("user_id", "")c.Next()return}// 通过ticket调用CAS接口获取用户信息,// 如果未获取到,说明用户确实没有登录,则跳转到CAS登录页面// 在跳转时需要带上当前的页面地址用于登录成功后的跳转user := handler.GetLoginUser(ticket)if user.UserId == "" {params := url.Values{}params.Add("service", fmt.Sprintf("http://%s", c.Request.URL.String())c.Redirect(http.StatusFound, fmt.Sprintf("%s?%s", config.Config.AuthLoginUrl, params.Encode()))return} else {// 获取到用户信息,则将用户信息写入sessionsession.Set("user_name", user.UserName)session.Set("user_id", user.UserId)session.Save()c.Next()}} else {c.Next()}}
}

5 前后端分离

现在的应用架构都采用前后端分离的方式,那么前后端分离的SSO跟非前后端分离有什么区别呢?

比较大的区别应该是在跳转部分的service参数:如果是前后端不分离,那么后端接收到的路由就是实际的页面地址,因此,如果登录成功跳转回来的话是可以直接用后端请求到的地址。如果前后端分离,跳转回来的页面肯定应该是前端的地址,这时候,跳转动作就只能在前端进行:

    // 获取用户信息async getUserName() {let token = getCookie("SESSIONID")if (token === "") {window.location.href = 'https://cas.example.com/cas/login?service=' + window.location.href} else {const out = await getUserProfile()this.username = out.Dataif (this.username === '') {window.location.href = 'https://cas.example.com/cas/login?service=' + window.location.href}}}

另外,在前后端分离的情况下,如果前端和后端不在同一个nginx下,会出现跨域问题。

6 跨域

跨域问题出现的原因是浏览器的同源访问限制策略,同源指的是相同的协议(例如,都是http)、域名、端口。为了安全起见,当浏览器发起XHR请求时,浏览器会查看当前源和请求的源是否相同,如果不相同就会禁止访问。

因此,跨域问题的出现有两个要素:

  • 不同源
  • XHR请求

如何解决跨域的问题呢?

常见的方案有三种:

  • 修改浏览器设置,禁用浏览器安全策略
  • JSONP,利用了非XHR请求不存在跨域,但是它只支持HTTP的GET请求
  • CORS,在响应头增加Access-Control-Allow-Origin选项,说明服务端允许访问的域名
  • 修改nginx或者apache的配置,当然也是在响应头增加Access-Control-Allow-Origin选项

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/161530.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式开发学习之STM32F407点亮LED及J-Link下载(二)

嵌入式开发学习之STM32F407点亮LED及J-Link下载(二) 开发涉及工具控制端口配置端口的设定与确认端口配置方法实现点亮LED程序下载与仿真 有工程实例,链接在最底部。 开发涉及工具 开发环境(IDE):IAR-ARM8…

力扣每日一题46:全排列

题目描述: 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1: 输入:nums [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2: …

Tuxera NTFS2024最新永久版下载和安装

要使用Tuxera NTFS for Mac,你需要先下载和安装Tuxera NTFS for Mac驱动器,然后按照以下步骤操作: 1、下载和安装Tuxera NTFS for Mac 免费下载Tuxera NTFS for Mac驱动器的最新版本。下载完成后,双击DMG文件并按照提示安装即可…

云计算:shell脚本

shell脚本,会极大减少重复性工作,缩短很大时间。 脚本每个人都可以不一样,只要实现就可以。 注意:要多思考,把思路锻炼好。以后就可以写各种程序。 shell语言 学完shell之后,对Linux理解更深刻&#xff…

IDEA 修改插件安装位置

不说假话,一定要看到最后,不然你以为我为什么要自己总结!!! IDEA 修改插件安装位置 前言步骤 前言 IDEA 默认的配置文件均安装在C盘,使用时间长会生成很多文件,这些文件会占用挤兑C盘空间&…

如何使用前端模块化开发?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

vue中引入jquery解决跨域问题

1、vue 工程文件 package.json 中 引入 “dependencies”: { “jquery”:“^2.2.4” }, 2、控制台执行命令,当前工程文件夹下 cnpm install 3、修改的vue文件中 加入 import $ from ‘jquery’ 4、调用 ajax请求 $.ajax({url:http://192.168.0.10:9099/strutsJspA…

Vue Router - 路由的使用、两种切换方式、两种传参方式、嵌套方式

目录 一、Vue Router 1.1、下载 1.2、基本使用 a)引入 vue-router.js(注意:要在 Vue.js 之后引入). b)创建好路由规则 c)注册到 Vue 实例中 d)展示路由组件 1.3、切换路由的两种方式 1.…

会议OA小程序首页布局

目录 一. Flex布局介绍 1.1 什么是Flex布局 1.2 基本概念 1.3 Flex属性 二. 会议OA首页轮播图的实现 配置 Mock工具 swiper 效果展示 三. 会议OA首页会议信息布局 index.js index.wxml index.wxss 首页整体效果展示 一. Flex布局介绍 布局的传统解决方案&#x…

简单的对称加密

异或 异或算法的好处便是数A和数B异或后,把结果再和数A异或便可得到B,或者和数B异或可重新得到数据A。利用异或的这个特性可简单实现数据的加密和解密算法。 恺撒密码 恺撒密码的替换方法是通过排列明文和密文字母表,密文字母表示通过将明…

MATLAB | 对随机信号进行统计分析,绘制频次直方图、频率分布图,与理论概率密度进行比较

一、问题描述 对于一个随机信号,我们可以通过统计手段,得到其的频次分布图(直方图),并由此计算出它的频率分布图。当观察次数区域无穷大时,频率分布图近似于概率密度函数。 下面我们以稳定分布的随机变量为…

互联网Java工程师面试题·Java 总结篇·第五弹

目录 47、Java 语言如何进行异常处理,关键字:throws、throw、try、catch、finally 分别如何使用? 48、运行时异常与受检异常有何异同? 49、列出一些你常见的运行时异常? 50、阐述 final、finally、finalize 的区别…

在 IDEA 中的各种调试技巧,轻松定位 Bug(超级全面)

在现在的开发中,我们经常采用Debug来追踪代码的运行流程,通常在程序运行过程中出现异常,启用Debug模式可以分析定位异常发生的位置,以及在运行过程中参数的变化。通常我们也可以启用Debug模式来跟踪代码的运行流程去学习三方框架的…

Orleans的成员管理和故障检测故障检测

Orleans的成员管理和故障检测故障检测 简介 Orleans框架是一个基于.NET平台的开源分布式系统框架,用于开发可扩展,高可用,高性能的云服务应用程序。它采用了Actor模型,将分布式系统中的各个节点抽象成为Actor,使得开…

蓝桥杯每日一题2023.10.17

迷宫 - 蓝桥云课 (lanqiao.cn) 题目描述 样例: 01010101001011001001010110010110100100001000101010 00001000100000101010010000100000001001100110100101 01111011010010001000001101001011100011000000010000 0100000000101010001101000010100000101010101100…

nginx正反向代理,负载均衡

Nginx 正向代理,反向代理 ,负载均衡 Nginx有两种代理协议 七层代理(http协议) 四层代理(tcp/udp流量转发) 四层代理七层代理概念 四层代理 四层代理:基于tcp/ip协议层的转发代理方式&#…

LabVIEW建立生产者消费者

LabVIEW建立生产者消费者 生产者/消费者设计模式由并行循环组成,这些循环分为两类:生产者循环和消费者循环。生产者循环和消费者循环间的通信可以使用队列或通道连线来实现。 队列 LabVIEW内置的队列操作VI可在函数选板>>数据通信>>队列操…

python每日一练(9)

🌈write in front🌈 🧸大家好,我是Aileen🧸.希望你看完之后,能对你有所帮助,不足请指正!共同学习交流. 🆔本文由Aileen_0v0🧸 原创 CSDN首发🐒 如…

小程序框架

目录 一.什么是小程序框架 二.视图层 先建立四个包 数据绑定 条件渲染 ​编辑 使用模板 事件系统 所有a.js 输出结果 ​编辑 三.跳转 a页面跳b页面 ​编辑 a页面跳c页面 测试结果 四.生命周期 一级跳一级 一级跳二级 二级跳二级 页面隔代跳转 一.什么是小程…

Flink 的集群资源管理

集群资源管理 一、ResourceManager 概述 1、ResourceManager 作为统一的集群资源管理器,用于管理整个集群的计算资源,包括 CPU资源、内存资源等。 2、ResourceManager 负责向集群资源管理器申请容器资源启动TaskManager实例,并对TaskManag…