shiro实战系列(九)之Web

简介: 一、Configuration(配置)将 Shiro 集成到任何 Web 应用程序的最简单的方法是在 web.xml 中配置 ContextListener 和 Filter,理解如何读取 Shiro 的 INI 配置文件。

 

一、Configuration(配置)

将 Shiro 集成到任何 Web 应用程序的最简单的方法是在 web.xml 中配置 ContextListener 和 Filter,理解如何读取 Shiro 的 INI 配置文件。大部分的 INI 配置格式定义在 Configuration 页的 INI Sections 节,但我在这里我们将介绍一些额外 的 Web 的特定部分。

 

Shiro 1.2 and later 在 Shiro 1.2 及以后版本,标准的 Web 应用程序通过添加下面的 XML 块到 web.xml 来初始化 Shiro

这假设一个 Shiro INI 配置文件在以下两个位置任意一个,并使用最先发现的那个:

 1. /WEB-INF/shiro.ini

 2. 在 classpath 根目录下 shiro.ini 文件  

 

下面是上述配置所做的事情: 

(1)    EnvironmentLoaderListener 初始化一个 Shiro WebEnvironment 实例(其中包含 Shiro 需要的一切操作,包括 SecurityManager),使得它在 ServletContext 中能够被访问。如果你需要在任何时候获得 WebEnvironment 实 例,你可以调用 WebUtils.getRequiredWebEnvironment(ServletContext)。 

(2)     ShiroFilter 将使用此 WebEnvironment 对任何过滤的请求执行所有必要的安全操作。 

(3)    最后,filter-mapping 的定义确保了所有的请求被 ShiroFilter 过滤,建议大多数 Web 应用程序使用以确保任何 请求是安全的。 

 

二、ShiroFilter filter-mapping              

它通常是可取的在任何其他 filter-mapping 声明之前定义 ShiroFilter filter-mapping,以确保 Shiro 也能在那些过滤器 下工作的很好。  

 

三、 Custom WebEnvironment Class

 默认情况下,EnvironmentLoaderListener 将创建一个 IniWebEnvironment 实例,呈现 Shiro 基于 INI 文件的配置。如 果你愿意,你可以在 web.xml 中指定一个自定义的 ServletContext context-param:

这允许你自定义一个如何解析和代表 WebEnvironment 实例的配置格式。你可以为自定义的行为对现有的 IniWebEnvironment 创建子类,或完全支持不同的配置格式。例如,如果有人想在 XML 中配置 Shiro 而不是在 INI 中, 他们可以创建一个基于 XML 的实现,如 com.foo.bar.shiro.XmlWebEnviroment

四、Custom Configuration Locations

IniWebEnvironment 将会去读取和加载 INI 配置文件。默认情况下,这个类会自动地在下面两个位置寻找 Shiro.ini 配 置(按顺序)。 1. /WEB-INF/shiro.ini 2. classpath:shiro.ini 它将使用最先发现的那个。   然而,如果你想把你的配置放在另一位置,你可以在 web.xml 中用 contex-param 指定该位置。

默认情况下,在 ServletContext.getResource 方法定义的规则下,param-value 是可以被解析的。例如, /WEB-INF/some/path/shiro.ini。  

但你也可以指定具体的文件系统,如 classpath 或 URL 位置,通过使用 Shiro 支持的合适的资源前缀,例如: 

  (1)file://home/foobar/myapp/shiro.ini 

(2)classpath:com/foo/bar/shiro.ini  (3)url:http://confighost.mycompany.com/myapp/shiro.ini

 

 

 

Shiro 1.1 and earlier

 

在 Web 应用程序中使用 Shiro 1.1 或更早版本的最简单的方法是定义 IniShiroFilter 并指定一个 filter-mapping:

该定义期望你的 INI 配置是一个在 classpath 根目录的 Shiro.ini 文件(如:classpath:shiro.ini)。

 

Custom Path

如果你不想将你的 INI 配置放在/WEB-INF/shiro.ini 或 classpath:shiro.ini,你可以指定一个自定义的资源位置,如果必 要的话。添加一个 configPath 的 init-param,并指定资源位置。

不合格的(不完整的组合或'non-prefixed')configPath 值被假定为 ServletContext 的资源路径,通过 ServletContext.getResource 方法所定义的规则来解析。

通过分别地使用 classpath:,url:,或 file:前缀来指明 classpath,url,或 filesystem 位置,你也可以指定其他非 ServletContext 资源位置。例如:

 

