Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
如果你对shiro有问题的话,请看这篇文章:Springboot+shiro,完整教程,带你学会shiro-CSDN博客
第一步,先准备数据库:
数据库需要准备三个表,一个user表,一个role表,一个permission表。
user表:
CREATE TABLE `user` (
`id` int NOT NULL,
`username` varchar(100) DEFAULT NULL,
`password` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
role表:
CREATE TABLE `role` (
`id` int NOT NULL,
`name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
permission表:
CREATE TABLE `permission` (
`id` int NOT NULL,
`name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
然后插入数据:



第一个是user表,第二个是permission表,第三个是role表。大家自己建就是了。
第二步就是创建springboot项目,并操作数据库。
pom文件:
<?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>org.tianfan</groupId>
<artifactId>shiroTest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.9.1</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.mybatis.spring.boot</groupId>-->
<!-- <artifactId>mybatis-spring-boot-starter</artifactId>-->
<!-- <version>3.0.0</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.21</version>
<scope>test</scope>
</dependency>
<!-- springbootweb-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.7</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.31</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
</project>
application文件:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://localhost:3306/tianfan?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
配置实体类:
user类:
package org.tianfan.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User implements Serializable {
private Long id;
private String username;
private String password;
}
Role类:
package org.tianfan.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Role implements Serializable {
private Long id;
private String name;
// getter and setter
}
permission类:
package org.tianfan.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Permission implements Serializable {
private Long id;
private String name;
// getter and setter
}
准备mapper
PermissionMapper
package org.tianfan.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.tianfan.pojo.Permission;
public interface PermissionMapper extends BaseMapper<Permission> {
}
RoleMapper
package org.tianfan.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.tianfan.pojo.Role;
public interface RoleMapper extends BaseMapper<Role> {
}
UserMapper
package org.tianfan.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.tianfan.pojo.User;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
准备service
UserService:
package org.tianfan.service;
import org.apache.ibatis.annotations.Mapper;
import org.tianfan.pojo.Permission;
import org.tianfan.pojo.Role;
import org.tianfan.pojo.User;
import java.util.List;
public interface UserService {
User findByUsername(String username);
List<Role> findRolesByUserId(Long userId);
List<Permission> findPermissionsByRoleId(Long roleId);
}
准备serviceImpl
UserServiceImpl
package org.tianfan.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.tianfan.mapper.PermissionMapper;
import org.tianfan.mapper.RoleMapper;
import org.tianfan.mapper.UserMapper;
import org.tianfan.pojo.Permission;
import org.tianfan.pojo.Role;
import org.tianfan.pojo.User;
import org.tianfan.service.UserService;
import java.util.ArrayList;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;
@Autowired
RoleMapper roleMapper;
@Autowired
PermissionMapper permissionMapper;
@Override
public User findByUsername(String username) {
LambdaQueryWrapper<User> lambdaQueryWrapper=new LambdaQueryWrapper();
lambdaQueryWrapper.eq(User::getUsername,username);
User user = userMapper.selectOne(lambdaQueryWrapper);
System.out.println(user);
return user;
}
@Override
public List<Role> findRolesByUserId(Long userId) {
LambdaQueryWrapper lambdaQueryWrapper=new LambdaQueryWrapper();
lambdaQueryWrapper.eq("id",userId);
Role role = roleMapper.selectOne(lambdaQueryWrapper);
List<Role> list=new ArrayList<>();
list.add(role);
return list;
}
@Override
public List<Permission> findPermissionsByRoleId(Long roleId) {
LambdaQueryWrapper lambdaQueryWrapper=new LambdaQueryWrapper();
lambdaQueryWrapper.eq("id",roleId);
Permission permission = permissionMapper.selectOne(lambdaQueryWrapper);
List<Permission> list=new ArrayList<>();
list.add(permission);
return list;
}
}
现在为止,开始配置shiro
配置一下ShiroConfig,配置那些比如说shiro要过滤的请求,securityManager(管理shiro对象的类)拿到主体的关键类,MyShiroRealm认证规格类,LifecycleBeanPostProcessor,用于在Spring容器中管理Shiro的生命周期。
package org.tianfan.config;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.shiro.mgt.SecurityManager;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/login.html", "anon");
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public SessionsSecurityManager securityManager(MyShiroRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//配置realm
securityManager.setRealm(userRealm);
return securityManager;
}
@Bean
public MyShiroRealm myShiroRealm() {
MyShiroRealm myShiroRealm = new MyShiroRealm();
return myShiroRealm;
}
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
MyShiroRealm认证规格类:
package org.tianfan.config;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.tianfan.service.UserService;
import org.tianfan.pojo.Permission;
import org.tianfan.pojo.Role;
import org.tianfan.pojo.User;
import org.tianfan.service.impl.UserServiceImpl;
import java.util.List;
public class MyShiroRealm extends AuthorizingRealm {
@Autowired
private UserServiceImpl userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
User user = (User) principalCollection.getPrimaryPrincipal();
List<Role> roles = userService.findRolesByUserId(user.getId());
for (Role role : roles) {
authorizationInfo.addRole(role.getName());
List<Permission> permissions = userService.findPermissionsByRoleId(role.getId());
for (Permission permission : permissions) {
authorizationInfo.addStringPermission(permission.getName());
}
}
return authorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
System.out.println(token.getUsername());
User user = userService.findByUsername(token.getUsername());
if (user == null) {
throw new UnknownAccountException();
}
return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
}
}
现在就可以测试了,Contoller类:
package org.tianfan.contoller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.tianfan.pojo.User;
import org.tianfan.service.UserService;
@RestController
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/login")
public String login( String username, String password) {
System.out.println(username+password);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
subject.login(token);
return "登录成功";
} catch (AuthenticationException e) {
return "用户名或密码错误";
}
}
@GetMapping("/user")
public User getUser() {
Subject subject = SecurityUtils.getSubject();
return (User) subject.getPrincipal();
}
@GetMapping("/admin")
public String admin() {
return "admin";
}
}
主类:
package org.tianfan;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class);
}
}
前端页面login.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录表单</title>
<style type="text/css">
body {
background-color: #333;
font-family: Arial, sans-serif;
font-size: 14px;
color: #fff;
}
.container {
margin: 0 auto;
width: 400px;
padding: 20px;
background-color: #444;
border-radius: 5px;
box-shadow: 0 0 10px #000;
}
h2 {
margin-top: 0;
text-align: center;
}
form {
display: block;
margin: 0;
padding: 0;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="text"], input[type="password"], input[type="email"] {
display: block;
width: 100%;
padding: 10px;
margin-bottom: 10px;
border: none;
border-radius: 5px;
background-color: #555;
color: #fff;
font-size: 14px;
}
input[type="submit"], input[type="reset"] {
display: inline-block;
padding: 10px 20px;
margin-right: 10px;
border: none;
border-radius: 5px;
background-color: #f00;
color: #fff;
font-size: 14px;
cursor: pointer;
}
input[type="submit"]:hover, input[type="reset"]:hover {
background-color: #c00;
}
.third-party {
margin-top: 20px;
text-align: center;
}
.third-party a {
display: inline-block;
margin-right: 10px;
border-radius: 50%;
background-color: #fff;
color: #000;
font-size: 20px;
line-height: 40px;
width: 40px;
height: 40px;
text-align: center;
text-decoration: none;
transition: all 0.3s ease;
}
.third-party a:hover {
background-color: #000;
color: #fff;
}
</style>
</head>
<body>
<div class="container">
<h2>登录</h2>
<form action="http://localhost:8080/login" method="post" name="login-form">
<label for="username">用户名</label>
<input type="text" id="username" name="username" required>
<label for="password">密码</label>
<input type="password" id="password" name="password" required>
<input type="submit" value="登录">
<input type="reset" value="重置">
</form>
<div class="third-party">
<a href="#">QQ</a>
<a href="#">微信</a>
<a href="#">微博</a>
</div>
</div>
</body>
</html>
运行启动结果图:

