Apache Shiro与Web整合

配置

将Shiro集成到任何Web应用程序的最简单方法就是是在web.xml中配置Servlet ContextListener和Filter,它们了解如何读取Shiro的INI配置。大部分INI配置格式已经在Shiro中的配置详解中提到,所以我们将在此处介绍一些特定于Web的其他部分。

web.xml

Shiro 1.2及以后

在Shiro 1.2及更高版本中,标准Web应用程序通过将添加到以下内容到XML块中来初始化Shiro:

<listener>
    <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>

...

<filter>
    <filter-name>ShiroFilter</filter-name>
    <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>ShiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

上面写法是基于Shiro的INI配置文件出现在以下两种位置:

  1. /WEB-INF/shiro.ini
  2. shiro.ini 文件位于classpath的根目录。
    以下是上面的配置详解:
  • EnvironmentLoaderListener初始化Shiro的WebEnvironment实例(包含一切Shiro操作所需要的东西,其中包括SecurityManager),并使其在ServletContext中可被访问。如果您需要获取此WebEnvironment实例,可以通过WebUtils.getRequiredWebEnvironment(servletContext)方法调用。

  • ShiroFilter将使用这个WebEnvironment来执行所有必要的安全操作来过滤请求。

  • 最后,该filter-mapping定义确保所有请求都被ShiroFilter过滤。

自定义WebEnvironment类

默认情况下,EnvironmentLoaderListener将创建一个IniWebEnvironment实例,该实例来自于Shiro的INI的配置。您也可以在web.xmlServletContext context-param中自定义一个WebEnvironment实例:

<context-param>
    <param-name>shiroEnvironmentClass</param-name>
    <param-value>com.foo.bar.shiro.MyWebEnvironment</param-value>
</context-param>

这允许您自定义如何解析配置格式并将其表示为WebEnvironment实例。您可以基于现有的IniWebEnvironment实现创建一个子类,或者完全支持不同的配置格式。例如,如果有人想用XML而不是INI配置Shiro,他们可以创建一个基于XML的实现,例如com.foo.bar.shiro.XmlWebEnvironment

自定义配置位置

IniWebEnvironment会在以下两个位置中读取并加载INI配置文件:

  1. /WEB-INF/shiro.ini
  2. classpath:shiro.ini

谁先背发现则会使用谁。然而,如果您想自定义INI文件的位置,可以在web.xml中的context-param中定义:

<context-param>
    <param-name>shiroConfigLocations</param-name>
    <param-value>YOUR_RESOURCE_LOCATION_HERE</param-value>
</context-param>

默认情况下,param-value预期可以通过ServletContext.getResource方法定义的规则进行解析。例如,/WEB-INF/some/path/shiro.ini
但您也可以使用Shiro的ResourceUtils类去通过检测适当的资源前缀来指定特定的文件系统,类路径或URL位置,例如:

Shiro 1.1及更早版本

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

<filter>
    <filter-name>ShiroFilter</filter-name>
    <filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class>
</filter>

...

