sa-token多端登陆实现,PC,APP登陆分别设置token过期时间

news2024/11/27 1:29:31

sa-token多端登陆实现,PC,APP登陆分别设置token过期时间

在这里插入图片描述

Sa-Token 介绍

Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权 等一系列权限相关问题。

Sa-Token 功能一览

Sa-Token 目前主要五大功能模块:登录认证、权限认证、单点登录、OAuth2.0、微服务鉴权。

登录认证 —— 单端登录、多端登录、同端互斥登录、七天内免登录
权限认证 —— 权限认证、角色认证、会话二级认证
Session会话 —— 全端共享Session、单端独享Session、自定义Session
踢人下线 —— 根据账号id踢人下线、根据Token值踢人下线
账号封禁 —— 登录封禁、按照业务分类封禁、按照处罚阶梯封禁
持久层扩展 —— 可集成Redis、Memcached等专业缓存中间件,重启数据不丢失
分布式会话 —— 提供jwt集成、共享数据中心两种分布式会话方案
微服务网关鉴权 —— 适配Gateway、ShenYu、Zuul等常见网关的路由拦截认证
单点登录 —— 内置三种单点登录模式:无论是否跨域、是否共享Redis,都可以搞定
OAuth2.0认证 —— 轻松搭建 OAuth2.0 服务,支持openid模式
二级认证 —— 在已登录的基础上再次认证,保证安全性
Basic认证 —— 一行代码接入 Http Basic 认证
独立Redis —— 将权限缓存与业务缓存分离
临时Token认证 —— 解决短时间的Token授权问题
模拟他人账号 —— 实时操作任意用户状态数据
临时身份切换 —— 将会话身份临时切换为其它账号
前后端分离 —— APP、小程序等不支持Cookie的终端
同端互斥登录 —— 像QQ一样手机电脑同时在线,但是两个手机上互斥登录
多账号认证体系 —— 比如一个商城项目的user表和admin表分开鉴权
Token风格定制 —— 内置六种Token风格,还可:自定义Token生成策略、自定义Token前缀
注解式鉴权 —— 优雅的将鉴权与业务代码分离
路由拦截式鉴权 —— 根据路由拦截鉴权,可适配restful模式
自动续签 —— 提供两种Token过期策略,灵活搭配使用,还可自动续签
会话治理 —— 提供方便灵活的会话查询接口
记住我模式 —— 适配[记住我]模式,重启浏览器免验证
密码加密 —— 提供密码加密模块,可快速MD5、SHA1、SHA256、AES、RSA加密
全局侦听器 —— 在用户登陆、注销、被踢下线等关键性操作时进行一些AOP操作
开箱即用 —— 提供SpringMVC、WebFlux等常见web框架starter集成包,真正的开箱即用
更多功能正在集成中… —— 如有您有好想法或者建议,欢迎加群交流

PC,APP登陆分别设置token过期时间代码案例

最种实现效果:同一账号不同设备登陆,APP的token永不过期,PC的的3600秒
在这里插入图片描述

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.satoken</groupId>
    <artifactId>sa-token-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- SpringBoot核心jar包 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Sa-Token 权限认证,在线文档:https://sa-token.cc -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-spring-boot-starter</artifactId>
            <version>1.34.0</version>
        </dependency>
        <!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-dao-redis-jackson</artifactId>
            <version>1.34.0</version>
        </dependency>

        <!-- 提供Redis连接池 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!-- Sa-Token 整合 jwt -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-jwt</artifactId>
            <version>1.34.0</version>
        </dependency>

    </dependencies>
</project>
server:
  # 端口
  port: 8081

############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
sa-token:
  # token名称 (同时也是cookie名称)
  token-name: satoken
  # token有效期,单位s 默认30天, -1代表永不过期
  timeout: 2592000
  # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
  activity-timeout: 3600
  # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
  is-concurrent: true
  # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
  is-share: false
  # token风格
  token-style: uuid
  # 是否输出操作日志
  is-log: false
  # jwt秘钥
  jwt-secret-key: asdasdasifhueuiwyurfewbfjsdafjk
spring:
  # redis配置
  redis:
    # Redis数据库索引(默认为0)
    database: 1
    # Redis服务器地址
    host: 127.0.0.1
    # Redis服务器连接端口
    port: 6379
    # Redis服务器连接密码(默认为空)
    # password:
    # 连接超时时间
    timeout: 10s
    lettuce:
      pool:
        # 连接池最大连接数
        max-active: 200
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms
        # 连接池中的最大空闲连接
        max-idle: 10
        # 连接池中的最小空闲连接
        min-idle: 0
package com.satoken.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @author TANGSHUAI
 * @version 1.0
 * @date 2023-06-09 10:58
 */
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        //设置序列化Key的实例化对象
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置序列化Value的实例化对象
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        return redisTemplate;
    }

}