输入正确的密码:


之后就可以直接访问

如果没有登录正确的账号信息的话,就不可以访问这个,并且会直接跳转到login.jsp
如果你对shiro有问题的话,请看这篇文章:Springboot+shiro,完整教程,带你学会shiro-CSDN博客
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个的更多相关文章
- springboot+layui 整合百度富文本编辑器ueditor入门使用教程(踩过的坑)
springboot+layui 整合百度富文本编辑器ueditor入门使用教程(踩过的坑) 写在前面: 富文本编辑器,Multi-function Text Editor, 简称 MTE, 是一 ...
- duilib教程之duilib入门简明教程8.完整的自绘标题栏
看了前面那么多教程,相信对duilib已有基本映像了,我们就快马加鞭,做出一个完整的自绘标题栏吧~ 看到下面这个效果图,小伙伴们是不是有点惊呆了呢~O(∩_∩)O~ duilib实现以 ...
- hadoop入门学习教程--DKHadoop完整安装步骤
使用hadoop版本是DKH标准三节点发行版,DKHadoop版本的易用性比较好,环境部署要简单的多,参考此篇安装前请先下载DKHadoop版本,网盘链接:https://pan.baidu.com/ ...
- springboot整合ueditor实现图片上传和文件上传功能
springboot整合ueditor实现图片上传和文件上传功能 写在前面: 在阅读本篇之前,请先按照我的这篇随笔完成对ueditor的前期配置工作: springboot+layui 整合百度富文本 ...
- spring-session(二)与spring-boot整合实战
前两篇介绍了spring-session的原理,这篇在理论的基础上再实战. spring-boot整合spring-session的自动配置可谓是开箱即用,极其简洁和方便.这篇文章即介绍spring- ...
- springBoot整合spring security+JWT实现单点登录与权限管理--筑基中期
写在前面 在前一篇文章当中,我们介绍了springBoot整合spring security单体应用版,在这篇文章当中,我将介绍springBoot整合spring secury+JWT实现单点登录与 ...
- SpringBoot整合开发
1.SpringBoot分模块 分模块就是将一个项目分成多个模块,即maven项目. 1)首先创建一个springboot的项目: 第一步:选择springboot的项目 第二步:填写项目的相关信息, ...
- Taurus.MVC 微服务框架 入门开发教程:项目部署:1、微服务应用程序常规部署实现多开,节点扩容。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...
- Taurus.MVC 微服务框架 入门开发教程:项目部署:2、让Kestrel支持绑定多个域名转发,替代Ngnix使用。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...
- Taurus.MVC 微服务框架 入门开发教程:项目部署:3、微服务应用程序版本升级:全站升级和局部模块升级。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...
随机推荐
- papricice
2023-07-14 题目 题目传送门 题目大意 给定一个 \(n\) 个点的树,这 \(n\) 个点编号为 \(1\) 到 \(n\). 现在要选择断掉两条边,会形成三个连通块,假设这三个连通块内的 ...
- ATtiny88初体验(三):串口
ATtiny88初体验(三):串口 ATtiny88单片机不包含串口模块,因此只能使用软件方式模拟串口时序. 串口通信时序通常由起始位.数据位.校验位和停止位四个部分组成,常见的配置为1位起始位.8位 ...
- 多重断言插件之pytest-assume的简单使用
背景: pytest-assume是Pytest框架的一个扩展,它允许在单个测试用例中多次断言.通常情况下,当一个断言失败时,测试会立即停止执行,而pytest-assume允许我 们继续执行剩余的断 ...
- 为什么创建 Redis 集群时会自动错开主从节点?
哈喽大家好,我是咸鱼 在<一台服务器上部署 Redis 伪集群>这篇文章中,咸鱼在创建 Redis 集群时并没有明确指定哪个 Redis 实例将担任 master,哪个将担任 slave ...
- centos8环境基本优化
centos8环境基本优化 目录 centos8环境基本优化 1.防火墙优化 2.源优化: 方案1.更换阿里源 方案2.使用centos8.5 源 安装epel源 3.ssh连接慢解决 4.关闭公网, ...
- MySQL实战实战系列 02 日志系统:一条SQL更新语句是如何执行的?
前面我们系统了解了一个查询语句的执行流程,并介绍了执行过程中涉及的处理模块.相信你还记得,一条查询语句的执行过程一般是经过连接器.分析器.优化器.执行器等功能模块,最后到达存储引擎. 那么,一条更新语 ...
- zxy 简单 dp 大讲堂
讲课讲得非常清楚啊,我绝赞膜拜.节奏可以,思路清晰,解法自然,为讲师点赞. 第一个题是 loj3282 / joisc2020 - Treatment Project.原问题由 \(\left(S, ...
- package.json指南
一.属性 name 定义项目的名称,不能以"."和"_"开头,不能包含大写字母 version 定义项目的版本号,格式为:大版本号.次版本号.修订号 descr ...
- SpringBoot WebSocket STOMP
SpringBoot WebSocket STOMP 关键词:Springboot, WebSocket, STOMP, broadcast, sendToUser, MessageMapping, ...
- Nuxt.js 生成sitemap站点地图文件
Nuxt.js 生成sitemap站点地图文件 背景介绍 使用nuxt框架生成静态文件支持SEO优化,打包之后需要生成一个 sitemap.xml 文件方便提交搜索引擎进行收录.官网有提供一个插件 ...