<!-- Make sure any request you want accessible to Shiro is filtered. /* catches all -->
<!-- requests.  Usually this filter mapping is defined first (before all others) to -->
<!-- ensure that Shiro works in subsequent filters in the filter chain:             -->
<filter-mapping>
    <filter-name>ShiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

此定义要求您的INI配置位于类路径根目录下的shiro.ini文件中(例如classpath:shiro.ini)。

自定义路径

如果你不想把你的INI配置放在/WEB-INF/shiro.ini或者classpath:shiro.ini中,你可以自定义资源的位置并根据需要指定。添加configPath init-param并指定资源位置:

<filter>
    <filter-name>ShiroFilter</filter-name>
    <filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class>
    <init-param>
        <param-name>configPath</param-name>
        <param-value>/WEB-INF/anotherFile.ini</param-value>
    </init-param>
</filter>

...

Shiro 1.2及更高版本中提供了ServletContext资源路径。在1.1和更早的版本中,所有configPath定义必须指定classpath:,file:或url:前缀:

...
<init-param>
    <param-name>configPath</param-name>
    <param-value>url:http://configHost/myApp/shiro.ini</param-value>
</init-param>
...
内联配置

最后,还可以在不使用INI文件的情况下将您的INI配置嵌入到web.xml中。您可以使用config init-param而不是configPath

<filter>
    <filter-name>ShiroFilter</filter-name>
    <filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class>
    <init-param><param-name>config</param-name><param-value>

    # INI Config Here

    </param-value></init-param>
</filter>
...

内联配置通常适用于小型或简单的应用程序,但通常更方便的是将其外部化到专用的shiro.ini文件中,原因如下:

  • 您可能希望将安全配置与web.xml配置部分分开
  • 您的安全配置可能会变得很大,并且您希望将web.xml保持精简并且更易于阅读
  • 您有一个复杂的构建系统,可能需要在多个位置引用相同的shiro配置

Web INI配置

除了标准[main][users][roles]在配置章节中已经说明,你还可以在shiro.ini文件中指定一个特定的网络[urls]部分:

# [main], [users] and [roles] above here
...
[urls]
...

该[urls]部分允许您执行我们已经看到的Web框架中不存在的内容:为应用程序中的任何URL路径匹配定义的过滤器链的能力!

[urls]
URL路径表达式

该部分中每一行的格式urls如下:

_URL_Ant_Path_Expression_ = _Path_Specific_Filter_Chain_

例如:

...
[urls]

/index.html = anon
/user/create = anon
/user/** = authc
/admin/** = authc, roles[administrator]
/rest/** = authc, rest
/remoting/rpc/** = authc, perms["remote:invoke"]

接下来,我们详细介绍这些行的含义。
相对于等号(=)左侧的标记是Web应用程序的上下文根的Ant风格的路径表达式。
例如,假设您有以下[urls]行:

/account/** = ssl, authc

此行指出:访问我的应用程序的请求/account或任何的它的子路径(/account/foo,/account/bar/baz等)都将触发‘SSL,authc’过滤器链”。我们将在下面介绍过滤器链。

请注意,所有路径表达式都与应用程序的上下文根无关。

过滤链定义

等号(=)右侧的标记是逗号分隔的过滤器列表,用于匹配该路径的请求。它必须符合以下格式:

filter1[optional_config1], filter2[optional_config2], ..., filterN[optional_configN]

其中:

  • filterN是[main]节中定义的过滤器bean的名称
  • [optional_configN]括号中是一个可选的的字符串,对于该特定路径的特定过滤器具有意义。如果过滤器不需要该URL路径的特定配置,您可以丢弃括号,filterN[]只需变为filterN
    并且因为过滤器令牌定义了链(也就是列表),所以请记住顺序很重要!请求流经过过滤器链的顺序会遵循逗号分隔的列表的顺序。

最后,如果不满足其必要条件,每个过滤器都可以自由地处理响应(例如,执行重定向,使用HTTP错误代码进行响应,直接呈现等)。否则,允许请求通过过滤器链并到达最终目标视图。

可用过滤器

可用于过滤器链定义的过滤器“池”在本[main]节中定义。在[main]部分中分配给它们的名称是在过滤器链定义中使用的名称。例如:
[main]

myFilter = com.company.web.some.FilterImplementation
myFilter.property1 = value1

[urls]

/some/path/** = myFilter

默认过滤器

运行Web应用程序时,Shiro默认将创建一些有用的Filter实例,并自动在[main]部分中使用它们。您可以像配置main中的任何其他bean一样配置它们,并在链定义中引用它们。例如:

[main]
...
# Notice how we didn't define the class for the FormAuthenticationFilter ('authc') - it is instantiated and available already:
authc.loginUrl = /login.jsp
...

[urls]
...
# make sure the end-user is authenticated.  If not, redirect to the 'authc.loginUrl' above,
# and after successful authentication, redirect them back to the original account page they
# were trying to view:
/account/** = authc
...

自动可用的默认过滤器实例由DefaultFilter枚举定义,枚举的name字段是可用于配置的名称。他们是:

过滤器名称
anonorg.apache.shiro.web.filter.authc.AnonymousFilter
authcorg.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasicorg.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
logoutorg.apache.shiro.web.filter.authc.LogoutFilter
noSessionCreationorg.apache.shiro.web.filter.session.NoSessionCreationFilter
permsorg.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
portorg.apache.shiro.web.filter.authz.PortFilter
restorg.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
rolesorg.apache.shiro.web.filter.authz.RolesAuthorizationFilter
sslorg.apache.shiro.web.filter.authz.SslFilter
userorg.apache.shiro.web.filter.authc.UserFilter

会话管理

Servlet容器会话

在Web环境中,Shiro的默认会话管理器SessionManager实现是ServletContainerSessionManager。这个非常简单的实现将所有会话管理职责(包括servlet容器支持的会话集群)委托给运行时Servlet容器。它本质上是Shiro的servlet容器的会话API的桥梁。

使用此默认值的好处是,使用现有servlet容器会话配置(超时,任何特定于容器的群集机制等)的应用程序将按预期工作。

这个默认值的缺点是你被绑定到servlet容器的特定会话行为。例如,如果要集群会话,但是在生产中使用Jetty进行测试和使用Tomcat,则特定于容器的配置(或代码)将不可移植。

Servlet容器会话超时

如果使用默认的servlet容器支持,则在Web应用程序的web.xml文件中按预期配置会话超时。例如:

<session-config>
  <!-- web.xml expects the session timeout in minutes: -->
  <session-timeout>30</session-timeout>
</session-config>

原生会话

如果您希望会话配置和集群的设置可以跨servlet容器移植(例如测试中的Jetty,但生产中是Tomcat或JBoss),或者您希望控制特定的会话/群集功能,则可以启用Shiro的本机会话管理。

这里的“Native”一词意味着Shiro可以在自己的企业会话管理中实现用于支持所有SubjectHttpServletRequest的会话并完全绕过servlet容器。但请放心–Shiro直接实现了Servlet规范的相关部分,因此任何现有的Web / http相关代码都能按预期工作,并且永远不需要“知道”Shiro在透明地管理会话。

DefaultWebSessionManager

要为Web应用程序启用本机会话管理,您需要配置一个支持本机Web的会话管理器来覆盖默认的基于servlet容器的会话管理器。您可以通过配置DefaultWebSessionManagerShiro的实例来实现SecurityManager。例如,在shiro.ini:

[main]
...
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
# configure properties (like session timeout) here if desired

# Use the configured native session manager:
securityManager.sessionManager = $sessionManager

声明后,您可以配置DefaultWebSessionManager实例来使用本地会话选项配置,如会话超时和集群配置等。

本机会话超时

配置DefaultWebSessionManager实例后,会话超时的配置如上文容器超市中显示的一样。

会话Cookie

DefaultWebSessionManager中支持两个特定的网络配置属性:

  • sessionIdCookieEnabled (布尔值)
  • sessionIdCookie,一个Cookie实例。
会话Cookie配置

DefaultWebSessionManagersessionIdCookie默认实例是 SimpleCookie。这个简单的实现允许您希望在http Cookie上配置的所有相关属性的JavaBeans样式属性配置。

例如,您可以设置Cookie域:

[main]
...
securityManager.sessionManager.sessionIdCookie.domain = foo.com

cookie的默认名称JSESSIONID与servlet规范一致。此外,Shiro的cookie支持HttpOnly属性,可以保证额外的安全性。

禁用会话Cookie

如果您不想使用会话cookie,可以通过将该sessionIdCookieEnabled属性配置为false 来禁用它们。例如:

[main]
...
securityManager.sessionManager.sessionIdCookieEnabled = false

记住我的服务

如果AuthenticationToken实现org.apache.shiro.authc.RememberMeAuthenticationToken接口(经常使用的UsernamePasswordToken已经实现了RememberMeAuthenticationToken接口并支持rememberMe登录。),Shiro将执行’rememberMe'服务。此接口指定一个方法:

boolean isRememberMe();

如果此方法返回true,Shiro将记住最终用户在会话中的身份。

代码支持

要以编程方式使用rememberMe,可以将支持此配置的类的值设置为true。例如,使用标准UsernamePasswordToken

UsernamePasswordToken token = new UsernamePasswordToken(username, password);

token.setRememberMe(true);

SecurityUtils.getSubject().login(token);
...

基于表单的登录

对于Web应用程序,默认情况下过滤器为FormAuthenticationFilter。这支持读取表单/请求的参数作为“rememberMe”的布尔值。默认情况下,它期望请求参数的命名为rememberMe

[main]
authc.loginUrl = /login.jsp

[urls]

# your login form page here:
login.jsp = authc

在您的前端表单中,有一个名为“rememberMe”的复选框:

<form ...>

   Username: <input type="text" name="username"/> <br/>
   Password: <input type="password" name="password"/>
    ...
   <input type="checkbox" name="rememberMe" value="true"/>Remember Me?
   ...
</form>

默认情况下,FormAuthenticationFilter会寻找名为usernamepasswordrememberMe的请求参数。如果这些与您在表单中使用的表单字段名称不同,则需要在FormAuthenticationFilter上配置名称。例如,在shiro.ini:

[main]
...
authc.loginUrl = /whatever.jsp
authc.usernameParam = somethingOtherThanUsername
authc.passwordParam = somethingOtherThanPassword
authc.rememberMeParam = somethingOtherThanRememberMe
...

Cookie配置

您可以在rememberMeManager对象中自定义cookie的各种属性,例如:

[main]
...

securityManager.rememberMeManager.cookie.name = foo
securityManager.rememberMeManager.cookie.maxAge = blah
...

自定义 RememberMeManager

如果默认的RememberMeManager实现不能满足您的需求,您可以像自定义SecurityManager那样去实现一个自定义类,然后在配置文件中引用:

[main]
...
rememberMeManager = com.my.impl.RememberMeManager
securityManager.rememberMeManager = $rememberMeManager
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值