package com.satoken.config;

import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
import cn.dev33.satoken.stp.StpLogic;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author TANGSHUAI
 * @version 1.0
 * @date 2023-06-08 17:14
 */
@Configuration
public class SaTokenConfigure {
    // Sa-Token 整合 jwt (Simple 简单模式)
    @Bean
    public StpLogic getStpLogicJwt() {
        return new StpLogicJwtForSimple();
    }
}


package com.satoken.controller;

import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author TANGSHUAI
 * @version 1.0
 * @date 2023-06-08 17:06
 */
@RestController
@RequestMapping("/user/")
public class LoginController {

    // 测试登录,浏览器访问: http://localhost:8081/user/doLogin?username=zhang&password=123456
    @RequestMapping("doLogin")
    public String doLogin(String username, String password,@RequestParam(name = "source",defaultValue = "PC") String source) {
        // 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
        if("zhang".equals(username) && "123456".equals(password)) {
            StpUtil.login(10001, new SaLoginModel()
                    .setDevice("PC")                // 此次登录的客户端设备类型, 用于[同端互斥登录]时指定此次登录的设备类型
                    .setIsLastingCookie(true)        // 是否为持久Cookie(临时Cookie在浏览器关闭时会自动删除,持久Cookie在重新打开后依然存在)
                    .setTimeout(60 * 60 * 24 * 7)    // 指定此次登录token的有效期, 单位:秒 (如未指定,自动取全局配置的 timeout 值)
                    .setExtra("name", "zhangsan")    // Token挂载的扩展参数 (此方法只有在集成jwt插件时才会生效)
                    .setIsWriteHeader(false)         // 是否在登录后将 Token 写入到响应头
            );
            return "登录成功";
        }
        return "登录失败";
    }

    @RequestMapping("doLogin2")
    public String doLogin2(String username, String password,@RequestParam(name = "source",defaultValue = "APP")String source) {
        // 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
        if("zhang".equals(username) && "123456".equals(password)) {
            StpUtil.login(10001, new SaLoginModel()
                    .setDevice("APP")                // 此次登录的客户端设备类型, 用于[同端互斥登录]时指定此次登录的设备类型
                    .setIsLastingCookie(true)        // 是否为持久Cookie(临时Cookie在浏览器关闭时会自动删除,持久Cookie在重新打开后依然存在)
                    .setTimeout(-1)    // 指定此次登录token的有效期, 单位:秒 (如未指定,自动取全局配置的 timeout 值)
                    .setExtra("name", "zhangsan")    // Token挂载的扩展参数 (此方法只有在集成jwt插件时才会生效)
                    .setIsWriteHeader(false)         // 是否在登录后将 Token 写入到响应头
            );
            return "登录成功";
        }
        return "登录失败";
    }

    // 查询登录状态,浏览器访问: http://localhost:8081/user/isLogin
    @RequestMapping("isLogin")
    public String isLogin() {
        System.out.println(StpUtil.getLoginId());
        return "当前会话是否登录:" + StpUtil.isLogin();
    }



}

package com.satoken.listener;

import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.stp.SaLoginModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @author TANGSHUAI
 * @version 1.0
 * @date 2023-06-09 10:08
 */
@Component
public class MySaTokenListener implements SaTokenListener {

    @Autowired
    private RedisTemplate redisTemplate;

    /** 每次登录时触发 */
    @Override
    public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {
        //登陆成功修改App端token永不过期
        String device = loginModel.getDevice();
        if("APP".equals(device)){
            //app登陆,修改redis中的token为永不过期
            redisTemplate.persist("satoken:login:last-activity:"+tokenValue);
            //sa-token自带修改token过期时间
            //SaManager.getSaTokenDao().updateTimeout("satoken:login:last-activity:"+tokenValue, SaTokenDao.NEVER_EXPIRE);
        }
        System.out.println("---------- 自定义侦听器实现 doLogin");
    }

    /** 每次注销时触发 */
    @Override
    public void doLogout(String loginType, Object loginId, String tokenValue) {
        System.out.println("---------- 自定义侦听器实现 doLogout");
    }

    /** 每次被踢下线时触发 */
    @Override
    public void doKickout(String loginType, Object loginId, String tokenValue) {
        System.out.println("---------- 自定义侦听器实现 doKickout");
    }

    /** 每次被顶下线时触发 */
    @Override
    public void doReplaced(String loginType, Object loginId, String tokenValue) {
        System.out.println("---------- 自定义侦听器实现 doReplaced");
    }

    /** 每次被封禁时触发 */
    @Override
    public void doDisable(String loginType, Object loginId, String service, int level, long disableTime) {
        System.out.println("---------- 自定义侦听器实现 doDisable");
    }

