jwt+shiro认证

news2024/11/18 17:36:24

文章目录

  • jwt + shiro 认证
    • jwt 使用
      • 引入依赖
      • 编写 jwt 工具类
      • 测试
    • shiro + jwt 认证
      • 项目文件路径:
      • 引入依赖
      • shiro.ini
      • 重写 Realm
      • 认证服务接口
      • 认证服务接口实现类
      • 自定义 token
      • 测试

代码来自于小傅哥 《API网关》 项目

jwt + shiro 认证

jwt 使用

引入依赖

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

编写 jwt 工具类

注意 signingKey 不要暴露出去。

package cn.bugstack.gateway.authorization;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 小傅哥,微信:fustack
 * @description JWT(JSON Web Tokens)https://jwt.io/
 * @github https://github.com/fuzhengwei
 * @Copyright 公众号:bugstack虫洞栈 | 博客:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
 */
public class JwtUtil {

    private static final String signingKey = "B*B^5Fe";

    /**
     * 生成 JWT Token 字符串
     *
     * @param issuer    签发人
     * @param ttlMillis 有效期
     * @param claims    额外信息
     * @return Token
     */
    public static String encode(String issuer, long ttlMillis, Map<String, Object> claims) {
        if (null == claims) {
            claims = new HashMap<>();
        }

        // 签发时间(iat):荷载部分的标准字段之一
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        // 签发操作
        JwtBuilder builder = Jwts.builder()
                // 荷载部分
                .setClaims(claims)
                // 签发时间
                .setIssuedAt(now)
                // 签发人;类似 userId、userName
                .setSubject(issuer)
                // 设置生成签名的算法和秘钥
                .signWith(SignatureAlgorithm.HS256, signingKey);

        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);
            // 过期时间(exp):荷载部分的标准字段之一,代表这个 JWT 的有效期。
            builder.setExpiration(exp);
        }

        return builder.compact();
    }

    public static Claims decode(String token) {
        return Jwts.parser()
                // 设置签名的秘钥
                .setSigningKey(signingKey)
                // 设置需要解析的 jwt
                .parseClaimsJws(token)
                .getBody();
    }
}

测试

@Test
public void test_awt() {
    String issuer = "xiaofuge";
    long ttlMillis = 7 * 24 * 60 * 60 * 1000L;
    Map<String, Object> claims = new HashMap<>();
    claims.put("key", "xiaofuge");

    // 编码
    String token = JwtUtil.encode(issuer, ttlMillis, claims);
    System.out.println(token);

    // 解码
    Claims parser = JwtUtil.decode(token);
    System.out.println(parser.getSubject());
}

shiro + jwt 认证

项目文件路径:

在这里插入图片描述

在这里插入图片描述

引入依赖

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.3.2</version>
</dependency>

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

shiro.ini

[main]
# 声明1个Realm,也可以声明多个,多个则顺序执行
gatewayAuthorizingRealm=cn.bugstack.gateway.authorization.GatewayAuthorizingRealm
# 指定 securityManager 的 realms 实现。如果是多个则用逗号隔开。
securityManager.realms=$gatewayAuthorizingRealm

重写 Realm

在 realm 中进行认证操作,即拿到 token 进行 jwt 解密,如果解密成功,说明认证成功

package cn.bugstack.gateway.authorization;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

/**
 * @author 小傅哥,微信:fustack
 * @description 验证领域
 * @github https://github.com/fuzhengwei
 * @Copyright 公众号:bugstack虫洞栈 | 博客:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
 */
public class GatewayAuthorizingRealm extends AuthorizingRealm {

    @Override
    public Class<?> getAuthenticationTokenClass() {
        return GatewayAuthorizingToken.class;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 暂时不需要做授权处理
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        try {
            // 验证解析是否报错
            JwtUtil.decode(((GatewayAuthorizingToken) token).getJwt());
        } catch (Exception e) {
            throw new AuthenticationException("无效令牌");
        }
        return new SimpleAuthenticationInfo(token.getPrincipal(), token.getCredentials(), this.getName());
    }

}

认证服务接口

/**
 * @author 小傅哥,微信:fustack
 * @description 认证服务接口
 * @github https://github.com/fuzhengwei
 * @Copyright 公众号:bugstack虫洞栈 | 博客:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
 */
public interface IAuth {

    boolean validate(String id, String token);

}

认证服务接口实现类

做两件事:初始化 shiro 和 shiro 认证

  • 使用 ini 初始化 shiro 可参考官网:https://shiro.apache.org/configuration.html

  • validate() : 在这里进行 shiro 的认证,认证时传入我们自己实现的 GatewayAuthorizingToken ,里边存储的有被认证用户传进的 jwt 的 token,拿到之后会到我们自定义的 GatewayAuthorizingRealm 中进行认证操作,即对 GatewayAuthorizingToken 中传入的 token 使用 jwt 进行解密,如果解密成功,则认证成功

/**
 * @author 小傅哥,微信:fustack
 * @description 认证服务实现
 * @github https://github.com/fuzhengwei
 * @Copyright 公众号:bugstack虫洞栈 | 博客:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
 */
