4.0.0org.springframework.bootspring-boot-starter-parent2.5.0com.yzmshiro0.0.1-SNAPSHOTpomshiroDemo project for Spring Bootcommonshiro01shiro02shiro03shiro04shiro05shiro06UTF-8UTF-81.8org.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-testtestmysqlmysql-connector-javacom.baomidoumybatis-plus-boot-starter3.3.2com.baomidoumybatis-plus-generator3.3.2org.freemarkerfreemarker2.3.30org.projectlomboklombokorg.apache.commonscommons-lang3com.alibabafastjson1.2.62org.apache.shiroshiro-spring1.6.0org.springframework.bootspring-boot-starter-thymeleaforg.apache.maven.pluginsmaven-compiler-plugin${java.version}${java.version}${project.build.sourceEncoding}
shiro01 入门篇子工程
4.0.0com.yzmshiro0.0.1-SNAPSHOT../pom.xmlshiro010.0.1-SNAPSHOTjarshiro01Demo project for Spring Bootcom.yzmcommon0.0.1-SNAPSHOTorg.springframework.bootspring-boot-maven-plugin
3 数据库表
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户名称',
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户密码',
`salt` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '',
`r_ids` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户表';
CREATE TABLE `role` (
`r_id` int NOT NULL AUTO_INCREMENT,
`r_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '角色名称',
`r_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '角色描述',
`p_ids` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '',
PRIMARY KEY (`r_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='角色表';
CREATE TABLE `permissions` (
`p_id` int NOT NULL AUTO_INCREMENT,
`p_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '权限名称',
`p_desc` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '权限描述',
PRIMARY KEY (`p_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='权限表';
用户表
角色表
权限表
4 目录结构
entity、mapper、service等都是mybatis代码自动生成器生成
application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test3?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
username: root
password: root
mybatis-plus:
mapper-locations: classpath:/mapper
public class MyShiroRealm extends AuthorizingRealm {
private final UserService userService;
private final RoleService roleService;
private final PermissionsService permissionsService;
public MyShiroRealm(UserService userService, RoleService roleService, PermissionsService permissionsService) {
this.userService = userService;
this.roleService = roleService;
this.permissionsService = permissionsService;
}
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof UsernamePasswordToken;
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String username = (String) principalCollection.getPrimaryPrincipal();
// 查询用户,获取角色ids
User user = userService.lambdaQuery().eq(User::getUsername, username).one();
List roleIds = Arrays.stream(user.getRIds().split(","))
.map(Integer::parseInt)
.collect(Collectors.toList());
// 查询角色,获取角色名、权限ids
List roles = roleService.listByIds(roleIds);
Set roleNames = new HashSet<>(roles.size());
Set permIds = new HashSet<>();
roles.forEach(role -> {
roleNames.add(role.getRName());
Set collect = Arrays.stream(
role.getPIds().split(",")).map(Integer::parseInt).collect(Collectors.toSet());
permIds.addAll(collect);
});
// 获取权限名称
List permissions = permissionsService.listByIds(permIds);
List permNames = permissions.stream().map(Permissions::getPName).collect(Collectors.toList());
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
authorizationInfo.addRoles(roleNames);
authorizationInfo.addStringPermissions(permNames);
return authorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 获取用户名跟密码
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
String username = usernamePasswordToken.getUsername();
// 也可以这样获取
//String username = (String) authenticationToken.getPrincipal();
//String password = new String((char[]) authenticationToken.getCredentials());
// 查询用户是否存在
User user = userService.lambdaQuery().eq(User::getUsername, username).one();
if (user == null) {
throw new UnknownAccountException();
}
return new SimpleAuthenticationInfo(
user.getUsername(),
user.getPassword(),
// 用户名 + 盐
// 这里要跟EncryptUtils的一样
ByteSource.Util.bytes(user.getUsername() + user.getSalt()),
getName()
);
}
}
用户密码使用加密的
EncryptUtils.java 注册用户的时候加密,配置自定义的realm需要
package com.yzm.shiro01.utils;
import com.yzm.shiro01.entity.User;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
public class EncryptUtils {
private static final RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
public static final String ALGORITHM_NAME = "MD5"; // 散列算法
public static final int HASH_ITERATIONS = 2; // 散列次数
public static void encryptPassword(User user) {
// 随机字符串作为salt因子,实际参与运算的salt我们还引入其它干扰因子
user.setSalt(randomNumberGenerator.nextBytes().toHex());
user.setPassword(new SimpleHash(
ALGORITHM_NAME,
user.getPassword(),
// 用户名 + 盐
ByteSource.Util.bytes(user.getUsername() + user.getSalt()),
HASH_ITERATIONS
).toHex());
}
}