【Shiro】Springboot集成Shiro(四)

简介: 【Shiro】Springboot集成Shiro(四)

【2】过滤器链

定义:authentication.properties

#静态资源不过滤

/static/**=anon

#登录链接不过滤

/login/**=anon

#其他链接是需要登录的

/**=authc

注意:这里定义的过滤器是有执行顺序的,从上向下执行

【3】加载原理分析

定义:PropertiesUtil,从classpath中加载authentication.properties

1. package com.itheima.shiro.properties;
2. 
3. import com.itheima.shiro.utils.EmptyUtil;
4. import lombok.extern.log4j.Log4j2;
5. 
6. /**
7.  * @Description 读取Properties的工具类
8.  */
9. @Log4j2
10. public class PropertiesUtil {
11. 
12. public static LinkProperties propertiesShiro = new LinkProperties();
13. 
14. /**
15.      * 读取properties配置文件信息
16.      */
17. static {
18. String sysName = System.getProperty("sys.name");
19. if (EmptyUtil.isNullOrEmpty(sysName)) {
20.             sysName = "application.properties";
21.         } else {
22.             sysName += ".properties";
23.         }
24. try {
25.             propertiesShiro.load(PropertiesUtil.class.getClassLoader()
26.                     .getResourceAsStream("authentication.properties"));
27.         } catch (Exception e) {
28.             log.warn("资源路径中不存在authentication.properties权限文件,忽略读取!");
29.         }
30.     }
31. 
32. /**
33.      * 根据key得到value的值
34.      */
35. public static String getShiroValue(String key) {
36. return propertiesShiro.getProperty(key);
37.     }
38. 
39. }

定义LinkProperties,这个类保证了Properties类的有序

1. package com.itheima.shiro.properties;
2. 
3. import java.io.*;
4. import java.util.ArrayList;
5. import java.util.Enumeration;
6. import java.util.List;
7. import java.util.Properties;
8. 
9. 
10. /**
11.  * @Description 有序Properties类
12.  */
13. 
14. public class LinkProperties extends Properties{
15. 
16.   /** serialVersionUID */
17.   private static final long serialVersionUID = 7573016303908223266L;
18. 
19.   private List<Object> keyList = new ArrayList<Object>();  
20. 
21. /** 
22.      * 默认构造方法 
23.      */
24. public LinkProperties() {  
25. 
26.     }  
27. 
28. /** 
29.      * 从指定路径加载信息到Properties 
30.      * @param path 
31.      */
32. public LinkProperties(String path) {  
33. try {  
34. InputStream is = new FileInputStream(path);  
35. this.load(is);  
36.         } catch (FileNotFoundException e) {  
37.             e.printStackTrace();  
38. throw new RuntimeException("指定文件不存在!");  
39.         } catch (IOException e) {  
40.             e.printStackTrace();  
41.         }  
42.     }  
43. 
44. /** 
45.      * 重写put方法,按照property的存入顺序保存key到keyList,遇到重复的后者将覆盖前者。 
46.      */
47. @Override
48. public synchronized Object put(Object key, Object value) {  
49. this.removeKeyIfExists(key);  
50.         keyList.add(key);  
51. return super.put(key, value);  
52.     }  
53. 
54. 
55. /** 
56.      * 重写remove方法,删除属性时清除keyList中对应的key。 
57.      */
58. @Override
59. public synchronized Object remove(Object key) {  
60. this.removeKeyIfExists(key);  
61. return super.remove(key);  
62.     }  
63. 
64. /** 
65.      * keyList中存在指定的key时则将其删除 
66.      */
67. private void removeKeyIfExists(Object key) {  
68.         keyList.remove(key);  
69.     }  
70. 
71. /** 
72.      * 获取Properties中key的有序集合 
73.      * @return 
74.      */
75. public List<Object> getKeyList() {  
76. return keyList;  
77.     }  
78. 
79. /** 
80.      * 保存Properties到指定文件,默认使用UTF-8编码 
81.      * @param path 指定文件路径 
82.      */
83. public void store(String path) {  
84. this.store(path, "UTF-8");  
85.     }  
86. 
87. /** 
88.      * 保存Properties到指定文件,并指定对应存放编码 
89.      * @param path 指定路径 
90.      * @param charset 文件编码 
91.      */
92. public void store(String path, String charset) {  
93. if (path != null && !"".equals(path)) {  
94. try {  
95. OutputStream os = new FileOutputStream(path);  
96. BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, charset));  
97. this.store(bw, null);  
98.                 bw.close();  
99.             } catch (FileNotFoundException e) {  
100.                 e.printStackTrace();  
101.             } catch (IOException e) {  
102.                 e.printStackTrace();  
103.             }  
104.         } else {  
105. throw new RuntimeException("存储路径不能为空!");  
106.         }  
107.     }  
108. 
109. /** 
110.      * 重写keys方法,返回根据keyList适配的Enumeration,且保持HashTable keys()方法的原有语义, 
111.      * 每次都调用返回一个新的Enumeration对象,且和之前的不产生冲突 
112.      */
113. @Override
114. public synchronized Enumeration<Object> keys() {  
115. return new EnumerationAdapter<Object>(keyList);  
116.     }  
117. 
118. /** 
119.      * List到Enumeration的适配器 
120.      */
121. private class EnumerationAdapter<T> implements Enumeration<T> {  
122. private int index = 0;  
123. private final List<T> list;  
124. private final boolean isEmpty;  
125. 
126. public EnumerationAdapter(List<T> list) {  
127. this.list = list;  
128. this.isEmpty = list.isEmpty();  
129.         }  
130. 
131. public boolean hasMoreElements() {  
132. //isEmpty的引入是为了更贴近HashTable原有的语义,在HashTable中添加元素前调用其keys()方法获得一个Enumeration的引用,  
133. //之后往HashTable中添加数据后,调用之前获取到的Enumeration的hasMoreElements()将返回false,但如果此时重新获取一个  
134. //Enumeration的引用,则新Enumeration的hasMoreElements()将返回true,而且之后对HashTable数据的增、删、改都是可以在  
135. //nextElement中获取到的。  
136. return !isEmpty && index < list.size();  
137.         }  
138. 
139. public T nextElement() {  
140. if (this.hasMoreElements()) {  
141. return list.get(index++);  
142.             }  
143. return null;  
144.         }  
145. 
146.     }  
147. }