    /** 每次被解封时触发 */
    @Override
    public void doUntieDisable(String loginType, Object loginId, String service) {
        System.out.println("---------- 自定义侦听器实现 doUntieDisable");
    }

    /** 每次二级认证时触发 */
    @Override
    public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) {
        System.out.println("---------- 自定义侦听器实现 doOpenSafe");
    }

    /** 每次退出二级认证时触发 */
    @Override
    public void doCloseSafe(String loginType, String tokenValue, String service) {
        System.out.println("---------- 自定义侦听器实现 doCloseSafe");
    }

    /** 每次创建Session时触发 */
    @Override
    public void doCreateSession(String id) {
        System.out.println("---------- 自定义侦听器实现 doCreateSession");
    }

    /** 每次注销Session时触发 */
    @Override
    public void doLogoutSession(String id) {
        System.out.println("---------- 自定义侦听器实现 doLogoutSession");
    }

    /** 每次Token续期时触发 */
    @Override
    public void doRenewTimeout(String tokenValue, Object loginId, long timeout) {
        System.out.println("---------- 自定义侦听器实现 doRenewTimeout");
    }
}


package com.satoken;

import cn.dev33.satoken.SaManager;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author TANGSHUAI
 * @version 1.0
 * @date 2023-06-08 17:04
 */
