springboot 整合 shiro 框架自定义登录验证和权限管理

本文介绍 springboot 项目整合 shiro 框架过程。

复制代码
项目版本信息:
jdk 1.8
springboot 2.7.18 
mysql 5.7

一、添加依赖

xml 复制代码
<!-- 添加依赖-->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-starter</artifactId>
    <version>1.9.0</version>
</dependency>
<!-- 添加mybatisplus依赖-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.0.5</version>
</dependency>
<!-- 添加mysql依赖-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
</dependency>
<!-- 添加lombok依赖-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
<!-- 添加thymeleaf依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

二、添加配置

yaml 复制代码
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath:mapper/*.xml
spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/shirodemo?characterEncoding=utf-8&useSSL=false
    username: your_username
    password: your_password
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
shiro:
  loginUrl: /myController/login

三、创建数据库

sql 复制代码
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(30) DEFAULT NULL,
  `pwd` varchar(50) DEFAULT NULL,
  `rid` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

根据需求插入数据:

四、创建实体类

五、创建 mapper 接口

复制代码
使用了 mybatisplus ,只需要继承 BaseMapper 接口就能自动生成简单的 crud 操作。

六、创建业务层接口,并写出接口实现类

css 复制代码
注意加上 @service 注解

七、启动类添加 @MapperScan("com.yuqn.shiro_springboot.mapper") 注解,扫描 mapper 包下的接口。

复制代码
上述一至七,都是shiro进行登录认证和权限管理必备的前提。

八、自定义登录认证

8.1、创建自定义realm

需要继承 AuthorizingRealm 类,并且重写 doGetAuthenticationInfo 和 doGetAuthorizationInfo,其中 doGetAuthenticationInfo() 就是写自定义登录验证的方法, doGetAuthorizationInfo() 则是自定义授权方法,代码如下:

java 复制代码
/**
 * @author: yuqn
 * @Date: 2024/4/10 14:49
 * @description:
 * 自定义登录认证方法
 * @param: null
 * @return: null
 */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    // 1、获取用户信息
    String name = authenticationToken.getPrincipal().toString();
    // 2、获取数据库用户信息
    User user = userService.getUserInfoByName(name);
    // 3、判断,将数据封装返回
    if (user != null){
        AuthenticationInfo info = new SimpleAuthenticationInfo(
                authenticationToken.getPrincipal(),
                user.getPwd(),
                ByteSource.Util.bytes("yuqn"),
                authenticationToken.getPrincipal().toString()
        );
        System.out.println(info);
        return info;
    }
    return null;
}

8.2、创建配置类

通过配置类,创建一系列需要的对象(如加密器等)存储到realm中,并且配置 shiro 内置过滤器。

java 复制代码
@Configuration
public class ShiroConfig {

    @Resource
    private MyRealm myRealm;

    // 配置securitymanager
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(){
        // 1、创建defaultWebSecurityManager对象
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        // 2、创建加密对象,设置相关属性
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        hashedCredentialsMatcher.setHashIterations(1);
        // 3、将加密对象存储到myRealm中
        myRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        // 4、将myRealm存入到defaultWebSecurityManager对象
        defaultWebSecurityManager.setRealm(myRealm);
        // 5、返回
        return defaultWebSecurityManager;
    }

    // 配置shiro内置过滤器拦截范围
    @Bean
    public DefaultShiroFilterChainDefinition shiroFilterChainDefinition(){
        DefaultShiroFilterChainDefinition defaultShiroFilterChainDefinition = new DefaultShiroFilterChainDefinition();
        // 设置不认证可以访问的资源
        defaultShiroFilterChainDefinition.addPathDefinition("/myController/userLogin","anon");
        defaultShiroFilterChainDefinition.addPathDefinition("/login","anon");
        // 设置需要进行登录认证的拦截范围
        defaultShiroFilterChainDefinition.addPathDefinition("/**","authc");
        return defaultShiroFilterChainDefinition;
    }

}

8.3、添加控制器

创建控制器,用于接收前端请求并且做出处理。

less 复制代码
@Controller
@RequestMapping("myController")
public class MyController {
    @GetMapping("userLogin")
    @ResponseBody
    public String userLogin(String name,String pwd){
        // 1获取subject对象
        Subject subject = SecurityUtils.getSubject();
        // 2封装请求数据到token
        AuthenticationToken token = new UsernamePasswordToken(name,pwd);
        // 3调用login方法进行登录认证
        try{
            subject.login(token);
            return "登录成功";
        }catch(AuthenticationException e){
            e.printStackTrace();
            System.out.println("登录失败");
            return "登录失败";
        }

    }
}

这里使用 get 请求更方便,实际开发中不建议使用 get 请求进行登录,安全性较低。

8.4、浏览器测试

启动项目,通过浏览器访问地址 http://localhost:8080/myController/userLogin?name=admin&pwd=123456

通过浏览器访问地址 http://localhost:8080/myController/userLogin?name=admin&pwd=123123

复制代码
数据库里面的 admin 密码是使用 md5 进行一次加盐加密的,原数据为 123456,加盐为 yuqn。

8.4、不足之处

实际开发中,密码一般是从前端用户传递而来,为了安全,一般是前端进行处理后后传到后端,那么后端得到的基本就是加密后的密码了,只需要通过 shiro 进行验证即可。

九、权限管理

十、拓展

shiro 是一个安全的框架,主要用来进行登录验证、权限管理。

10.1、shiro有三大核心,分别是:

1、Subject: 代表了当前用户的操作,包含了用户的身份(Principals)和凭据(Credentials)。

2、SecurityManager: 是Shiro框架的核心,负责对所有的Subject进行管理,它是Shiro的守门神,管理着所有的安全操作。

3、Realm: 是Shiro与应用安全数据之间的桥梁,它负责获取安全数据(如用户、角色、权限)。

10.2、shiro 框架和 spring security 框架的区别:

1、shiro 是在 apache 下的工具, spring security 是在 spring 下的工具

2、shiro 不依赖任何框架, spring security 依赖 spring 框架

3、spring security 相比 shiro 更加复杂

4、因为 spring security 是在 spring 下,所以 spring security 能够更好地与spring mvc框架整合

相关推荐
砍材农夫1 小时前
spring|spring web|拦截器、过滤器、aop
java·spring boot·spring·spring cloud
考虑考虑8 小时前
docker compose V2版本新属性
运维·后端·自动化运维
weixin_BYSJ198710 小时前
【计算机毕设】基于SpringBoot与Vue的文物保护档案管理系统08621
vue.js·spring boot·spring cloud·微服务·架构·django·课程设计
GreenTea10 小时前
7000 万 QPS、500 PB:OpenAI 如何用一个 Python 存储平台撑住 10 亿用户
后端·架构
Flynt10 小时前
Java 27 升级实测:默认值动得比新特性多,有个老参数会让 JVM 直接起不来
java·jvm·后端
Bs_MoneyMagnet10 小时前
基于springboot+vue的个人健康管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·vue3·springboot3·计算机毕业设计
GreenTea10 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
Bs_MoneyMagnet13 小时前
基于springboot+vue的心理咨询预约与随访平台的设计与实现 源码+文档
vue.js·spring boot·后端·spring·毕业设计·旅游·计算机毕业设计
IT_陈寒13 小时前
Vue的响应式更新把我坑惨了,原来问题出在这
前端·人工智能·后端
陌シ未央ゞ14 小时前
基于BM25算法和RRF实现的混合索引(java版)
人工智能·spring boot·后端·算法