Introduction : Expliquer le domaine par défaut de shiro et les méthodes d'utilisation courantes
-
Rôle Realm : Shiro obtient les données de sécurité de Realm
-
Le domaine qui l'accompagne par défaut : idae vérifie la relation d'héritage du domaine, il existe des domaines avec une implémentation par défaut et un héritage personnalisé
-
deux notions
- principal : il peut y avoir plusieurs principaux, mais ils doivent être uniques. Les principaux incluent le nom d'utilisateur, le numéro de téléphone mobile, l'adresse e-mail, etc.
- informations d'identification : informations d'identification, généralement des mots de passe
- Donc, généralement, nous disons que principal + identifiant est compte + mot de passe
-
En développement, il s'agit souvent d'un domaine personnalisé, c'est-à-dire intégrez AuthorizingRealm ! ! ! ! ! !
Relation d'héritage et d'implémentation du domaine
Démarrage rapide Shiro intégré IniRealm fonctionnement pratique et API de vérification des autorisations
Combat réel : obtenez la prise utilisateur à partir du fichier shiro.ini, puis évaluez les autorisations pertinentes de cet utilisateur.
Note ⚠️ : Cette façon d'écrire est de nous faire comprendre ce que fait le framework shiro, sans se connecter à la base de données, pour expérimenter rapidement le rôle du framework de sécurité de shiro. Dans le développement réel, cette méthode ne sera certainement pas utilisée.
Créez un fichier shiro.ini dans le répertoire des ressources
shiro.ino
# 格式 name=password,role1,role2,..roleN
[users]
# user 'root' with password 'secret' and the 'admin' role,
jack = 456, user
# user 'guest' with the password 'guest' and the 'guest' role
lll = 123, root,admin
# 格式 role=permission1,permission2...permissionN 也可以用通配符
# 下面配置user的权限为所有video:find,video:buy,如果需要配置video全部操作crud 则 user = video:*
[roles]
user = video:find,video:buy
# 'admin' role has all permissions, indicated by the wildcard '*'
admin = *
复制代码
Classe de test : QuickStartTest3.java
package com.lzh;
/**
* @Author:kaiyang.cui
* @Package:com.lzh
* @Project:lzh_shiro
* @name:QuickStartTest
* @Date:2023/3/27 下午2:05
* @Filename:QuickStartTest
* @Description:从shiro.ini 文件中取到用户jack,然后判断这个用户的相关权限
* @Version:1.0
*/
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;
public class QuickStartTest3 {
@Test
public void testAuthentication() {
// 创建SecurityManager工厂,通过配置文件ini创建
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
// 将securityManager设置到当前运行环境中
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
// 模拟用户输入的用户名和密码
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("jack", "456");
subject.login(usernamePasswordToken);
// 获取验证结果 isAuthenticated() 是否授权,结果是boolen
System.out.println("认证结果:" + subject.isAuthenticated());
// 是否有对应的角色
System.out.println("是否有user角色:" + subject.hasRole("user"));
System.out.println("getPrincipal认证结果-实际上就是获取登录用户账号" + subject.getPrincipal());
System.out.println("检查是否有视频删除权限,如果有则不报错,没有就报错。不用担心");
try {
subject.checkPermission("video:delete");
} catch (Exception e) {
System.err.println("没有video:delete权限");
}
//isPermitted() 和 checkPermission() 方法的区别是,前者有返回值,后者没有
System.out.println("是否有视频购买权限:" + subject.isPermitted("video:buy"));
// 退出登录
subject.logout();
// 检查用户退出登录后的认证结果
System.out.println("认证结果:" + subject.isAuthenticated());
}
}
复制代码
认证结果:true
是否有user角色:true
getPrincipal认证结果-实际上就是获取登录用户账号jack
检查是否有视频删除权限,如果有则不报错,没有就报错。不用担心
没有video:delete权限
是否有视频购买权限:true
认证结果:false
复制代码
Démarrage rapide Shiro intégré JdbcRealm fonctionnement pratique
Cette méthode est recommandée pour le développement
Créez d'abord une base de données, vous pouvez choisir le nom de la base de données, ce qui suit est le SQL pour créer une table et insérer des données de base
Cette table est un utilisateur correspondant à plusieurs rôles, et un rôle correspondant à plusieurs autorisations.
/*
Navicat MySQL Data Transfer
Source Server : 阿里云华北root
Source Server Type : MySQL
Source Server Version : 80024
Source Host : 39.97.253.89:3306
Source Schema : class_shiro
Target Server Type : MySQL
Target Server Version : 80024
File Encoding : 65001
Date: 27/03/2023 16:38:39
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for roles_permissions
-- ----------------------------
DROP TABLE IF EXISTS `roles_permissions`;
CREATE TABLE `roles_permissions` (
`id` bigint NOT NULL AUTO_INCREMENT,
`role_name` varchar(100) DEFAULT NULL,
`permission` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_roles_permissions` (`role_name`,`permission`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb3;
-- ----------------------------
-- Records of roles_permissions
-- ----------------------------
BEGIN;
INSERT INTO `roles_permissions` VALUES (4, 'admin', 'video:*');
INSERT INTO `roles_permissions` VALUES (3, 'role1', 'video:buy');
INSERT INTO `roles_permissions` VALUES (2, 'role1', 'video:find');
INSERT INTO `roles_permissions` VALUES (5, 'role2', '*');
INSERT INTO `roles_permissions` VALUES (1, 'root', '*');
COMMIT;
-- ----------------------------
-- Table structure for user_roles
-- ----------------------------
DROP TABLE IF EXISTS `user_roles`;
CREATE TABLE `user_roles` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(100) DEFAULT NULL,
`role_name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_user_roles` (`username`,`role_name`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb3;
-- ----------------------------
-- Records of user_roles
-- ----------------------------
BEGIN;
INSERT INTO `user_roles` VALUES (1, 'jack', 'role1');
INSERT INTO `user_roles` VALUES (2, 'jack', 'role2');
INSERT INTO `user_roles` VALUES (4, 'lzh', 'admin');
INSERT INTO `user_roles` VALUES (3, 'lzh', 'root');
COMMIT;
-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(100) DEFAULT NULL,
`password` varchar(100) DEFAULT NULL,
`password_salt` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_users_username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb3;
-- ----------------------------
-- Records of users
-- ----------------------------
BEGIN;
INSERT INTO `users` VALUES (1, 'jack', '123', NULL);
INSERT INTO `users` VALUES (2, 'lzh', '456', NULL);
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
复制代码
Créez ensuite le fichier jdbcrealm.ini dans le répertoire des ressources : jdbcrealm.ini
#注意 文件格式必须为ini,编码为ANSI
#声明Realm,指定realm类型
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
#配置数据源
#dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
dataSource=com.alibaba.druid.pool.DruidDataSource
# mysql-connector-java 5 用的驱动url是com.mysql.jdbc.Driver,mysql-connector-java6以后用的是com.mysql.cj.jdbc.Driver
dataSource.driverClassName=com.mysql.cj.jdbc.Driver
#避免安全警告
dataSource.url=jdbc:mysql://39.97.253.89:3306/class_shiro?characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
dataSource.username=你的账号
dataSource.password=你的密码
#指定数据源
jdbcRealm.dataSource=$dataSource
#开启查找权限, 默认是false,不会去查找角色对应的权限,坑!!!!!
jdbcRealm.permissionsLookupEnabled=true
#指定SecurityManager的Realms实现,设置realms,可以有多个,用逗号隔开
securityManager.realms=$jdbcRealm
复制代码
Il y a un gouffre ici. Bien que nous puissions écrire le pilote MySQL comme nous le voulons lorsque nous créons le projet SpringBoot, ce fichier respecte strictement les règles suivantes. L'url du pilote utilisé par mysql-connector-java 5 est com.mysql.jdbc. Le pilote, com.mysql.cj.jdbc.Driver est utilisé après mysql-connector-java6
Méthode JdbcRealm 1 : écrivez jdbcrealm.ini et utilisez jdbcrealm.ini pour aider shiro à simuler la base de données de requêtes de connexion des utilisateurs afin d'obtenir les informations d'autorisation
Testez le code pour écrire ce fichier via jdbcrealm.ini :
package com.lzh;
/**
* @Author:kaiyang.cui
* @Package:com.lzh
* @Project:lzh_shiro
* @name:QuickStartTest
* @Date:2023/3/27 下午2:05
* @Filename:QuickStartTest
* @Description:从shiro.ini 文件中取到用户jack,然后判断这个用户的相关权限
* @Version:1.0
*/
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;
public class QuickStartTest4 {
@Test
public void testAuthentication() {
// 创建SecurityManager工厂,通过配置文件ini创建
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:jdbcrealm.ini");
SecurityManager securityManager = factory.getInstance();
// 将securityManager设置到当前运行环境中
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
// 模拟用户输入的用户名和密码
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("jack", "123");
subject.login(usernamePasswordToken);
// 获取验证结果 isAuthenticated() 是否授权,结果是boolen
System.out.println("认证结果:" + subject.isAuthenticated());
// 是否有对应的角色
System.out.println("是否有user角色:" + subject.hasRole("admin"));
// 是否有对应的权限
System.out.println("是否有对应的权限:" + subject.isPermitted("video:delete"));
}
}
复制代码
认证结果:true
是否有user角色:false
是否有对应的权限:false
复制代码
Dans la table de données, nous avons trouvé que l'utilisateur jack a role1 et role2, donc la méthode hasRole renvoie false, nous avons donc ouvert le code java, shiro.ini et la base de données MySQL. Faites-vous plaisir.
Au moment où j'écris ceci, je suis curieux de savoir pourquoi un fichier de configuration jdbcrealm.ini plus quelques lignes de code peuvent trouver les informations d'un certain utilisateur sans écrire d'instructions SQL du tout. Ici, vous devez vérifier org.apache.shiro.realm.jdbc.JdbcRealm
le code source, le code source est le suivant :
Après avoir visualisé le code source, j'ai soudainement réalisé que l'instruction de requête avait été définie dans la classe JdbcRealm ! ! ! ! !
Attendez, j'ai aussi découvert que les tables de données sont des tables users, user_roles, roles_permissions, c'est pourquoi, quand on fait faire des projets à d'autres personnes, toutes les tables qu'on voit portent le même nom, comme si elles avaient été convenues ! ! ! ! ! ! ! Ensuite, lorsque je définirai la table de données ultérieurement, je devrai également définir le nom de la table et les champs de la table de cette manière.
Méthode 2 : à l'aide du pool de connexions à la base de données, shiro simule la connexion de l'utilisateur pour interroger les informations d'autorisation de la base de données
package com.lzh;
/**
* @Author:kaiyang.cui
* @Package:com.lzh
* @Project:lzh_shiro
* @name:QuickStartTest
* @Date:2023/3/27 下午2:05
* @Filename:QuickStartTest
* @Description:方式二使用数据库连接池
* @Version:1.0
*/
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
public class QuickStartTest5 {
@Test
public void testAuthentication() {
DefaultSecurityManager securityManager = new DefaultSecurityManager();
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql://39.97.253.89:3306/class_shiro?characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false");
ds.setUsername("你的账号");
ds.setPassword("你的密码");
JdbcRealm jdbcRealm = new JdbcRealm();
jdbcRealm.setPermissionsLookupEnabled(true);
jdbcRealm.setDataSource(ds);
securityManager.setRealm(jdbcRealm);
// 将securityManager设置到当前运行环境中
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
// 模拟用户输入的用户名和密码
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("jack", "123");
subject.login(usernamePasswordToken);
// 获取验证结果 isAuthenticated() 是否授权,结果是boolen
System.out.println("认证结果:" + subject.isAuthenticated());
// 是否有对应的角色
System.out.println("是否有user角色:" + subject.hasRole("admin"));
// 是否有对应的权限
System.out.println("是否有对应的权限:" + subject.isPermitted("video:delete"));
}
}
复制代码
认证结果:true
是否有user角色:false
是否有对应的权限:false
复制代码
Résumer:
Dans IniRealm, nous mettons les rôles et les autorisations des informations de l'utilisateur dans le fichier shiro.ini. En coopérant avec le code Java, nous avons obtenu les informations, les rôles et les autorisations de la connexion utilisateur simulée, mais qui stockera les informations de l'utilisateur dans le fichier *.ini ? ? ? ? Les utilisateurs sont stockés dans la base de données.
Ensuite, nous avons appris la classe JdbcRealm, qui revient à apprendre JavaJDBC au début. Nous utiliserons du code java pour parcourir la base de données MySQL, mais cette opération n'est toujours pas très pratique. Nous utilisons shiro dans l'entreprise pour réaliser la personnalisation des informations d'autorisation des utilisateurs en personnalisant Realm. Shiro est un article en série, bienvenue pour faire attention à mes pépites.