查看shirocConfig

 

加载完整之后交于ShiroFilterFactoryBean使用setFilterChainDefinitionMap使得过滤生效

【4】自定义过滤器

上面我们使用了shiro的默认过滤器,但是由于业务需求,咱们可能要定义自己的过滤器,那么咱们定义呢?

这里我们先查看RolesAuthorizationFilter

 

分析:改源码表示,例如:/admin/order= roles["admin, root"] ,只有当放问该接口同时具备admin和root两种角色时,才可以被访问。

【5】自定义过滤器使用

【5.1】需求

1、实现只要有其中一个角色,则可访问对应路径

【5.2】RolesOrAuthorizationFilter

新建filter层,新建类RolesOrAuthorizationFilter

1. package com.itheima.shiro.filter;
2. 
3. import org.apache.shiro.subject.Subject;
4. import org.apache.shiro.util.CollectionUtils;
5. import org.apache.shiro.web.filter.authz.AuthorizationFilter;
6. 
7. import javax.servlet.ServletRequest;
8. import javax.servlet.ServletResponse;
9. import java.io.IOException;
10. import java.util.Set;
11. 
12. /**
13.  * @Description:角色或关系
14.  */
15. public class RolesOrAuthorizationFilter extends AuthorizationFilter {
16. 
17. //TODO - complete JavaDoc
18. 
19. @SuppressWarnings({"unchecked"})
20. public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
21. 
22. Subject subject = getSubject(request, response);
23.         String[] rolesArray = (String[]) mappedValue;
24. 
25. if (rolesArray == null || rolesArray.length == 0) {
26. //no roles specified, so nothing to check - allow access.
27. return true;
28.         }
29. 
30.         Set<String> roles = CollectionUtils.asSet(rolesArray);
31. //循环roles判断只要有角色则返回true
32. for (String role : roles) {
33. if(subject.hasRole(role)){
34. return true;
35.             }
36.         }
37. return false;
38.     }
39. 
40. }
【5.3】编辑ShiroConfig

在ShiroConfig类中添加如下内容