public class AuthService implements IAuth {

    private Subject subject;

    public AuthService() {
        // 1. 获取 SecurityManager 工厂,此处使用 shiro.ini 配置文件初始化 SecurityManager
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        // 2. 得到 SecurityManager 实例 并绑定给 SecurityUtils
        SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);
        // 3. 得到 Subject 及 Token
        this.subject = SecurityUtils.getSubject();
    }

    @Override
    public boolean validate(String id, String token) {
        try {
            // 身份验证
            subject.login(new GatewayAuthorizingToken(id, token));
            // 返回结果
            return subject.isAuthenticated();
        } finally {
            // 退出
            subject.logout();
        }
    }

}

自定义 token

在自定义 token 中存储 jwt 认证信息

/**
 * @author 小傅哥,微信:fustack
 * @description 验证 Token
 * @github https://github.com/fuzhengwei
 * @Copyright 公众号:bugstack虫洞栈 | 博客:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
 */
public class GatewayAuthorizingToken implements AuthenticationToken {

    private static final long serialVersionUID = 1L;

    // 通信管道ID
    private String channelId;

    // JSON WEB TOKEN
    private String jwt;

    public GatewayAuthorizingToken() {
    }

    public GatewayAuthorizingToken(String channelId, String jwt) {
        this.channelId = channelId;
        this.jwt = jwt;
    }

    @Override
    public Object getPrincipal() {
        return channelId;
    }

    @Override
    public Object getCredentials() {
        return this.jwt;
    }

    public String getChannelId() {
        return channelId;
    }

    public void setChannelId(String channelId) {
        this.channelId = channelId;
    }

    public String getJwt() {
        return jwt;
    }

    public void setJwt(String jwt) {
        this.jwt = jwt;
    }
}

测试

@Test
public void test_auth_service() {
    IAuth auth = new AuthService();
    // 这里的 token 使用 jwt 工具类的 encode() 方法生成的 token
    boolean validate = auth.validate("123", "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ4aWFvZnVnZSIsImV4cCI6MTY5MTY0NTM3NSwiaWF0IjoxNjkxMDQwNTc1LCJrZXkiOiJ4aWFvZnVnZSJ9.fy8Rc5d_w6JX1QRIBuEeni8fgtDYFVyCBsnukuPXrlc");
    System.out.println(validate ? "验证成功" : "验证失败");
}

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

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

相关文章

一个SpringBoot 项目能处理多少请求?

这篇文章带大家盘一个读者遇到的面试题哈。 根据读者转述&#xff0c;面试官的原问题就是&#xff1a;一个 SpringBoot 项目能同时处理多少请求&#xff1f; 不知道你听到这个问题之后的第一反应是什么。 我大概知道他要问的是哪个方向&#xff0c;但是对于这种只有一句话的…

【C语言督学训练营 第二十一天】汇编语言零基础入门

文章目录 前言1.C语言源文件转汇编2.汇编指令格式3.汇编常用指令3.1 相关寄存器3.2 常用指令3.3 数据传送指令3.4 算术/逻辑运算指令3.5 控制流指令3.6 条件码 4.如何定义汇编中的变量5.选择循环汇编实战6.函数调用汇编实战7.C语言源文件转机器指令 前言 汇编语言是一种功能很强…

WebDAV之π-Disk派盘 + CX文件管理器

CX文件管理器是一款好用的文件管理工具。它的功能非常的丰富,它能满足用户对文件管理的需求,而且功能也是一目了然,可以帮助用户快速的对文件进行操作。这款软件还支持SFTP、WebDAV、FTP等下载访问方式。手机和电脑在同一局域网下,可以使用FTP或派盘从你的电脑直接访问手机…

selenium页面切换操作

selenuim页面切换 webdriver只能在一个页面里对元素进行识别和定位。如果有多个页面操作的时候&#xff0c;要先进行页面切换。 切换分两种 1 iframe内嵌页面切换&#xff08;框架集切换&#xff09; # 1 获取iframe标签 iframe driver.find_element_by_tag_name(iframe) …

echarts绘制甘特图

说在前面 项目上有需求&#xff0c;需要在大屏上展示进度甘特图&#xff0c;调研了DHTMLX和普加甘特图&#xff0c;效果都不是特别符合需求现状&#xff0c;查询了一些博客&#xff0c;决定使用echarts来绘制甘特图。 实现效果展示 实现思路分析 1、应该采用柱状图&#xff…

LeetCode404. 左叶子之和

