Apache Shiro est un framework de sécurité (autorisation) Java.
Shiro facilite le développement d'applications suffisamment performantes, qui peuvent être utilisées non seulement dans l'environnement JavaSE, mais également dans l'environnement JavaEE. Shiro peut tout faire : authentification, autorisation, cryptage, gestion de session, intégration Web, mise en cache et bien plus encore.
Authentification : authentification de l'identité, connexion, vérification si l'utilisateur possède l'identité correspondante
Autorisation : autorisation, c'est-à-dire vérification de l'autorité, vérification si un utilisateur authentifié dispose d'une certaine autorisation ; , c'est-à-dire déterminer les opérations qu'un utilisateur peut effectuer, telles que : vérifier si un utilisateur a un certain rôle, ou vérifier finement si un utilisateur a une certaine autorisation sur une certaine ressource
Session Manager : gestion de session, c'est-à-dire ! , utilisateur Après la connexion, c'est la première session. Avant de se déconnecter, toutes ses informations sont dans la session ; la session peut être un environnement JavaSE ordinaire ou un environnement Web ; cryptage du mot de passe Stocké dans la base de données au lieu du texte brut ; Support Web : support Web, qui peut être facilement intégré à l'environnement Web
Mise en cache : par exemple, après la connexion d'un utilisateur, ses informations utilisateur, ses rôles et ses autorisations sont supprimés. Il n'est pas nécessaire de vérifier à chaque fois. Cela peut améliorer l'efficacité.
Concurrence : Shiro prend en charge la vérification simultanée des applications multithread, c'est-à-dire que si vous démarrez un autre thread dans un thread, les autorisations peuvent y être automatiquement propagées.
Test : fournissez des tests. support ;
Exécuter en tant que : permet à un utilisateur de se faire passer pour un autre utilisateur (s'il le permet)
Se souvenir de moi : se souvenir de moi, il s'agit d'une fonction très courante, c'est-à-dire qu'après vous être connecté une fois, vous n'êtes pas obligé de le faire ; connectez-vous la prochaine fois
SecurityManager : Security Manager, c'est-à-dire que toutes les opérations liées à la sécurité interagiront avec le SecurityManager. , et il gère tous les sujets. On peut voir qu'il est le cœur de Shiro, et il est responsable de l'interaction avec les autres composants de Shiro. C'est équivalent au rôle du
DispatcherServlet
Realm de SpringMVC : Shiro obtient des données de sécurité (telles que). comme utilisateurs, rôles, autorisations) de Realm C'est-à-dire que si SecurityManager veut vérifier l'identité de l'utilisateur, il doit obtenir l'utilisateur correspondant de Realm pour comparaison afin de déterminer si l'identité de l'utilisateur est légale, il est également nécessaire d'obtenir ; le rôle correspondant de l'utilisateur et les autorisations de Realm pour vérifier si l'opération de l'utilisateur peut être effectuée. Realm peut être considéré comme une source de données
Security Manager : équivalent au DispatcherServlet dans SpringMVC ; c'est le cœur de Shiro. Toutes les interactions spécifiques sont contrôlées via le Security Manager. Il gère tous les sujets et est responsable de l'authentification, de l'autorisation et de la gestion du cache.
Realm : il peut y avoir un ou plusieurs domaines, qui peuvent être considérés comme une entité sécurisée ; la source de données, c'est-à-dire utilisée pour obtenir des entités de sécurité, peut être implémentée à l'aide de DBC, ou d'une implémentation de mémoire, etc., fournie par l'utilisateur, donc généralement dans les applications, vous devez implémenter votre propre domaine
SessionManager : un composant qui gère la session ; cycle de vie, et Shiro peut non seulement être utilisé dans l'environnement Web, il peut également être utilisé dans l'environnement JavaSE ordinaire
CacheManager : contrôleur de cache pour gérer les caches tels que les utilisateurs, les rôles, les autorisations, etc. car ces données sont fondamentalement rarement accessibles ; , l'accès peut être amélioré après avoir été placé dans le cache Performance ;
Cryptographie : module de cryptographie, Shiro améliore certains composants de cryptage courants pour le cryptage des mots de passe, le décryptage, etc.
2. Démarrage rapide
2 Créez un nouveau projet Maven, supprimez son répertoire src et utilisez-le comme projet parent
3. un nouveau module Maven dans le projet parent
4. Copiez les dépendances POM du cas de démarrage rapide dans les fichiers XML
.<dependencies> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.4.1</version> </dependency> <!-- configure logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.29</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.29</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies>
5. Copiez le fichier log4j.properties sous la ressource dans le cas de démarrage rapide
6 Copiez le fichier shiro.ini
7 Copiez le fichier Quickstart.java
8.
2. Analysez le code
public class Quickstart { private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class); public static void main(String[] args) { //工厂模式,通过shiro.ini配置文件中的信息,生成一个工厂实例 Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); //获取当前的用户对象Subject Subject currentUser = SecurityUtils.getSubject(); //通过当前用户拿到session Session session = currentUser.getSession(); session.setAttribute("someKey", "aValue"); String value = (String) session.getAttribute("someKey"); if (value.equals("aValue")) { log.info("Subject=>session[" + value + "]"); } //判断当前的用户是否被认证 if (!currentUser.isAuthenticated()) { //Token :令牌,没有获取,随机 UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa"); token.setRememberMe(true); //设置记住我 try { currentUser.login(token); //执行了登录操作 } catch (UnknownAccountException uae) { //如果 用户名不存在 log.info("There is no user with username of " + token.getPrincipal()); } catch (IncorrectCredentialsException ice) { //如果 密码不正确 log.info("Password for account " + token.getPrincipal() + " was incorrect!"); } catch (LockedAccountException lae) { //用户被锁定,如密码输出过多,则被锁定 log.info("The account for username " + token.getPrincipal() + " is locked. " + "Please contact your administrator to unlock it."); } //...在此处捕获更多异常 catch (AuthenticationException ae) { //意外情况 ? 错误 ? } } //打印其标识主体(在这种情况下,为用户名) log.info("User [" + currentUser.getPrincipal() + "] logged in successfully."); //测试角色是否存在 if (currentUser.hasRole("schwartz")) { log.info("May the Schwartz be with you!"); } else { log.info("Hello, mere mortal."); } //粗粒度,极限范围小 //测试类型化的极限(不是实例级别) if (currentUser.isPermitted("lightsaber:wield")) { log.info("You may use a lightsaber ring. Use it wisely."); } else { log.info("Sorry, lightsaber rings are for schwartz masters only."); } //细粒度,极限范围广 //实例级别的权限(非常强大) if (currentUser.isPermitted("winnebago:drive:eagle5")) { log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'. " + "Here are the keys - have fun!"); } else { log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!"); } //注销 currentUser.logout(); //退出 System.exit(0); } }
2. et les packages d'intégration Shiro
<!--SpringBoot 和 Shiro 整合包--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.1</version> </dependency>
Shiro
Utilisateur sujet-> ShiroFilterFactoryBean
Données de connexion au domaine3. Écrivez un domaine personnalisé, qui doit hériter de AuthorizingRealm
L'ordre de création des objets en fonctionnement réel : realm -> securityManager -> subject
//自定义的 UserRealm extends AuthorizingRealm public class UserRealm extends AuthorizingRealm { //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //打印一个提示 System.out.println("执行了授权方法"); return null; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //打印一个提示 System.out.println("执行了认证方法"); return null; } }
@Configuration public class ShiroConfig { //ShiroFilterFactoryBean:3 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebsecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebsecurityManager); return bean; } //DefaultWebSecurityManager:2 @Bean(name="securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){ DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager(); //关闭UserRealm securityManager.setRealm(userRealm); return securityManager; } //创建realm 对象,需要自定义类:1 @Bean(name="userRealm") public UserRealm userRealm(){ return new UserRealm(); } }
2. Utilisez
1. Interception de connexion Ajoutez la demande de connexion qui doit être interceptée dans la méthode getShiroFilterFactoryBean@Configuration public class ShiroConfig { //ShiroFilterFactoryBean:3 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebsecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebsecurityManager); //添加shiro的内置过滤器 /* anon : 无需认证,就可以访问 authc : 必须认证了才能访问 user : 必须拥有 “记住我” 功能才能用 perms : 拥有对某个资源的权限才能访问 role : 拥有某个角色权限才能访问 */ filterMap.put("/user/add","authc"); filterMap.put("/user/update","authc"); //拦截 Map<String,String> filterMap=new LinkedHashMap<>(); filterMap.put("/user/*","authc"); bean.setFilterChainDefinitionMap(filterMap); // //设置登录的请求 // bean.setLoginUrl("/toLogin"); return bean; }
2. Authentification de l'utilisateur
1 Écrivez une méthode de connexion dans la couche Contrôleur//登录的方法 @RequestMapping("/login") public String login(String username, String password, Model model) { //获取当前用户 Subject subject = SecurityUtils.getSubject(); //封装用户的登录数据,获得令牌 UsernamePasswordToken token = new UsernamePasswordToken(username, password); //登录 及 异常处理 try { //执行用户登录的方法,如果没有异常就说明OK了 subject.login(token); return "index"; } catch (UnknownAccountException e) { //如果用户名不存在 System.out.println("用户名不存在"); model.addAttribute("msg", "用户名错误"); return "login"; } catch (IncorrectCredentialsException ice) { //如果密码错误 System.out.println("密码错误"); model.addAttribute("msg", "密码错误"); return "login"; } } }
//认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //打印一个提示 System.out.println("执行了认证方法"); // 用户名密码 String name = "root"; String password = "123456"; //通过参数获取登录的控制器中生成的 令牌 UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; //用户名认证 if (!token.getUsername().equals(name)){ // return null UnKnownAccountException return null; } //密码认证, Shiro 自己做,为了避免和密码的接触 //最后返回一个 AuthenticationInfo 接口的实现类,这里选择 SimpleAuthenticationInfo // 三个参数:获取当前用户的认证 ; 密码 ; 认证名 return new SimpleAuthenticationInfo("", password, ""); } }
Entrez le mot de passe correct et vous pourrez vous connecter. avec succès
4. Shiro intègre Mybatis
1. Importer les dépendances<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.19</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.12</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.1</version> </dependency>
spring: datasource: username: root password: 123456 url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC 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: com.huang.pojo mapper-locations: classpath:mybatis/mapper/*.xml
3 Dans application.properties
mybatis.type-aliases-package=com.longdi.pojo mybatis.mapper-locations=classpath:mapper/*.xml
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> <scope>provided</scope> </dependency>
@Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private String pwd; private String perms; }
@Repository @Mapper public interface UserMapper { public User queryUserByName(String name); }
<?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.longdi.mapper.UserMapper"> <select id="queryUserByName" resultType="User" parameterType="String"> select * from mybatis.user where name=#{name} </select> </mapper>
public interface UserService { public User queryUserByName(String name); }
11. Connectez-vous avec succès à la base de données
5. Implémentez la demande d'autorisation
1 Modifiez dans la classe ShiroConfig
2.4. Méthode d'autorisation d'écriture doGetAuthorizationInfo
5. Test d'autorisation de demande réussi6. Shiro intègre Thymeleaf
1 Importer les dépendances
@Service public class UserServiceImpl implements UserService{ @Autowired UserMapper userMapper; @Override public User queryUserByName(String name) { return userMapper.queryUserByName(name); } }
2.
3.index.html 4. Test
5. Mettre la session en authentification 6.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!