实例详解:Java使用JWT和Redis实现高效单点登录(SSO)
前言
单点登录(Single Sign-On,简称SSO)是一种身份验证和访问控制机制,允许用户使用一组凭证(如登录名和密码)登录到多个应用程序中,而无需为每个应用程序单独进行身份验证。用户只需要登录一次就可以访问所有系统的应用和资源。相对于传统的每个系统都需要登录一次的方式,单点登录可以提高用户体验,降低用户的登录成本。在本文中,我们将通过使用JWT(JSON Web Token)和Redis来实现SSO功能,并提供详细的Java代码实例。
一、实现单点登录的步骤
-
设计登录系统
设计登录系统时,需要考虑如何通过登录信息验证用户身份,并生成令牌(Token),同时将Token保存在服务器端和客户端。 -
实现令牌传递和验证
在用户通过登录系统进行登录和身份验证后,应用程序要将Token返回给客户端,由客户端在访问其他应用时携带Token进行验证。 -
支持跨域访问
由于SSO需要支持不同的域名和端口之间的单点登录,所以应用程序需要支持跨域访问。传统的方式是使用Cookies来处理SSO,但如果采用Cookies,会有跨站脚本攻击(XSS)和跨站请求伪造(CSRF)的安全问题。因此,在现代Web应用程序中,通常使用 JSON Web Token(JWT)或OAuth 2.0来实现单点登录和授权。
二、Java实现单点登录的代码示例
下面,我们给出一个基于Spring Boot
和JWT
和Redis
的Java实现单点登录的样例代码。
1.添加依赖
在我们的Spring Boot项目中,添加如下JWT
和Redis
的依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.7.0</version>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.11.2</version>
</dependency>
2.配置Redis连接:
在application.properties
文件中添加以下Redis连接信息:
spring:redis:host: localhostport: 6379password: your_pwdjedis:pool:max-active: 1024max-wait: 10000max-idle: 200min-idle: 10timeout: 10000
jwt:secret: your_secret_keytoken:expireTime: 3600
3.实现JWT Token工具类:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;@Component
public class JwtTokenUtil {@Value("${jwt.secret}")private String secret;@Value("${jwt.token.expireTime}")private Long expireTime;private final String TOKEN_CACHE_PREFIX = "token:";@Autowiredprivate RedisTokenUtils redisTokenUtils;public String generateToken(String username) {Map<String, Object> claims = new HashMap<>();claims.put("sub", username);claims.put("created", new Date());String token = Jwts.builder().setClaims(claims).setExpiration(generateExpirationDate()).signWith(SignatureAlgorithm.HS512, secret).compact();redisTokenUtils.setToken(TOKEN_CACHE_PREFIX + username, token);return token;}// 其他方法...// 注意事项:// - 加密密钥(secret)需要保密且足够复杂。// - JWT Token的有效期应根据实际需求进行设置。
}
4.实现Redis Token存储工具类:
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.Component;import java.util.Date;
import java.util.concurrent.TimeUnit;@Component
public class RedisTokenUtils {@Value("${jwt.token.expireTime}")private Long expireTime;@Autowiredprivate RedisTemplate<String, Object> redisTemplate;public void setToken(String key, Object value) {redisTemplate.opsForValue().set(key, value, expireTime, TimeUnit.MINUTES);}public void deleteToken(String key) {redisTemplate.delete(key);}// 其他方法...// 注意事项:// - Redis的连接配置需要正确设置。// - Token的存储和删除应在合适的时机进行。
}
5. 实现登录逻辑:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class AuthService {@Autowiredprivate JwtTokenUtil jwtTokenUtil;public String login(String username, String password) {// 验证用户名和密码的逻辑// ...String token = jwtTokenUtil.generateToken(username);return token;}
}
6. 实现登出逻辑:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class AuthService {@Autowiredprivate JwtTokenUtil jwtTokenUtil;public void logout(String username) {jwtTokenUtil.deleteToken(username);}
}
三、注意事项
在使用JWT和Redis实现SSO时,需要注意以下事项:
- 密钥(secret)的安全性很重要,并应保密且足够复杂。比如:在生成Token时,使用合适的算法进行签名,以确保Token的安全性。验证Token时,需要使用相同的算法和密钥进行解密和验证。同时,还需要对Token的合法性进行校验,比如检查Token是否过期、是否被篡改等。
- 令牌的有效期应根据实际需求进行设置,过长的有效期可能会增加安全风险,而过短的有效期可能会导致频繁的重新登录。
- 在用户登出或注销操作时,应及时删除对应的令牌,以避免令牌被滥用。
总结
通过结合JWT和Redis,我们可以轻松实现单点登录(SSO)的功能。JWT用于生成和验证令牌,而Redis用于存储和管理令牌。JWT提供了一种轻量级的、无状态的身份验证机制,而Redis则提供了持久化存储和高性能的缓存功能。通过这样的组合,我们可以实现身份认证的高效和可靠,同时提供了可配置的令牌有效期功能,保证了系统的安全性。
相关文章:
实例详解:Java使用JWT和Redis实现高效单点登录(SSO)
前言 单点登录(Single Sign-On,简称SSO)是一种身份验证和访问控制机制,允许用户使用一组凭证(如登录名和密码)登录到多个应用程序中,而无需为每个应用程序单独进行身份验证。用户只需要登录一次…...
SQL中使用ROLLUP和CUBE函数轻松生成汇总行
在数据分析和报表制作中,通常需要对数据进行汇总和分组,我们常用的就是GROUP BY汇总数据,当我们想按照不同维度汇总时,往往需要编写多个GROUP BY预计,而借助ROLLUP 和 CUBE 函数可以一次性生成子总计和总计行ÿ…...

CentOS 7 安装和配置java环境
1 安装包准备 安装包可以通过下面地址进行版本选择安装: https://www.oracle.com/java/technologies/downloads/#java8 2 正式开始安装 本次分享的安装方法直接通过编辑/etc/profile文件实现java的安装 2.1 新建安装包存放目录 mkdir /java cd /java/ 2.2 解压安…...

「实验记录」CS144 Lab0 networking warmup
文章目录 一、Motivation二、SolutionsS1 - Writing webgetS2 - An in-memory reliable byte stream 三、Results四、Source 一、Motivation 第一个小测试 webget 是想让我们体验并模拟一下在浏览器中键入 URL 后获得远程服务器传来的内容,这并没有太大的难度&…...
html5怎么实现语音搜索
html5怎么实现语音搜索 谷歌的网站在他们首页发现了HTML5的新玩法——语音搜索。 注意: 只有webkit核心的浏览器才能使用 用法很简单 只需要在input添加属性x-webkit-speech即可,例子如下: 代码如下: <input type"text" x-…...

吴恩达《机器学习》1-2:什么是机器学习?
一、什么是机器学习? Arthur Samuel(1959): 他定义机器学习为,在进行特定编程的情况下,给予计算机学习能力的领域。 Tom Mitchell(1998): 他定义的机器学习是,…...

基于STC系列单片机实现定时器扫描数码管显示定时器/计数器产生频率的功能
#define uchar unsigned char//自定义无符号字符型为uchar #define uint unsigned int//自定义无符号整数型为uint #define NixieTubeSegmentCode P0//自定义数码管段码为单片机P0组引脚 #define NixieTubeBitCode P2//自定义数码管位码为单片机P2组引脚 sbit LED P1^0;//位定义…...

Linux环境开发工具yum、makefile的使用 【Linux】
文章目录 Linux软件包管理器 - yumLinux下安装软件的方式yum查找软件包如何实现本地机器和云服务器之间的文件互传卸载软件Linux编译器 - gcc/g 程序的翻译过程1.预编译(预处理)2.编译(生成汇编)3.汇编(生成机器可识别…...
第六章(6):Python中的函数—闭包和装饰器
1.闭包 在Python中,闭包是指函数与其相关的自由变量的一个整体。当一个函数返回了一个内部函数时,这个内部函数可以访问其定义所在的外部函数中的变量,即使这个外部函数已经返回了。这种特性就叫做闭包。 代码示意: def funca():x = 250def funcb():print(我仍然可以访问…...

Linux--安装与配置虚拟机及虚拟机服务器坏境配置与连接---超详细教学
一,操作系统介绍 1.1.什么是操作系统 操作系统(Operating System,简称OS)是一种系统软件,它是计算机硬件和应用软件之间的桥梁。它管理计算机的硬件和软件资源,为应用程序提供接口和服务,并协调…...

基于SSM的个性化美食推荐系统设计与实现
末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…...

Django 全局配置 settings 详解
文章目录 1 概述1.1 Django 目录结构 2 常用配置:settings.py2.1 注册 APP:INSTALLED_APPS2.2 模板路径:TEMPLATES2.3 静态文件:STATICFILES_DIRS2.4 数据库:DATABASES2.5 允许访问的主机:ALLOWED_HOSTS 1 …...

uniapp接口请求api封装,规范化调用
封装规范和vue中的差不多,都是统一封装成一个request对象,然后在api.js里面调用。 先创建一个utils文件夹,然后里面创建一个request.js,代码如下: export const baseURL 基础url地址const request (options) > …...

色彩校正及OpenCV mcc模块介绍
一、术语 1.光:是电磁波,可见光是可被人眼感知的电磁波。可见光大约在400-700nm波段。光子携带的能量与波长成反比,400nm--700nm之间的单色光的颜色从紫色渐变成红色。 2.光谱:除了太阳光源外,LED灯、白炽灯等各种照明…...
2023mathorcup大数据数学建模竞赛A题坑洼道路识别67页完整高质量原创论文
大家好,从昨天肝到现在,终于完成了本次mathorcup大数据数学建模竞赛A题基于计算机视觉的坑洼道路检测和识别的完整论文了。 给大家看一下目录吧: 摘 要: 10 一、问题重述 12 二.问题分析 13 2.1问题一 13 2.2问题…...

【k8s】5、资源管理命令-声明式
目录 一、 yaml和json介绍 1、yuml语言介绍 2、k8s支持的文件格式 3、yaml和json的主要区别 二、声明式对象管理 1、命令式对象配置 2、声明式对象配置 3、声明式对象管理命令介绍 三、编写资源配置清单 1、 编写yaml文件 2、 启动并查看资源 3、创建service服务对外…...

信息系统项目管理师教程 第四版【第6章-项目管理概论-思维导图】
信息系统项目管理师教程 第四版【第6章-项目管理概论-思维导图】 课本里章节里所有蓝色字体的思维导图...
【Flutter】Flutter 中的图片管理 图片优化的最佳实践
【Flutter】Flutter 中的图片管理 图片优化的最佳实践 文章目录 一、前言二、图片资源的重要性1. 对于项目复杂性的影响2. 性能和资源优化3. 国际化和多平台支持4. UI/UX 的角度看图片管理5. 图片资源与应用安全三、Flutter 中的图片资源分类1. Asset 图片2. 网络图片3. 本地文…...

dash--项目的前端展示简单基础
1.前置工作 创建虚拟环境: sudo apt-get install python3-venv # 安装 python3 -m venv venv # 在本目录下创建venv虚拟环境(也是一个文件夹。如果用不到这个虚拟环境以后就rm -rf venv) source venv/bin/activate # 激活虚拟环境临时使用清华…...
LeetCode 面试题 16.06. 最小差
文章目录 一、题目二、C# 题解 一、题目 给定两个整数数组 a 和 b,计算具有最小差绝对值的一对数值(每个数组中取一个值),并返回该对数值的差 示例: 输入:{1, 3, 15, 11, 2}, {23, 127, 235, 19, 8} 输出&…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...

基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...