Inline Config

 最后,也可以将你的 INI 配置嵌入到 web.xml 中而不使用一个独立的 INI 文件。你可以通过使用 init-param 做到这点, 而不是 configPath:

内嵌配置对于小型的或简单的应用程序通常是很好用的,但是由于以下原因一般把它具体化到一个专用的 Shiro.ini 文件中:

  (1)你可能编辑了许多安全配置,不希望为 web.xml 添加版本控制。 

(2)你可能想从余下的 web.xml 配置中分离安全配置。 

(3)你的安全配置可能变得很大,你想保持 web.xml 的苗条并易于阅读。 

(4)你有个负责的编译系统,相同的 shiro 配置可能需要在多个地方被引用。 

 这取决于你——使用什么使你的项目更有意义。

 

Subject Inspection

[urls]项允许你做一些在我们已经见过的任何 Web 框架都不存在的东西:在你的应用程序中定义自适应过滤器链来 匹配 URL 路径!

 

  这将更为灵活,功能更为强大,比你通常在 web.xml 中定义的过滤器链更为简洁:即使你从未使用任何 Shiro 提供 的其他功能并仅仅使用了这个,但它即使是单独使用也是值得的。 

 

[urls] 在 urls 项的每一行格式如下:

URL_Ant_Path_Expression = Path_Specific_Filter_Chain  

 

接下来我们将讨论这些行的具体含义。

 

URL Path Expressions  

 

等号左边是一个与 Web 应用程序上下文根目录相关的 Ant 风格的路径表达式。   例如,假设你有如下的[urls]行:

此行表明,“任何对我应用程序的/accout 或任何它的子路径(/account/foo, account/bar/baz,等等)的请求都将触 发'ssl, authc'过滤器链”。我们将在下面讨论过滤器链。   请注意,所有的路径表达式都是相对于你的应用程序的上下文根目录而言的。这意味着如果某一天你在某个位置部 署了你的应用程序,如 www.somehost.com/myapp ,然后又将它部署到了 www.anotherhost.com (没有'myapp'子 目录),这样的匹配模式仍将继续工作。所有的路径都是相对于 HttpServletRequest.getContextPath()的值来的。

 

Filter Chain Definitions

 等号右边是逗号隔开的过滤器列表,用来执行匹配该路径的请求。它必须符合以下格式: filter1[optional_config1], filter2[optional_config2], ..., filterN[optional_configN]   并且: 

(1)    filterN 是一个定义在[main]项中的 filter bean 的名字。 

(2)     [optional_configN]是一个可选的括号内的对特定的路径,特定的过滤器有特定含义的字符串(每个过滤器,每 个路径的具体配置!)。若果该过滤器对该 URL 路径并不需要特定的配置,你可以忽略括号,于是 filteNr[] 就变成了 filterN.

 

因为过滤器标志符定义了链(又名列表),所以请记住顺序问题!请按顺序定义好你的逗号分隔的列表,这样请求 就能够流通这个链。  

 

最后,每个过滤器按照它期望的方式自由的处理请求,即使不具备必要的条件(例如,执行一个重定向,响应一个 HTTP 错误代码,直接渲染等)。否则,它有可能允许该请求继续通过这个过滤器链到达最终的视图。

Available Filters

在过滤器链中能够使用的过滤器“池”被定义在[main]项。在[main]项中指派给它们的名字就是在过滤器链定义中使 用的名字。例如:

 

Default Filters

当运行一个 Web 应用程序时,Shiro 将会创建一些有用的默认 Filter 实例,并自动地在[main]项中将它们置为可用。 你可以在 main 中配置它们,当作在你的链的定义中你是否有任何其他的 bean 和 reference。例如:

自动地可用的默认的 Filter 实例是被 DefaultFilter 枚举定义的,枚举的名称字段是可供配置的名称。它们是:

由于这是与任何过滤器链定义机制(web.xml,Shiro 的 INI 等)相关的例子,你通过在过滤器链中包含它来启用过 滤器,通过在过滤器链中移除它来禁用过滤器。  

 

但在 Shiro 1.2 中新增的一个新功能是不通过从过滤器链中移除过滤器来启用或禁用过滤器。如果启用(默认设置), 那么请求将如预期一样过滤。如果禁用,那么该过滤器将允许请求立即通过到 FilterChain 的下一个元素。你可以基 于一般配置属性触发过滤器的启用状态,或者你甚至可以在每一个请求的基础上触发。   这是一个强大的概念,因为基于特定需求启用或禁用一个过滤器比更改静态过滤器链(这是永久的且固定的)定义 更为方便。 

 Shiro通过它的OncePerRequestFilter抽象父类来完成这点。所有Shiro的不受规范限制的过滤器实现子类实现这一点, 因此不需要从过滤器链移除它们实现启用或禁用。如果你需要实现此功能,你可以为自己的过滤器实现继承这个类 的子类。

 

 

  SHIRO-224 将有望为任何过滤器使用这项功能,不仅仅只是那些 OncePerRequestFilter 的子类。如果这对你很重要, 请为这个 issue 投票。

 

 