404. 左叶子之和 文章目录 [404. 左叶子之和](https://leetcode.cn/problems/sum-of-left-leaves/)一、题目二、题解方法一&#xff1a;递归方法二&#xff1a;迭代 一、题目 给定二叉树的根节点 root &#xff0c;返回所有左叶子之和。 示例 1&#xff1a; 输入: root [3,9…

个人信息保护合规审计如何做?

8月3日&#xff0c;为指导、规范个人信息保护合规审计活动&#xff0c;根据《中华人民共和国个人信息保护法》等法律法规&#xff0c;国家互联网信息办公室就《个人信息保护合规审计管理办法&#xff08;征求意见稿&#xff09;》&#xff08;简称《办法》&#xff09;及配套的…

【Apifox】Apifox设置全局Token:

文章目录 一、获取登录Token和设置全局变量&#xff1a;二、设置全局参数&#xff1a;三、效果&#xff1a; 一、获取登录Token和设置全局变量&#xff1a; 二、设置全局参数&#xff1a; 三、效果&#xff1a;

盘点7月Sui生态发展,了解Sui的近期成长历程!

自5月Sui主网上线三个月以来&#xff0c;7月是Sui网络进行最多次重要更新的一个月&#xff0c;Sui网络和生态正呈指数形式不断向上发展。为吸引更多的项目或开发者加入生态构建以及活跃用户参与生态&#xff0c;Sui基金会推出了Builder House、黑客松、Bullshark Quests、NFT再…

数据库:MYSQL参数max_allowed_packet 介绍

1、参数作用 max_allowed_packet参数是指mysql服务器端和客户端在一次传送数据包的过程当中最大允许的数据包大小。如果超过了设置的最大长度,则会数据库保持数据失败。 2、问题场景 ● 有时候业务的需要,可能会存在某些字段数据长度非常大(比如富文本编辑器里面的内容),…

基于Java的学生管理系统设计与实现

一、系统功能介绍 基于Java的学生管理系统&#xff0c;本系统包括学生信息管理、学生成绩管理、县教育信息管理、个人资料管理等功能。 二、相关页面展示 以下是页面展示&#xff1a; 1 登录页面 2 首页页面页面 3 学生成绩查询页面 4 本校成绩排行页面 5 管理员学生成绩管…

【Apollo学习笔记】—— Cyber RT之调度

文章目录 前言相关代码整理 调度介绍Cyber RT的改进实时操作系统资源限制&优先级协程 Cyber RT调度策略任务窃取两种任务类型componen组件自定义任务 Cyber调度实践配置文件DAG文件cyber_launch文件component组件BUILD文件 问题参考 前言 本文是对Cyber RT的学习记录,文章可…

4G WWAN设备类型

WWAN设备类型 USB dongle是设备接入互联网的重要方式之一&#xff0c;典型的通过USB接口与主设备连接&#xff0c;然后主设备通过4G/5G接入互联网&#xff0c;作为移动宽带设备&#xff0c;它有那些设备类型及暴露方式呢&#xff1f; 移动宽带设备类型&#xff1a;ModemManage…

无涯教程-Lua - nested语句函数

Lua编程语言允许在另一个循环中使用一个循环。以下部分显示了一些示例来说明这一概念。 nested loops - 语法 Lua中嵌套for循环语句的语法如下- for init,max/min value, increment dofor init,max/min value, incrementdostatement(s)endstatement(s) end Lua编程语言中的…

Podman权限问题导致的403报错思路与解决

问题 podman运行镜像&#xff0c;端口映射、卷映射无误&#xff0c;但在运行访问测试容器内http接口报错403. 查阅系统日志&#xff0c;存在多处容器相关的selinux访问被拒绝错误&#xff0c;sealert提示需要为几个进程的对象添加临时规则。 考虑是否为selinux问题&#xff…

语义分割文献整理

2014年文献 1.论文题目《Semantic Image Segmentation with Deep Convolutional Nets and Fully Connected CRFs》 1.1.网络别名《DeepLabV1》 1.2.论文引用 Chen L C, Papandreou G, Kokkinos I, et al. Semantic image segmentation with deep convolutional nets and fu…

AI赋能转型升级 助力打造“数智辽宁”——首次大模型研讨沙龙在沈成功举行

当前&#xff0c;以“ChatGPT”为代表的大模型正在引领新一轮全球人工智能技术发展浪潮&#xff0c;推动人工智能从以专用小模型定制训练为主的“手工作坊时代”&#xff0c;迈入以通用大模型预训练为主的“工业化时代”&#xff0c;正不断加速实体经济智能化升级&#xff0c;深…

(自控原理)控制系统的数学模型

目录 一、时域数学模型 1、线性元件微分方程的建立 2、微分方程的求解方法​编辑 3、非线性微分方程的线性化 二、复域数学模型 1、传递函数的定义 2、传递函数的标准形式 3、系统的典型环节的传递函数 4、传递函数的性质 5、控制系统数学模型的建立 6、由传递函数求…

【C++】带三维重建和还原的RIS/PACS源码

【PACS】集成三维影像后处理功能&#xff0c;包括三维多平面重建、三维容积重建、三维表面重建、三维虚拟内窥镜、最大/小密度投影、心脏动脉钙化分析等功能。系统功能强大&#xff0c;代码完整。 一、RIS/PACS系统简介 RIS/PACS系统在预约登记、分诊叫号、技师检查、诊断报告…

面向开发人员的远程桌面:随时随地安全编写代码

随着数字世界的不断发展&#xff0c;传统意义上的“工作场所”概念正在发生重大转变。这种转变在科技行业尤其明显&#xff0c;开发人员和软件工程师越来越倾向于选择远程或混合办公模式。 在这次重大转变中&#xff0c;远程桌面软件经证明是一项足以影响远程办公的技术。通过…