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 架构在大并发的演进过程更简单 ...
随机推荐
- Web通用漏洞--文件上传
Web通用漏洞--文件上传 概述 文件上传安全指的是攻击者通过利用上传实现后门的写入连接后门进行权限控制的安全问题,对于如何确保这类安全问题,一般会从原生态功能中的文件内容,文件后缀,文件类型等方面判 ...
- Kali开机启动模式修改
kali Linux安装之后默认启动图形化界面,为了减轻系统负担,可以修改启动进入字符界面. 具体步骤如下: 1.打开引导配置文件 vim /etc/default/grub 2.修改GRUB_CMD ...
- 关于 Llama 2 的一切资源,我们都帮你整理好了
Llama 2 是一个由 Meta 开发的大型语言模型,是 LLaMA 1 的继任者.Llama 2 可通过 AWS.Hugging Face 获取,并可以自由用于研究和商业用途.Llama 2 预训 ...
- Linux 内核音频数据传递主要流程 (下)
来而不往非礼也.前面看到了用户空间应用程序和 DMA buffer 之间交换数据,并更新 runtime->control->appl_ptr 指针的过程,这里看一下硬件设备驱动程序在完成 ...
- Linux 内核音频数据传递主要流程 (上)
Linux 用户空间应用程序通过声卡驱动程序(一般牵涉到多个设备驱动程序)和 Linux 内核 ALSA 框架导出的 PCM 设备文件,如 /dev/snd/pcmC0D0c 和 /dev/snd/p ...
- shopee的前景以及商用API(代码封装)
Shopee平台是东南亚和台湾地区最具代表性的电商平台之一,在过去几年里取得了巨大的成功.以下是Shopee平台的发展前景: 电商市场的快速增长:东南亚和台湾地区是人口众多.市场潜力巨大的区域,电商市 ...
- 面试题:Mybatis中的#{}和${}有什么区别?这是我见过最好的回答
面试题:Mybatis中的#{}和${}有什么区别? 前言 今天来分享一道比较好的面试题,"Mybatis中的#{}和${}有什么区别?". 对于这个问题,我们一起看看考察点和比较 ...
- Java并发Map的面试指南:线程安全数据结构的奥秘
简介 在计算机软件开发的世界里,多线程编程是一个重要且令人兴奋的领域.然而,与其引人入胜的潜力相伴而来的是复杂性和挑战,其中之一就是处理共享数据.当多个线程同时访问和修改共享数据时,很容易出现各种问题 ...
- 「shoi 2012」随机数
link. 对于 pass 1, 你把他考虑成 \(\frac{\sum x}{i}\) 的形式, 于是每次操作的贡献就是 \(\frac{2}{i}\), 那么答案就是 \(\sum_{i=2}^n ...
- 【效率提升】maven 转 gradle 实战
一.灵魂三问 1.gradle 是什么? 一个打包工具, 是一个开源构建自动化工具,足够灵活,可以构建几乎任何类型的软件,高性能.可扩展.能洞察等.其中洞察,可以用于分析构建过程中数据,提供分析参考, ...