General Enabling/Disabling

OncePerRequestFilter(及其所有子类)支持 Enabling/Disabling 所有请求及 per-request 基础。   一般为所有的请求启用或禁用一个过滤器是通过设置其 enabled 属性为 true 或 false。默认的设置是 true 由于大多 数过滤器本质上是需要执行的,如果他们被配置在一个过滤器链中。   例如,在 shiro.ini 中:

该例表明,许多潜在的 URL 路径都需要请求必须通过 SSL 连接保证。在开发中设置 SSL 是令人沮丧且费时的。在开 发时,你可以禁用 ssl 过滤器。当部署产品时,你可以启用它通过一个配置属性——这比手动更改所有 URL 路径或 维护两个 Shiro 配置要容易得多。

 

 

Request-specific Enabling/Disabling

 OncePerRequestFilter 实际上决定过滤器启用或禁用是基于它的 isEnabled(request, response)方法。   该方法默认返回 enabled 属性的值,该属性通常是用来 enabling/disabling 上面提及的所有请求。如果你想启用或禁 用一个基于特定标准的请求的过滤器,你可以通过覆盖 OncePerRequestFilter 的 isEnabled(request, response)方法来 执行更多特定的检查。  

 

Path-specific Enabling/Disabling

Shiro 的 PathMatchingFilter(一个 OncePerRequestFilter 的子类)能够对基于被过滤的特定路径的配置作出反应。这 意味着你可以启用或禁用一个过滤器基于路径和特定路径配置,除了传入的 request 和 response。   如果你需要能够对匹配的路径和特定路径配置作出反应来判断一个过滤器是否是启用的或禁用的,而不是通过覆盖 OncePerRequestFilter 的 isEnabled(request, reponse)方法,你应该是覆盖 PathMatchingFilter 的 isEnabled(request, response)方法。  

 

Remember Me Services

Shiro 将执行'rememberMe'服务如果 AuthenticationToken 实现了 org.apache.shiro.authc.RememberMeAuthenticationToken 接口。该接口指定了一个方法:

该例表明,许多潜在的 URL 路径都需要请求必须通过 SSL 连接保证。在开发中设置 SSL 是令人沮丧且费时的。在开 发时,你可以禁用 ssl 过滤器。当部署产品时,你可以启用它通过一个配置属性——这比手动更改所有 URL 路径或 维护两个 Shiro 配置要容易得多。

 

 

Request-specific Enabling/Disabling

 OncePerRequestFilter 实际上决定过滤器启用或禁用是基于它的 isEnabled(request, response)方法。   该方法默认返回 enabled 属性的值,该属性通常是用来 enabling/disabling 上面提及的所有请求。如果你想启用或禁 用一个基于特定标准的请求的过滤器,你可以通过覆盖 OncePerRequestFilter 的 isEnabled(request, response)方法来 执行更多特定的检查。  

 

Path-specific Enabling/Disabling

Shiro 的 PathMatchingFilter(一个 OncePerRequestFilter 的子类)能够对基于被过滤的特定路径的配置作出反应。这 意味着你可以启用或禁用一个过滤器基于路径和特定路径配置,除了传入的 request 和 response。   如果你需要能够对匹配的路径和特定路径配置作出反应来判断一个过滤器是否是启用的或禁用的,而不是通过覆盖 OncePerRequestFilter 的 isEnabled(request, reponse)方法,你应该是覆盖 PathMatchingFilter 的 isEnabled(request, response)方法。  

 

Remember Me Services

Shiro 将执行'rememberMe'服务如果 AuthenticationToken 实现了 org.apache.shiro.authc.RememberMeAuthenticationToken 接口。该接口指定了一个方法:

如果该方法返回 true,Shiro 将会在整个会话中记住终端用户的身份 ID。

Programmatic Support

要有计划性地使用 rememberMe,你可以在一个支持该配置的类上把它的值设为 true。例如,使用标准的 UsernamePasswordToken:

Form-based Login

对于 Web 应用程序而言,authc 过滤器默认是 FormAuthenticationFilter。它支持将'rememberMe'的布尔值作为一个 form/request 参数读取。默认地,它期望该 request 参数被命名为 rememberMe。下面是一个支持这点的 shiro.ini 配 置的例子: 

