springboot整合 shiro框架 && jwt验证

本文介绍了如何在SpringBoot项目中整合Shiro框架和JWT进行身份验证。详细讲解了JWT的构成(header、payload、signature)以及Shiro的三个核心组件(Subject、SecurityManager、Realm)。通过创建Realm类、过滤器和配置类,实现了JWT的校验和授权功能。Shiro的过滤器拦截请求, Realm进行验证和授权操作。
摘要由CSDN通过智能技术生成


前言

一个系统在起步的时候最重要的权限系统,最简单的实现就是通过角色表+菜单表相关联,通过登陆用户的角色查到对应的菜单,但是这样只能得到页面的权限,如何控制某个功能的权限呢?shiro来了...

一、jwt是什么?

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

1. jwt构成

JWT是由三段信息构成的,将这三段信息文本用.链接一起就构成了JWT字符串。就像这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

1.1 header

jwt的头部承载两部分信息:

  • 声明类型,这里是jwt
  • 声明加密的算法 通常直接使用 HMAC SHA256

完整的头部就像下面这样的JSON:

{
   
  'typ': 'JWT',
  'alg': 'HS256'
}

然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分.

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

1.2 playload

载荷就是存放有效信息的地方,这里一般存储用户的非敏感信息,为json格式

{
   
  "username": "joker",
  "addr": "北京朝阳区",
  "age": 23,
  "VIP":false
}

然后将其进行base64加密,得到Jwt的第二部分。

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

1.3 signature

jwt的第三部分是一个签证信息,这个签证信息由三部分组成:

  • header (base64后的)
  • payload (base64后的)
  • secret

这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

2. jwt实现

引入pom依赖

<dependency>
   <groupId>io.jsonwebtoken</groupId>
   <artifactId>jjwt</artifactId>
   <version>0.9.0</version>
</dependency>
<dependency>
   <groupId>com.auth0</groupId>
   <artifactId>java-jwt</artifactId>
   <version>3.5.0</version>
</dependency>

创建jwt工具类,该类提供了生成token,验证token等方法,同时每次生成等token可以设置有效时间

/*
 * 总的来说,工具类中有三个方法
 * 获取JwtToken,获取JwtToken中封装的信息,判断JwtToken是否存在
 * 1. encode(),参数是=签发人,存在时间,一些其他的信息=。返回值是JwtToken对应的字符串
 * 2. decode(),参数是=JwtToken=。返回值是荷载部分的键值对
 * 3. isVerify(),参数是=JwtToken=。返回值是这个JwtToken是否存在
 * */
@Slf4j
public class JwtUtil {
   
    //创建默认的秘钥和算法,供无参的构造方法使用
    private static final String defaultbase64EncodedSecretKey = "badbabe";
    private static final SignatureAlgorithm defaultsignatureAlgorithm = SignatureAlgorithm.HS256;

    public JwtUtil() {
   
        this(defaultbase64EncodedSecretKey, defaultsignatureAlgorithm);
    }

    private final String base64EncodedSecretKey;
    private final SignatureAlgorithm signatureAlgorithm;

    public JwtUtil(String secretKey, SignatureAlgorithm signatureAlgorithm) {
   
        this.base64EncodedSecretKey = Base64.encodeBase64String(secretKey.getBytes());
        this.signatureAlgorithm = signatureAlgorithm;
    }

    /*
     *这里就是产生jwt字符串的地方
     * jwt字符串包括三个部分
     *  1. header
     *      -当前字符串的类型,一般都是“JWT”
     *      -哪种算法加密,“HS256”或者其他的加密算法
     *      所以一般都是固定的,没有什么变化
     *  2. payload
     *      一般有四个最常见的标准字段(下面有)
     *      iat:签发时间,也就是这个jwt什么时候生成的
     *      jti:JWT的唯一标识
     *      iss:签发人,一般都是username或者userId
     *      exp:过期时间
     *
     * */
    public String encode(String iss, long ttlMillis, Map<String, Object> claims) {
   
        //iss签发人,ttlMillis生存时间,claims是指还想要在jwt中存储的一些非隐私信息
        if (claims == null) {
   
            claims = new HashMap<>();
        }
        long nowMillis = System.currentTimeMillis();

        JwtBuilder builder = Jwts.builder()
                .setClaims(claims)
                .setId(UUID.randomUUID().toString())//2. 这个是JWT的唯一标识,一般设置成唯一的,这个方法可以生成唯一标识
                .setIssuedAt(new Date(nowMillis))//1. 这个地方就是以毫秒为单位,换算当前系统时间生成的iat
                .setSubject(</
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值