优秀的编程知识分享平台

网站首页 > 技术文章 正文

springboot-如何使用shiro+jwt实现认证授权

nanyue 2024-09-21 19:52:16 技术文章 6 ℃

一、基本介绍

1.Shiro 和 JWT 基本概念

  • Shiro(Apache Shiro)是一个开源的 Java 安全框架,用于简化应用程序的身份认证、授权和会话管理等安全操作。它提供了一套易于使用的 API,帮助开发人员在他们的应用程序中实现安全功能。Shiro 可以处理用户登录验证、访问控制、密码加密等安全问题,使得开发者能够轻松地集成安全功能到他们的应用程序中。
  • JWT(JSON Web Token)是一种开放标准的身份验证和授权方法。它是一种轻量级的令牌,用于在客户端和服务端之间传递安全信息。JWT 是基于 JSON 格式的,包含了被称为声明的信息。这些声明可以包括用户的身份信息和其他相关数据。JWT 的一个重要特点是它是无状态的,服务端不需要存储用户的身份信息,而是通过验证令牌的完整性来确定用户的身份和权限。

2.登录和认证授权过程介绍

① 登录请求

第一次访问系统,输入用户名和密码向服务器端发起请求,完成登录过程,其执行过程如下图所示:

② 其他接口请求

当登录完成后,客户端携带第一次登录获取的token,访问需要认证授权的接口,服务器端从客户端请求的头信息中解析出token信息,完成认证和角色的授权,如果认证通过并且拥有对应的访问权限,则最终能够请求到需要调用的接口。其执行详细流程如下图所示:

流程说明:

  • 携带token请求其他接口:一般我们在请求的头信息中携带 token 信息。
  • 验证是否需要身份认证:判断请求是否携带了 token,如果未携带,则不会执行认证过程,比如游客状态访问的一些资源就不需要携带token;如果携带了,则委托交给Shiro Realm 完成认证和授权。这边Shiro 提供了基础身份验证过滤器 BasicHttpAuthenticationFilter,我们只需要继承它,重写 isAccessAllowed、executeLogin 等方法完成是否需要身认证的判定过程。
  • 执行身份认证:身份认证过程主要包括获取token信息、解析token信息、检查库中用户是否存在、使用库中密钥校验token是否有效等。Shiro 中实现身份认证,我们只需要继承 AuthorizingRealm 类,重写 doGetAuthenticationInfo 方法,在该方法中完成我们认证的具体实现。
  • 获取用户授权信息:在认证通过之后,shiro 会自动调用 doGetAuthorizationInfo 方法获取该用户的授权信息。

二、集成步骤概览

三、步骤说明

1.引入依赖包

2.定义令牌工具类

令牌工具类主要用于创建令牌和验证令牌,详情如下所示:

  • com.shawn.springboot.integeration.common.config.shiro.token.JWTUtil#createToken:创建 Token
  • com.shawn.springboot.integeration.common.config.shiro.token.JWTUtil#verify:验证 Token
  • com.shawn.springboot.integeration.common.config.shiro.token.JWTUtil#getUsername:获取 Token中用户名

3.封装令牌类

Shiro 默认情况下,是使用自带的 UsernamePasswordToken 作为其令牌,由于我们选择使用JWT来生成Token,那么就需要实现一个JWTToken类来取代UsernamePasswordToken。

JWTToken类需要实现AuthenticationToken类并重写getPrincipal()和getCredentials()两个方法(原本是用来获得用户名和密码的,这里直接将token返回),其实现详情如图所示:

  • com.shawn.springboot.integeration.common.config.shiro.token.JWTToken

4.实现认证过滤器

实现身份验证过滤器,用于判断请求是否需要进行身份验证,并在需要时进行身份验证。由于shiro 默认提供了类 BasicHttpAuthenticationFilter,它是一个基础身份验证过滤器,我们只需要继承并重写其 isAccessAllowed、executeLogin、preHandle 方法。具体实现如下图所示:

  • com.shawn.springboot.integeration.common.config.shiro.filter.JWTFilter#isAccessAllowed:是否允许访问
  • com.shawn.springboot.integeration.common.config.shiro.filter.JWTFilter#executeLogin:执行登录操作(委托shiro 完成认证和授权)
  • com.shawn.springboot.integeration.common.config.shiro.filter.JWTFilter#preHandle:对跨域提供支持
  • com.shawn.springboot.integeration.common.config.shiro.filter.JWTFilter#responseError:私有方法,在认证异常时,直接重定向到未授权的请求接口。

5.实现认证与授权

通过自定义 Realm,继承 AuthorizingRealm 类,重写 doGetAuthenticationInfo 和 doGetAuthorizationInfo 方法完成认证与授权。代码概览如下所示:

  • com.shawn.springboot.integeration.common.config.shiro.realm.CustomRealm

① 实现认证

  • com.shawn.springboot.integeration.common.config.shiro.realm.CustomRealm#doGetAuthenticationInfo

实现认证主要校验token信息中是否包含用户名、校验数据库中用户名是否存在、校验token是否有效三个过程。

②实现授权

  • com.shawn.springboot.integeration.common.config.shiro.realm.CustomRealm#doGetAuthorizationInfo

授权过程主要包括从数据库中查询角色信息和权限信息,然后将其设置到授权信息对象中返回。

6.自定义配置类

定义 ShiroConfig 配置类,用于对 Shiro 框架的配置,主要完成的工作包括:

①.配置 ShiroFilterFactoryBean:用于配置 Shiro 过滤器链,并将 JWT 过滤器添加到过滤器链中。还设置了安全管理器和无权限时跳转的 URL,并将过滤规则应用到过滤器链中。

  • com.shawn.springboot.integeration.common.config.shiro.ShiroConfig#factory

②.设置 SecurityManager 对象:用于管理认证和授权。在这个方法中,设置了自定义的 Realm,并关闭了 Shiro 自带的 session。

  • com.shawn.springboot.integeration.common.config.shiro.ShiroConfig#factory

③.设置 DefaultAdvisorAutoProxyCreator:用于支持 AOP(面向切面编程)。通过强制使用 CGLIB 代理,可以防止重复代理和代理出错的问题。

  • com.shawn.springboot.integeration.common.config.shiro.ShiroConfig#defaultAdvisorAutoProxyCreator

④.设置 AuthorizationAttributeSourceAdvisor 对象:用于支持基于注解的授权。将安全管理器设置到这个对象中。

  • com.shawn.springboot.integeration.common.config.shiro.ShiroConfig#authAttrSrcAdviso

⑤.设置生命周期:设置在 Spring 容器中管理 Shiro Bean 的生命周期。

  • com.shawn.springboot.integeration.common.config.shiro.ShiroConfig#lifecycleBeanPostProcessor

四、测试

1.测试代码

  • com.shawn.springboot.integeration.system.controller.LoginController#login:登录接口
  • com.shawn.springboot.integeration.system.controller.SysUserController#addSave:添加用户接口,这个接口添加了注解 @RequiresPermissions("system:user:add"),需要有对应的权限才能请求。

2.测试结果

①.请求登录接口

如图所示,登录请求完成成功,获取到服务端生成的 token,然后我们用该token去请求需要认证授权的接口。

②.请求保存用户接口

头信息中携带token,请求成功,如果我们头信息不带 token信息,则会返回权限不足(在全局异常处理器中添加授权异常处理),效果如下图所示:

Tags:

最近发表
标签列表