同时在你的 web form 中有一个名为'rememberMe'的 checkbox。

 

默认地,FormAuthenticationFilter 将会寻找名为 username,password 及 rememberMe 的 request 参数。如果这些不 同于你使用的 form 中的表单域名,你可能想在 FormAuthenticationFilter 上配置这些参数名。例如,在 shiro.ini 中:

Cookie configuration

你可以通过设定{{RememberMeManager}}的各方面的 cookie 属性来配置 rememberMe cookie 是如何工作的。例如, 在 shiro.ini 中:

Custom RememberMeManager

 应该注意到,默认基于 cookie 的 RememberMeManager 实现不符合你的需求,你可以插入任何你喜欢的插件到 securityManager 当中,就像你配置任何其他对象的引用一样:

JSP/GSP Tag Library

 Apache Shiro 提供了一个 Subject-aware JSP/GSP 标签库,它允许你控制你的 JSP,JSTL 或 GSP 页面基于当前 Subject 的状态进行输出。这对于根据身份个性化视图及当前用户所浏览的页面授权状态是相当有用的。  

 

Tag Library Configuration

 标签库描述文件(TLD )被打包在 META-INF/shiro.tld 文件中的 shiro-web.jar 文件中。要使用任何标签,添加下面一行 到你 JSP 页面(或任何你定义的页面指令)的顶部。  

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

  我们使用 shiro 前缀用以表明 shiro 标签库命名空间,当然你可以指定任何你喜欢的名字。   现在我们将讨论每一个标签,并展示它是如何用来渲染页面的。

 The guest tag

guest 标签将显示它包含的内容,仅当当前的 Subject 被认为是'guest'时。'guest'是指没有身份 ID 的任何 Subject。也 就是说,我们并不知道用户是谁,因为他们没有登录并且他们没有在上一次的访问中被记住(RememberMe 服务)。 

 例子:  

guest 标签与 user 标签逻辑相反。

 

The user tag

user 标签将显示它包含的内容,仅当当前的 Subject 被认为是'user'时。'user'在上下文中被定义为一个已知身份 ID 的 Subject,或是成功通过身份验证及通过'RememberMe'服务的。请注意这个标签在语义上与 authenticated 标签是 不同的,authenticated 标签更为严格。

usre 标签与 guest 标签逻辑相反

 

 

The authenticated tag

仅仅只当当前用户在当前会话中成功地通过了身份验证 authenticated 标签才会显示包含的内容。它比'user'标签更 为严格。它在逻辑上与'notAuthenticated'标签相反。   authenticated 标签只有当当前 Subject 在其当前的会话中成功地通过了身份验证才会显示包含的内容。它比 user 标 签更为严格,authenticated 标签通常在敏感的工作流中用来确保身份 ID 是可靠的。  

例子:

authenticated 标签与 notAuthenticated 标签逻辑相反。

 

The notAuthenticated tag

notAuthenticated 标签将会显示它所包含的内容,如果当前 Subject 还没有在其当前会话中成功地通过验证。   

notAuthenticated 标签与 Authenticated 标签逻辑相反。

 

 

The principal tag

principal 标签将会输出 Subject 的主体(标识属性)或主要的属性。 若没有任何标签属性,则标签将使用 principal 的 toString()值来呈现页面。例如(假设 principal 是一个字符串的用户 名): 

Typed principal

principal 标签默认情况下,假定该 principal 输出的是 subject.getPrincipal()的值。但若你想输出一个不是主要 principal 的值,而是属于另一个 Subject 的 principal collection,你可以通过类型来获取该 principal 并输出该值。   例如,输出 Subject 的用户 ID(并不是 username),假设该 ID 属于 principal collection:

 

Principal property

但如果该 principal(是默认主要的 principal 或是上面的'typed' principal)是一个复杂的对象而不是一个简单的字符串, 而且你希望引用该 principal 上的一个属性该怎么办呢?你可以使用 property 属性来来表示 property 的名称来理解 (必须通过 JavaBeans 兼容的 getter 方法访问)。例如(假主要的 principal 是一个 User 对象) 

The hasRole tag

 hasRole 标签将会显示它所包含的内容,仅当当前 Subject 被分配了具体的角色。

The lacksRole tag

 lacksRole 标签将会显示它所包含的内容,仅当当前 Subject 未被分配具体的角色。

The hasAnyRole tag

 hasAnyRole 标签将会显示它所包含的内容,如果当前的 Subject 被分配了任意一个来自于逗号分隔的角色名列表中 的具体角色。

