Shiro与SpringBoot整合
Shiro与SpringBoot整合
这里前端页面 采用thymeleaf进行渲染
1、导入基本的依赖坐标
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.9.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.23</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.7.4</version>
</dependency>
2、创建数据库表
/*
Navicat Premium Data Transfer
Source Server : 本机
Source Server Type : MySQL
Source Server Version : 80029
Source Host : localhost:3306
Source Schema : shirodb
Target Server Type : MySQL
Target Server Version : 80029
File Encoding : 65001
Date: 21/12/2022 18:22:39
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`pwd` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`rid` bigint NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '张三', '07ca00e10899418f0ea4ab92a9d69065', NULL);
INSERT INTO `user` VALUES (2, '李四', '07ca00e10899418f0ea4ab92a9d69065', NULL);
SET FOREIGN_KEY_CHECKS = 1;
这里的密码是直接三层加密获得的(是123)
3、创建yml文件
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/shirodb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: 20020630
#mybatis
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: com.aiit.pojo.po
global-config:
#数据库相关配置
db-config:
#主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID", ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
id-type: AUTO
logic-delete-value: 0
logic-not-delete-value: 1
banner: false
#指定登录的地址--用来重定向到登录页面
shiro:
loginUrl: /myController/login
4、自定义MyRealm类
@Component
public class MyRealm extends AuthorizingRealm {//这里继承的是AuthorizingRealm是AuthenticatingRealm的子类
@Autowired
UserService userService;
//自定义授权方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
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("salt"),
name
);
return info;
}
return null;
}
}
这里调用了service层进行用户的查询
用户实体类
@Data
public class User {
private Integer id;
private String name;
private String pwd;
private Integer rid;
}
service层具体代码
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User getUserInfoByName(String name) {
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper.eq("name",name);
User user = userMapper.selectOne(wrapper);
return user;
}
}
5、创建ShiroConfig配置类
@Configuration
public class ShiroConfig {
@Autowired
private MyRealm myRealm;
//配置SecurityManager
@Bean
public DefaultWebSecurityManager defaultWebSecurityManager() {
//1、创建对象
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
//2、创建加密对象,设置相关属性
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
matcher.setHashAlgorithmName("md5");
matcher.setHashIterations(3);//迭代次数
//3、将加密对象存储到myRealm中
myRealm.setCredentialsMatcher(matcher);
//4、将myRealm存入DefaultWebSecurityManager对象中
defaultWebSecurityManager.setRealm(myRealm);
//5、返回
return defaultWebSecurityManager;
}
@Bean
public DefaultShiroFilterChainDefinition shiroFilterChainDefinition(){
DefaultShiroFilterChainDefinition definition=new DefaultShiroFilterChainDefinition();
//设置不认证可以访问的资源
definition.addPathDefinition("/myController/userLogin","anon");
definition.addPathDefinition("/myController/login","anon");
definition.addPathDefinition("/**","authc");
return definition;
}
}
参数的解释:
anon:无需认证即可访问。
authc:需要认证才可访问。
user:点击“记住我”功能可访问。
6、创建Controller层
@Controller
@RequestMapping("myController")
public class MyController {
@GetMapping("/login")
public String login(){
return "login";
}
@GetMapping("/userLogin")
public String userLogin(String name, String password, HttpSession session){
//1、获取subject对象
Subject subject = SecurityUtils.getSubject();
//封装请求数据到token
AuthenticationToken token=new UsernamePasswordToken(name,password);
try {
subject.login(token);
session.setAttribute("user",token.getPrincipal().toString());
return "main";
} catch (AuthenticationException e) {
System.out.println("登录失败");
throw new RuntimeException(e);
}
}
}
7、创建前端页面
在resource下创建templates目录
在该目录下创建login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<div id="loginDiv">
<form action="/myController/userLogin" id="form" method="get">
<h1 id="loginMsg">LOGIN IN</h1>
<p>Username:<input id="username" name="name" type="text"></p>
<p>Password:<input id="password" name="password" type="password"></p>
<div id="subDiv">
<input type="submit" class="button" value="login up">
<input type="reset" class="button" value="reset">
</div>
</form>
</div>
</body>
</html>
在该目录下创建mian.html
登录成功后的跳转页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>shiro登录认证后主页面</h1>
登录的用户为<span th:text="${session.user}"></span>
</body>
</html>
8、测试
输入账号张三和密码123
登录成功