@SpringBootApplication
public class SaTokenDemoApp {
    public static void main(String[] args) {
        SpringApplication.run(SaTokenDemoApp.class, args);
        System.out.println("启动成功:Sa-Token配置如下:" + SaManager.getConfig());
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

hive on spark亲自编译,详细教程

hive on spark 进行编译操作 软件 hive 2.3.6 spark 2.0.0版本 hadoop-2.7.6版本 操作流程&#xff1a; hadoop-2.7.6 1、安装hadoop不说了。简单。 spark-2.0.0 2、下载spark-2.0.0的源码. https://archive.apache.org/dist/spark/spark-2.1.0/ 这个下载spark各个版本…

Logback自定义DBAppender保存系统日志到数据库

在系统中采用了spring boot logback&#xff0b;slf4j的日志框架&#xff0c;将系统日志记录到数据库。 相关参考来源&#xff1a; 官方文档-DBAppender Logback输出日志到自定义MySQL数据库&#xff08;重写DBAppender&#xff09; logback日志框架中filter的使用 1. 添加依…

【新版】系统架构设计师 - 系统配置与性能评价

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 文章目录 架构 - 系统配置与性能评价考点摘要系统性能概述性能指标性能调整阿姆达尔解决方案性能评价方法 架构 - 系统配置与性能评价 考点摘要 性能指标&#xff08;★★&#xff09;阿姆达尔解决方案&#xff…

java SSM 教师管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM 教师管理系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和 数据库&#xff0c;系统主要采用B…

工业深度学习软件 从标注 训练 到测试 再到现场部署

工业深度学习软件 从标注 训练 到测试 再到现场部署 M7000技术规格表 Producer Specification 影像系统 Imaging Sys 适配相机 supported cameras 支持海康&#xff0c;迈德威视&#xff0c;度申2D相机&#xff08;可根据需求增加适配其他厂家相机&#xff09; Support for Hi…

22AP30 H.265 编解码处理器

22AP30 H.265 编解码处理器 主要特点 SVP&#xff08;Smart Vision Processing&#xff09;  图像分析工具推理引擎&#xff08;NNIE&#xff09; − 支持多种图像分析工具 − 1.2Tops运算性能 处理器内核  ARM Cortex A53 四核1.15GHz − 32KB L1 I-Cache&#xff0c;32KB…

小程序页面事件与wxs脚本

文章和代码已经归档至【Github仓库&#xff1a;https://github.com/timerring/front-end-tutorial 】或者公众号【AIShareLab】回复 小程序 也可获取。 文章目录 小程序视图与逻辑页面导航声明式导航编程式导航导航传参 页面事件下拉刷新事件上拉触底事件上拉触底案例 自定义编…

一级建造师执业资格考试--工程管理--速学36记--联想法

第一记&#xff1a;项目管理 第二记&#xff1a;项目管理的核心 第三记&#xff1a;项目总承包方的工作程序 第四记&#xff1a;项目质量控制体系建立 第五记&#xff1a;项目质量控制体系运行 第六记&#xff1a;施工过程质量验收不合格的处理方法 第七记&#xff1a;装配式混…

33:避免遮掩继承而来的名称

我们都知道在下面的代码中&#xff1a; int x;//global变量 void someFunc() {double x;//local变量cin >> x;//读一个新值赋予local变量x } 上述读取数据的语句指涉的是local变量x&#xff0c;而不是global变量x&#xff0c;因为内层作用域的名称会遮掩外围作用域的名…

提示词工程让儿童编程轻而易举

编写长长的代码时常令人头疼。尤其是小朋友&#xff0c;打字不快&#xff0c;但想象力丰富。 现在借助chatgpt。 一切变得超级简单。 1. https://github.com/roocell/gptCozmo 2. https://github.com/Bhood23/CozmoGPT while True:from pyChatGPT import ChatGPTimport speec…

1427205-93-3,Fmoc-Ser(Ac4Manα1-2Ac3Manα1-2Ac3Manα)-OH:一种糖基化蛋白

Fmoc-Ser(Ac4Manα1-2Ac3Manα1-2Ac3Manα)-OH&#xff0c;其CAS号为1427205-93-3&#xff0c;英文名为Fmoc-Ser(Ac4Manα1-2Ac3Manα1-2Ac3Manα)-OH。分子式为C56H67NO30&#xff0c;分子量为1234.13&#xff0c;纯度标准为95%。外形颜色为固体或粉末&#xff0c;包装规格有1…

重命名文件名 | 一键导出表格,让您的文件快速整理归档

您是否因为大量文件命名混乱、找文件困难而感到苦恼&#xff1f;现在有一个好消息&#xff0c;文件批量改名高手帮你解决&#xff01;我们提供最简单、最快捷的方式来统一您的文件命名&#xff0c;无论是照片、文档或是音视频文件&#xff0c;只需一键即可完成重命名。而且我们…

华为OD机试真题 Java 实现【观看文艺汇演问题】【2023 B卷 100分】,附详细解题思路

一、题目描述 为庆祝中国共产党成立100周年&#xff0c;某公园将举行多场文艺汇演&#xff0c;很多演出都是同时进行。 一个人只能同时观看一场演出&#xff0c;且不能迟到早退。由于演出分散在不同的演出场地&#xff0c;所以连续观看的演出最少要有15分钟的时间间隔。 小明…

二、Drools WorkBench

一、WorkBench 简介 WorkBench 是 KIE 组件中的元素&#xff0c;也称为 KIE-WB&#xff0c;是 Drools-WB 与 JBPM-WB 的结合体。它是一个可视化的规则编辑器。WorkBench 其实就是一个 war 包&#xff0c;安装到 Tomcat 中就可以运行。使用 WorkBench 可以在浏览器中 创建数据对…

基于jsp+mysql+Spring+mybatis+Springboot的Springboot实现的就业信息管理平台

运行环境: 最好是java jdk 1.8&#xff0c;我在这个平台上运行的。其他版本理论上也可以。 IDE环境&#xff1a; Eclipse,Myeclipse,IDEA或者Spring Tool Suite都可以&#xff0c;如果编译器的版本太低&#xff0c;需要升级下编译器&#xff0c;不要弄太低的版本 tomcat服务器环…

教你如何使用自定义测试(Minium)进行微信小程序自动化测试

目录 前言&#xff1a; 一、 编写用例 基本操作 处理小程序API 处理小程序原生控件 数据驱动 二、 执行用例 本地执行 云测服务测试 三、 最佳实践 四、总结 前言&#xff1a; 微信小程序自动化测试是保障小程序质量的重要手段&#xff0c;Minium是一个可为微信小程…

kafka 对 java NIO 的封装

说明 本文基于 kafka 2.7 编写。author JellyfishMIX - github / blog.jellyfishmix.comLICENSE GPL-2.0 java NIO 组件 几个 java NIO 的组件。 Buffer: 缓冲区。这是一个接口&#xff0c;kafka 用它的 ByteBuffer 实现类&#xff0c;配合 SocketChannel 实现读写操作。读…

区块链产业快速发展 和数集团开启区块链应用新时代

UTONMOS区块链游戏要来了。 就在5月底&#xff0c;UTONMOS品牌所属公司上海和数集团在泰国发布了【神念无界】系列的多款国际版链游&#xff0c;包括【神念无界-源起山海】、【北荒传奇】、【神宠岛】、【神农园】等区块链游戏。 以【神念无界-源起山海】为例&#xff0c;其是…

Web、容器化 Native、小程序跨平台!三种跨平台方案对比

前端码农工作几年&#xff0c;从一家公司跳到另一家公司&#xff0c;永远逃不掉的是跨平台需求。除了本身应用在多平台上架的需求之外&#xff0c;资源有限恐怕是最大的原因&#xff0c;跨平台方案确实可以减少重复开发工作&#xff0c;降低成本和节省时间&#xff1b;而且掌握…

从开源到云原生,时序数据库 TDengine 六年回顾精彩纷呈

2023 年 6 月 6 日&#xff0c;涛思数据旗下时序数据库&#xff08;Time Series Database&#xff09; TDengine 迎来六周年庆典&#xff0c;并于北京保利国际广场T2举办了主题为“TDengine 6th Anniversary&#xff1a;Back to The Future”的庆典活动&#xff0c;设置了「TDe…