The hasPermission tag

 hasPermission 标签将会显示它所包含的内容,仅当当前 Subject“拥有”(蕴含)特定的权限。也就是说,用户具 有特定的能力。     

The lacksPermission tag

lacksPermission 标签将会显示它所包含的内容,仅当当前 Subject 没有拥有(蕴含)特定的权限。也就是说,用户没 有特定的能力。

 

目录
相关文章
|
2月前
|
存储 前端开发 Java
【JAVA】Java 项目实战之 Java Web 在线商城项目开发实战指南
本文介绍基于Java Web的在线商城技术方案与实现,涵盖三层架构设计、MySQL数据库建模及核心功能开发。通过Spring MVC + MyBatis + Thymeleaf实现商品展示、购物车等模块,提供完整代码示例,助力掌握Java Web项目实战技能。(238字)
326 0
|
2月前
|
存储 JavaScript 安全
Web渗透-XSS漏洞深入及xss-labs靶场实战
XSS(跨站脚本攻击)是常见的Web安全漏洞,通过在网页中注入恶意脚本,窃取用户信息或执行非法操作。本文介绍其原理、分类(反射型、存储型、DOM型)、测试方法及xss-labs靶场实战案例,帮助理解与防御XSS攻击。
828 1
Web渗透-XSS漏洞深入及xss-labs靶场实战
|
2月前
|
安全 Linux PHP
Web渗透-命令执行漏洞-及常见靶场检测实战
命令执行漏洞(RCE)指应用程序调用系统命令时,用户可控制输入参数,导致恶意命令被拼接执行,从而危害系统安全。常见于PHP的system、exec等函数。攻击者可通过命令连接符在目标系统上执行任意命令,造成数据泄露或服务瘫痪。漏洞成因包括代码层过滤不严、第三方组件缺陷等。可通过参数过滤、最小权限运行等方式防御。本文还介绍了绕过方式、靶场测试及复现过程。
913 0
|
8月前
|
机器学习/深度学习 开发框架 API
Python 高级编程与实战:深入理解 Web 开发与 API 设计
在前几篇文章中,我们探讨了 Python 的基础语法、面向对象编程、函数式编程、元编程、性能优化、调试技巧以及数据科学和机器学习。本文将深入探讨 Python 在 Web 开发和 API 设计中的应用,并通过实战项目帮助你掌握这些技术。
|
11月前
|
弹性计算 Java 数据库
Web应用上云经典架构实战
本课程详细介绍了Web应用上云的经典架构实战,涵盖前期准备、配置ALB、创建服务器组和监听、验证ECS公网能力、环境配置(JDK、Maven、Node、Git)、下载并运行若依框架、操作第二台ECS以及验证高可用性。通过具体步骤和命令,帮助学员快速掌握云上部署的全流程。
287 1
|
11月前
|
安全 应用服务中间件 网络安全
实战经验分享:利用免费SSL证书构建安全可靠的Web应用
本文分享了利用免费SSL证书构建安全Web应用的实战经验,涵盖选择合适的证书颁发机构、申请与获取证书、配置Web服务器、优化安全性及实际案例。帮助开发者提升应用安全性,增强用户信任。
|
机器学习/深度学习 数据采集 Docker
Docker容器化实战:构建并部署一个简单的Web应用
Docker容器化实战:构建并部署一个简单的Web应用
|
开发框架 前端开发 JavaScript
利用Python和Flask构建轻量级Web应用的实战指南
利用Python和Flask构建轻量级Web应用的实战指南
700 2
|
前端开发 API 开发者
Python Web开发者必看!AJAX、Fetch API实战技巧,让前后端交互如丝般顺滑!
在Web开发中,前后端的高效交互是提升用户体验的关键。本文通过一个基于Flask框架的博客系统实战案例,详细介绍了如何使用AJAX和Fetch API实现不刷新页面查看评论的功能。从后端路由设置到前端请求处理,全面展示了这两种技术的应用技巧,帮助Python Web开发者提升项目质量和开发效率。
276 1
|
SQL 负载均衡 安全
安全至上:Web应用防火墙技术深度剖析与实战
【10月更文挑战第29天】在数字化时代,Web应用防火墙(WAF)成为保护Web应用免受攻击的关键技术。本文深入解析WAF的工作原理和核心组件,如Envoy和Coraza,并提供实战指南,涵盖动态加载规则、集成威胁情报、高可用性配置等内容,帮助开发者和安全专家构建更安全的Web环境。
384 1