2024.5.23 Thursday
接上文【WEEK13】 【DAY3】Shiro第三部分【中文版】
目录
15.6.Shiro整合MyBatis
15.6.1.修改pom.xml
导入5个依赖
<!--mysql-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--druid-->
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<!--mybatis-->
<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
</dependency>
15.6.2.新建application.yaml
直接使用之前使用过的yaml文件配置,复制粘贴过来,在最后进行一些修改。此时,application.properties中的所有内容可以被注释,不影响使用。
spring:
datasource:
username: root
password: 123456
#假如时区报错,就增加一个时区的配置,和其他配置用&连接,如:serverTimezone=UTC
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
#Spring Boot 默认是不注入这些属性值的,需要自己绑定
#druid 数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计; log4j:日志记录; wall:防御sql注入
#如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
#则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
mybatis:
# type-aliases-package: P40.pojo
mapper-locations: classpath:mapper/*.xml
#以上三行注意缩进,直接决定报错与否
15.6.3.连接数据库
新建了mybatis数据库
CREATE DATABASE `mybatis`;
USE `mybatis`;
CREATE TABLE `user`(
`id` INT(20) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`pwd` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `user`(`id`,`name`,`pwd`) VALUES
(1,'zhangsan','123456'),
(2,'lisi','2345678'),
(3,'wangwu','3456789');
15.6.4.修改application.properties
spring.application.name=shiro-springboot
#mybatis.type-aliases-package=P40.pojo
mybatis.mapper-locations=classpath:mapper/*.xml
这里注意!!!第二行起的别名在这里不能使用(会报错)所以应该注释掉,才可以运行成功!
15.6.5.新建pojo文件夹和mapper(两处)文件夹
15.6.5.1.新建User.java
package com.P40.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
}
15.6.5.2.新建UserMapper.java
package com.P40.mapper;
import com.P40.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Repository
@Mapper//这个mapper注不注释无所谓
public interface UserMapper {
public User queryUserByName(String name);
}
15.6.5.3.新建UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.P40.mapper.UserMapper">
<select id="queryUserByName" parameterType="String" resultType="com.P40.pojo.User">
SELECT * FROM mybatis.user WHERE name = #{name}
</select>
</mapper>
15.6.6.新建service文件夹
15.6.6.1.新建UserService.java
package com.P40.service;
import com.P40.pojo.User;
public interface UserService {
public User queryUserByName(String name);
}
15.6.6.2.新建UserServiceImpl.java
package com.P40.service;
import com.P40.mapper.UserMapper;
import com.P40.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;
@Override
public User queryUserByName(String name) {
return userMapper.queryUserByName(name);
}
}
15.6.6.3.单元测试
修改ShiroSpringbootApplicationTests.java
package com.P40;
import com.P40.service.UserServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ShiroSpringbootApplicationTests {
@Autowired
UserServiceImpl userService;
@Test
void contextLoads() {
System.out.println(userService.queryUserByName("lisi"));
}
}
但是这里测试运行不了【已解决】修改了yaml配置文件和UserMapper.xml文件(核心是取消了文件别名)
15.6.7.连接真实数据库
15.6.7.1.修改UserRealm.java
package com.P40.config;
import com.P40.pojo.User;
import com.P40.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
//UserRealm是一个bean
//自定义的UserRealm,必须要继承AuthorizingRealm方法,然后implement methods(alt+insert)
public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("do doGetAuthorizationInfo 授权");
return null;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("do doGetAuthorizationInfo 认证");
//用户名,密码————数据读取。以下两行是编程初期模拟连接数据库得到的用户数据
// String name = "root";
// String password = "1";
UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
// if (!userToken.getUsername().equals(name)){
// return null; //抛出UnknownAccountException异常(自动的)
// }
//改为连接真实数据库
User user = userService.queryUserByName(userToken.getUsername());
if(user == null){ //此用户不存在
return null; //UnknownAccountException
}
//密码认证,shiro运行
// return new SimpleAuthenticationInfo("",password,"");
return new SimpleAuthenticationInfo("",user.getPwd(),"");
}
}
15.6.7.2.修改User表
添加一行数据
15.6.7.3.重启ShiroSpringbootApplication.java
http://localhost:8080/toLogin
对照User表中的用户名和密码进行登录测试
登录成功
直接把url中username改成root,由于password也是123456,故能够保持登录状态:
若把username改为lisi,因为lisi的password是2345678,所以显示密码错误,无法登录:
登录wangwu的账户,但将用户名输错,显示用户名错误,也无法登陆:
15.6.7.4.当前使用的是一般的加密
CredentialsMatcher.java
在MyController.java中新建断点,查看运行流程
亦可在UserRealm.java中新建断点
此时在CredentialsMatcher中没有把用户在网页中输入的密码进行加密,所以在url中密码显式出现(明文密码)。
点击左侧栏中绿色I,可以展开十种加密方法,其中默认使用的是SimpleCredentialsMatcher.
实际使用过程中MD5加密由于相同的明文密码被加密后得到的结果相同,更安全的方式是MD5盐值加密(在产生和MD相同的密码加密结果的末端还会加上用户名)