1. /**
2.      * @Description 自定义过滤器定义
3.      */
4. private Map<String, Filter> filters() {
5.         Map<String, Filter> map = new HashMap<String, Filter>();
6.         map.put("role-or", new RolesOrAuthorizationFilter());
7. return map;
8.     }
9. 
10. /**
11.      * @Description Shiro过滤器
12.      */
13. @Bean("shiroFilter")
14. public ShiroFilterFactoryBean shiroFilterFactoryBean(){
15. ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
16.         shiroFilter.setSecurityManager(defaultWebSecurityManager());
17. //使自定义过滤器生效
18.         shiroFilter.setFilters(filters());
19.         shiroFilter.setFilterChainDefinitionMap(filterChainDefinition());
20.         shiroFilter.setLoginUrl("/login");
21.         shiroFilter.setUnauthorizedUrl("/login");
22. return shiroFilter;
23.     }

【2.2.3】编辑authentication.properties

#静态资源不过滤

/static/**=anon

#登录链接不过滤

/login/**=anon

#访问/resource/**需要有admin的角色

/resource/**=role-or[admin]

#其他链接是需要登录的

/**=authc

7、注解方式鉴权

【1】注解介绍

以下为常用注解

注解 说明
@RequiresAuthentication 表明当前用户需是经过认证的用户
@ RequiresGuest 表明该用户需为”guest”用户
@RequiresPermissions 当前用户需拥有指定权限
@RequiresRoles 当前用户需拥有指定角色
@ RequiresUser 当前用户需为已认证用户或已记住用户

例如RoleAction类中我们添加

1. /**
2.   *@Description: 跳转到角色的初始化页面
3.   */
4.  @RequiresRoles(value ={"SuperAdmin","dev"},logical = Logical.OR)
5.  @RequestMapping(value = "listInitialize")
6.  public ModelAndView listInitialize(){
7.    return  new ModelAndView("/role/role-listInitialize");
8.  }

【2】注解原理分析

【2.1】装载过程

【2.2】调用过程

相关文章
|
2月前
|
Java Maven Docker
gitlab-ci 集成 k3s 部署spring boot 应用
gitlab-ci 集成 k3s 部署spring boot 应用
|
3月前
|
安全 Java Apache
SpringBoot+Shiro(一)
SpringBoot+Shiro(一)
|
22天前
|
XML Java 数据库连接
SpringBoot集成Flowable:打造强大的工作流管理系统
在企业级应用开发中,工作流管理是一个核心组件,它能够帮助我们定义、执行和管理业务流程。Flowable是一个开源的工作流和业务流程管理(BPM)平台,它提供了强大的工作流引擎和建模工具。结合SpringBoot,我们可以快速构建一个高效、灵活的工作流管理系统。本文将探讨如何将Flowable集成到SpringBoot应用中,并展示其强大的功能。
72 1
|
2月前
|
安全 Java 数据库
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
这篇文章是关于Apache Shiro权限管理框架的详细学习指南,涵盖了Shiro的基本概念、认证与授权流程,并通过Spring Boot测试模块演示了Shiro在单应用环境下的使用,包括与IniRealm、JdbcRealm的集成以及自定义Realm的实现。
46 3
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
|
1月前
|
JSON Java API
springboot集成ElasticSearch使用completion实现补全功能
springboot集成ElasticSearch使用completion实现补全功能
36 1
|
2月前
|
Java API Apache
Springboot+shiro,完整教程,带你学会shiro
这篇文章提供了一个完整的Apache Shiro与Spring Boot结合使用的教程,包括Shiro的配置、使用以及在非Web和Web环境中进行身份验证和授权的示例。
72 2
Springboot+shiro,完整教程,带你学会shiro
|
2月前
|
前端开发 Java Apache
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
本文详细讲解了如何整合Apache Shiro与Spring Boot项目,包括数据库准备、项目配置、实体类、Mapper、Service、Controller的创建和配置,以及Shiro的配置和使用。
373 1
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
|
22天前
|
XML 存储 Java
SpringBoot集成Flowable:构建强大的工作流引擎
在企业级应用开发中,工作流管理是核心功能之一。Flowable是一个开源的工作流引擎,它提供了BPMN 2.0规范的实现,并且与SpringBoot框架完美集成。本文将探讨如何使用SpringBoot和Flowable构建一个强大的工作流引擎,并分享一些实践技巧。
59 0
|
2月前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
115 1
|
2月前
|
NoSQL Java Redis
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。
31 0
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。

热门文章

最新文章