# 10. Web
# 10. Web
## <a class="pcalibre11 pcalibre2 pcalibre3 pcalibre1" id="Web-configuration">Configuration 配置</a>
將 Shiro 集成到任何 Web 應用程序的最簡單的方法是在 web.xml 中配置 ContextListener 和 Filter,理解如何讀取 Shiro 的 INI 配置文件。大部分的 INI 配置格式定義在 [Configuration](../I.%20Overview%20%E6%80%BB%E8%A7%88/4.%20Configuration%20%E9%85%8D%E7%BD%AE.md) 頁的 INI Sections 節,但我在這里我們將介紹一些額外的Web 的特定部分。
*Using Spring?*
*Spring 框架用戶將不執行此設置。如果你使用 Spring,你將要閱讀關于[Spring 特定的 Web 配置](../V.%20Integration%20%E6%95%B4%E5%90%88/15.%20Spring%20Framework.md)*
### Web.xml
### Shiro 1.2 and later
在Shiro 1.2 及以后版本,標準的 Web 應用程序通過添加下面的 XML 塊到 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 [Configuration](../I.%20Overview%20%E6%80%BB%E8%A7%88/4.%20Configuration%20%E9%85%8D%E7%BD%AE.md) 文件在以下兩個位置任意一個,并使用最先發現的那個:
1. /WEB-INF/shiro.ini
2. 在classpath 根目錄下shiro.ini 文件
下面是上述配置所做的事情:
- EnvironmentLoaderListener 初始化一個Shiro WebEnvironment 實例(其中包含 Shiro 需要的一切操作,包括 SecurityManager ),使得它在 ServletContext 中能夠被訪問。如果你需要在任何時候獲得WebEnvironment 實例,你可以調用WebUtils.getRequiredWebEnvironment(ServletContext)。
- ShiroFilter 將使用此 WebEnvironment 對任何過濾的請求執行所有必要的安全操作。
- 最后,filter-mapping 的定義確保了所有的請求被 ShiroFilter 過濾,建議大多數 Web 應用程序使用以確保任何請求是安全的。
*ShiroFilter filter-mapping*
*它通常可取的做法是在任何其他 filter-mapping 聲明之前定義 ShiroFilter filter-mapping,以確保 Shiro 也能在那些過濾器 下工作的很好。*
#### Custom WebEnvironment Class
默認情況下,EnvironmentLoaderListener 將創建一個IniWebEnvironment 實例,呈現 Shiro 基于INI 文件的[Configuration](../I.%20Overview%20%E6%80%BB%E8%A7%88/4.%20Configuration%20%E9%85%8D%E7%BD%AE.md)。如果你愿意,你可以在 web.xml 中指定一個自定義的 ServletContext context-param:
shiroEnvironmentClass</param-name> com.foo.bar.shiro.MyWebEnvironment</param-value> </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 指定該位置。
```
<context-param>
<param-name>shiroConfigLocations</param-name>
<param-value>YOUR_RESOURCE_LOCATION_HERE</param-value>
</context-param>
```
默認情況下,在 ServletContext.getResource 方法定義的規則下,param-value 是可以被解析的。例如, /WEB-INF/some/path/shiro.ini。
但你也可以指定具體的文件系統,如classpath 或URL 位置,通過使用Shiro 支持的合適的[ResourceUtils 類](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/io/ResourceUtils.html),例如:
- file://home/foobar/myapp/shiro.ini
- classpath:com/foo/bar/shiro.ini
- url:<http://confighost.mycompany.com/myapp/shiro.ini>
### Shiro 1.1 and earlier
在Web 應用程序中使用Shiro 1.1 或更早版本的最簡單的方法是定義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 配置是一個在 classpath 根目錄的Shiro.ini 文件(如:classpath:shiro.ini)。
#### Custom Path
如果你不想將你的 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>
...
```
不合格的(不完整的組合或'non-prefixed')configPath 值被假定為ServletContext 的資源路徑,通過 ServletContext.[getResource](http://download.oracle.com/javaee/6/api/javax/servlet/ServletContext.html#getResource(java.lang.String)) 方法所定義的規則來解析。
*ServletContext resource paths - Shiro 1.2+*
*ServletContext 資源路徑是一個在 Shiro 1.2 即將推出的功能。在 1.2 被發布后,所有的configPath 定義必須指定一個 classpath:,file:或url:前綴。*
通過分別地使用 classpath:,url:,或file:前綴來指明classpath,url,或 filesystem 位置,你也可以指定其他非 ServletContext 資源位置。例如:
```
...
<init-param>
<param-name>configPath</param-name>
<param-value>url:http://configHost/myApp/shiro.ini</param-value>
</init-param>
...
```
#### Inline Config
最后,也可以將你的 INI 配置嵌入到 web.xml 中而不使用一個獨立的 INI 文件。你可以通過使用 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 配置中分離安全配置。
- 你的安全配置可能變得很大,你想保持 web.xml 的苗條并易于閱讀。
- 你有個負責的編譯系統,相同的 shiro 配置可能需要在多個地方被引用。
這取決于你——使用什么使你的項目更有意義。
### <a class="pcalibre11 pcalibre2 pcalibre3 pcalibre1" id="Web-webini">Web INI configuration</a>
除了在主要的 [Configuration](https://github.com/waylau/apache-shiro-1.2.x-reference/blob/master/I.%20Overview%20%E6%80%BB%E8%A7%88/4.%20Configuration%20%E9%85%8D%E7%BD%AE.md) 章節描述的標準的\[main\],\[user\]和\[roles\]項外,你可以在shiro.ini 文件中指定具有 web 特性的\[urls\]項:
```
# [main], [users] and [roles] above here
...
[urls]
...
```
\[urls\]項允許你做一些在我們已經見過的任何 Web 框架都不存在的東西:在你的應用程序中定義自適應過濾器鏈來匹配URL 路徑!
這將更為靈活,功能更為強大,比你通常在 web.xml 中定義的過濾器鏈更為簡潔:即使你從未使用任何 Shiro 提供的其他功能并僅僅使用了這個,但它即使是單獨使用也是值得的。
\[urls\]
在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"]
```
接下來我們將討論這些行的具體含義。
#### URL Path Expressions
等號左邊是一個與Web 應用程序上下文根目錄相關的 [Ant](http://ant.apache.org/) 風格的路徑表達式。
例如,假設你有如下的\[urls\]行:
```
/account/** = ssl, authc
```
此行表明,“任何對我應用程序的/accout 或任何它的子路徑(/account/foo, account/bar/baz,等等)的請求都將觸發'ssl, authc'過濾器鏈”。我們將在下面討論過濾器鏈。
請注意,所有的路徑表達式都是相對于你的應用程序的上下文根目錄而言的。這意味著如果某一天你在某個位置部署了你的應用程序,如 www.somehost.com/myapp ,然后又將它部署到了 www.anotherhost.com (沒有'myapp'子目錄),這樣的匹配模式仍將繼續工作。所有的路徑都是相對于 [HttpServletRequest.getContextPath()](http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/servlet/http/HttpServletRequest.html#getContextPath()) 的值來的。
*Order Matters! 秩序*
*URL 路徑表達式按事先定義好的順序判斷傳入的請求,并遵循 FIRST MATCH WINS 這一原則。例如,讓我們假設有如下鏈的定義:*
```
/account/** = ssl, authc
/account/signup = anon
```
*如果傳入的請求旨在訪問 /account/signup/index.html(所有 'anon'ymous 用戶都能訪問),那么它將永不會被處理!原因是因為/account/\*\* 的模式第一個匹配了傳入的請求,“短路”了其余的定義。 始終記住基于FIRST MATCH WINS 的原則定義你的過濾器鏈!*
#### Filter Chain Definitions 定義
等號右邊是逗號隔開的過濾器列表,用來執行匹配該路徑的請求。它必須符合以下格式:
filter1\[optional\_config1\], filter2\[optional\_config2\], ..., filterN\[optional\_configN\]
并且:
- filterN 是一個定義在\[main\]項中的 filter bean 的名字
- \[optional\_configN\]是一個可選的括號內的對特定的路徑,特定的過濾器有特定含義的字符串(每個過濾器,每個路徑的具體配置!)。若果該過濾器對該 URL 路徑并不需要特定的配置,你可以忽略括號,于是 filteNr\[\] 就變成了 filterN.
因為過濾器標志符定義了鏈(又名列表),所以請記住順序問題!請按順序定義好你的逗號分隔的列表,這樣請求就能夠流通這個鏈。
最后,每個過濾器按照它期望的方式自由的處理請求,即使不具備必要的條件(例如,執行一個重定向,響應一個 HTTP 錯誤代碼,直接渲染等)。否則,它有可能允許該請求繼續通過這個過濾器鏈到達最終的視圖。
*確保能夠對路徑的具體配置作出反應,即\[optional\_configN\]一個過濾器標志符的一部分,是一個對所有Shiro 過濾器 適用的獨有的功能。*
*你也可以這樣做,如果你想創建你自己的 javax.servlet.Filter 的實現的話,確保你的過濾器子類 [org.apache.shiro.web.filter.PathMatchingFilter](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/PathMatchingFilter.html)*
#### Available Filters 可用的過濾器
在過濾器鏈中能夠使用的過濾器“池”被定義在\[main\]項。在\[main\]項中指派給它們的名字就是在過濾器鏈定義中使 用的名字。例如:
```
[main]
...
myFilter = com.company.web.some.FilterImplementation
myFilter.property1 = value1
...
[urls]
...
/some/path/** = myFilter
```
## <a class="pcalibre11 pcalibre2 pcalibre3 pcalibre1" id="Web-defaultfilters">Default Filters</a>
當運行一個 Web 應用程序時,Shiro 將會創建一些有用的默認 Filter 實例,并自動地在\[main\]項中將它們置為可用。
你可以在 main 中配置它們,當作在你的鏈的定義中你是否有任何其他的bean 和 reference。例如:
```
[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
...
```
自動地可用的默認的Filter 實例是被 [DefaultFilter 枚舉](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/mgt/DefaultFilter.html)定義的,枚舉的名稱字段是可供配置的名稱。它們是:
Filter Name Class anon [org.apache.shiro.web.filter.authc.AnonymousFilter](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/authc/AnonymousFilter.html) authc [org.apache.shiro.web.filter.authc.FormAuthenticationFilter](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/authc/FormAuthenticationFilter.html) authcBasic [org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/authc/BasicHttpAuthenticationFilter.html) logout [org.apache.shiro.web.filter.authc.LogoutFilter](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/authc/LogoutFilter.html) noSessionCreation [org.apache.shiro.web.filter.session.NoSessionCreationFilter](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/session/NoSessionCreationFilter.html) perms [org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/authz/PermissionsAuthorizationFilter.html) port [org.apache.shiro.web.filter.authz.PortFilter](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/authz/PortFilter.html) rest [org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/authz/HttpMethodPermissionFilter.html) roles [org.apache.shiro.web.filter.authz.RolesAuthorizationFilter](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/authz/RolesAuthorizationFilter.html) ssl [org.apache.shiro.web.filter.authz.SslFilter](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/authz/SslFilter.html) user [org.apache.shiro.web.filter.authc.UserFilter](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/authc/UserFilter.html) ## Enabling and Disabling Filters 啟動、禁用過濾器
由于這是與任何過濾器鏈定義機制(web.xml,Shiro 的INI 等)相關的例子,你通過在過濾器鏈中包含它來啟用過濾器,通過在過濾器鏈中移除它來禁用過濾器。
但在Shiro 1.2 中新增的一個新功能是不通過從過濾器鏈中移除過濾器來啟用或禁用過濾器。如果啟用(默認設置),那么請求將如預期一樣過濾。如果禁用,那么該過濾器將允許請求立即通過到FilterChain 的下一個元素。你可以基于一般配置屬性觸發過濾器的啟用狀態,或者你甚至可以在每一個請求的基礎上觸發。
這是一個強大的概念,因為基于特定需求啟用或禁用一個過濾器比更改靜態過濾器鏈(這是永久的且固定的)定義更為方便。
Shiro 通過它的 [OncePerRequestFilter](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/servlet/OncePerRequestFilter.html) 抽象父類來完成這點。所有 Shiro 的不受規范限制的過濾器實現子類實現這一點,因此不需要從過濾器鏈移除它們實現啟用或禁用。如果你需要實現此功能,你可以為自己的過濾器實現繼承這個類的子類。
[SHIRO-224](https://issues.apache.org/jira/browse/SHIRO-224) 將有望為任何過濾器使用這項功能,不僅僅只是那些OncePerRequestFilter 的子類。如果這對你很重要,請為這個issue 投票。
### General Enabling/Disabling
[OncePerRequestFilter](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/servlet/OncePerRequestFilter.html)(及其所有子類)支持 Enabling/Disabling 所有請求及 per-request 基礎。 一般為所有的請求啟用或禁用一個過濾器是通過設置其 enabled 屬性為true 或 false。默認的設置是true 由于大多 數過濾器本質上是需要執行的,如果他們被配置在一個過濾器鏈中。 例如,在shiro.ini 中:
```
[main]
...
# configure Shiro's default 'ssl' filter to be disabled while testing:
ssl.enabled = false
[urls]
...
/some/path = ssl, authc
/another/path = ssl, roles[admin]
...
```
該例表明,許多潛在的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](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/PathMatchingFilter.html)(一個 OncePerRequestFilter 的子類)能夠對基于被過濾的特定路徑的配置作出反應。這 意味著你可以啟用或禁用一個過濾器基于路徑和特定路徑配置,除了傳入的request 和 response。 如果你需要能夠對匹配的路徑和特定路徑配置作出反應來判斷一個過濾器是否是啟用的或禁用的,而不是通過覆蓋 OncePerRequestFilter 的 isEnabled(request, reponse)方法,你應該是覆蓋 PathMatchingFilter 的 isEnabled(request,response,path,pathConfig) 方法。
## <a class="pcalibre11 pcalibre2 pcalibre3 pcalibre1" id="Web-sessionManagement">Session Management</a>
### Servlet Container Sessions
在 web 環境中,Shiro 的默認的會話管理器 [SessionManager](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/session/mgt/SessionManager.html) 實現是 [ServletContainerSessionManager](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/session/mgt/ServletContainerSessionManager.html) 。 這個非常簡單的實現代表所有會話管理職責(包括會話集群如果 servlet 容器支持)運行 servlet 容器。 它本質上是一個橋 Shiro 會話 API 的 servlet 容器,沒有別的。
使用這個默認的一個好處是,使用現有的 servlet 容器的應用程序會話配置(超時,任何特定容器集群機制等)將正常工作。
這個默認的缺點是,你與 servlet 容器的特定會話行為。 舉個例子,如果你想集群會話,但你使用 Jetty 在生產、測試和 Tomcat 容器配置(或代碼)將不具有可移植性。
#### Servlet Container Session Timeout 容器會話超時
如果使用默認 servlet 容器支持,您配置將在您的web應用程序的會話超時 web . xml 文件。 例如:
```
<session-config>
<!-- web.xml expects the session timeout in minutes: -->
<session-timeout>30</session-timeout>
</session-config>
```
### Native Sessions 本地會話
如果你想讓你的會話配置設置和集群便攜式在 servlet 容器(比如 Jetty 在測試中,但 Tomcat 或 JBoss 在生產環境中),或你想控制特定的會話/聚類特性,您可以啟用 Shiro 的原生會話管理。
“Native”這個詞在這里意味著 Shiro 的企業將被用來支持所有會話管理實現 Subject 和 httpservletrequest 會話和完全繞過 servlet容器。 但放心,Shiro 實現 Servlet 規范的相關部分直接所以任何現有的 web/http 相關代碼符合預期和不需要“知道”,Shiro 透明地管理會話。
#### DefaultWebSessionManager
啟用本地會話管理您的web應用程序,您需要配置一個本地 web-capable 會話管理器覆蓋默認的基于 servlet 容器。 你可以通過配置的一個實例 [DefaultWebSessionManager](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/session/mgt/DefaultWebSessionManager.html) Shiro 的 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 實例與本地會話選項會話超時和集群配置的描述 [會話管理](http://shiro.apache.org/session-management.html) 部分。
#### Native Session Timeout本地會話超時
配置后 DefaultWebSessionManager 例如,會話超時配置中描述 [會話管理:會話超時](http://shiro.apache.org/session-management.html#SessionManagement-sessionTimeout)
#### Session Cookie
DefaultWebSessionManager 支持兩種網絡自身配置屬性:
- sessionIdCookieEnabled (一個 boolean)
- sessionIdCookie, 一個 [Cookie](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/servlet/Cookie.html) 實例.
*Cookie as a template 作為模板*
*sessionIdCookie 屬性本質上是一個模板,你配置 Cookie 實例屬性,該模板將在運行時用一個適當的會話ID值設置在實際 HTTP Cookie header中*
#### Session Cookie Configuration 配置
DefaultWebSessionManager 的 sessionIdCookie 默認實例是一個 [SimpleCookie](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/servlet/SimpleCookie.html) 。 這個簡單的實現允許 JavaBeans-style 屬性配置為所有你想要的相關屬性配置在 http Cookie。
例如,您可以設置 Cookie 域
```
[main]
...
securityManager.sessionManager.sessionIdCookie.domain = foo.com
```
查看 [SimpleCookie JavaDoc](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/servlet/SimpleCookie.html) 額外的屬性。
cookie 的默認名稱 JSESSIONID 根據servlet規范。 此外,Shiro 的cookie 支持 [HttpOnly](http://en.wikipedia.org/wiki/HTTP_cookie#HttpOnly_cookie) 標識。 sessionIdCookie 設置 在默認情況下 httponly 為 true 為了額外的安全。
*Shiro 的 Cookie 概念支持 HttpOnly 標識 甚至在 Servlet 2.4和 2.5 環境(而對原生的 Servlet API 只支持它在 2.6 或更高版本)。*
#### Disabling the Session Cookie 禁用
如果您不希望使用會話 cookie,您可以禁用它們被配置使用 sessionIdCookieEnabled 屬性為 false。 例如
```
[main]
...
securityManager.sessionManager.sessionIdCookieEnabled = false
```
## Remember Me Services
Shiro 將執行 'rememberMe' 服務如果 AuthenticationToken 實現了 [org.apache.shiro.authc.RememberMeAuthenticationToken](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/authc/RememberMeAuthenticationToken.html) 接口。該接口指定了一個方法
```
boolean isRememberMe();
```
如果該方法返回 true,Shiro 將會在整個會話中記住終端用戶的身份ID
*UsernamePasswordToken and RememberMe*
*經常使用的 UsernamePasswordToken 已經實現了RememberMeAuthenticationToken 接口,并支持 rememberMe 登錄。*
### Programmatic Support 編程支持
要有計劃性地使用 rememberMe ,你可以在一個支持該配置的類上把它的值設為 true。例如,使用標準的 UsernamePasswordToken:
```
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
token.setRememberMe(true);
SecurityUtils.getSubject().login(token);
```
### Form-based Login 基于表單的登錄
對于 Web 應用程序而言,authc 過濾器默認是FormAuthenticationFilter 。它支持將 'rememberMe' 的布爾值作為一個 form/request 參數讀取。默認地,它期望該 request 參數被命名為 rememberMe。下面是一個支持這點的 shiro.ini 配置的例子:
```
[main]
authc.loginUrl = /login.jsp
[urls]
# your login form page here:
login.jsp = authc
```
同時在你的 web form 中有一個名為 'rememberMe' 的checkbox。
```
<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 將會尋找名為 username,password 及 rememberMe 的request 參數。如果這些不同于你使用的form 中的表單域名,你可能想在 FormAuthenticationFilter 上配置這些參數名。例如,在 shiro.ini 中:
```
[main]
...
authc.loginUrl = /whatever.jsp
authc.usernameParam = somethingOtherThanUsername
authc.passwordParam = somethingOtherThanPassword
authc.rememberMeParam = somethingOtherThanRememberMe
...
```
### Cookie configuration
你可以通過設定 的各方面的 cookie 屬性來配置 rememberMe cookie 是如何工作的。例如, 在shiro.ini 中:
```
[main]
...
securityManager.rememberMeManager.cookie.name = foo
securityManager.rememberMeManager.cookie.maxAge = blah
...
```
請參見 [CookieRememberMeManager](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/mgt/CookieRememberMeManager.html) 及 [SimpleCookie](http://shiro.apache.org/static/current/apidocs/src-html/org/apache/shiro/web/servlet/SimpleCookie.html) 的 JavaDoc 支持來獲取更多的配置屬性
## <a class="pcalibre11 pcalibre2 pcalibre3 pcalibre1" id="Web-taglibrary">JSP / GSP Tag Library</a>
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 服務)。 例子:
```
<shiro:guest>
Hi there! Please <a href="login.jsp">Login</a> or <a href="signup.jsp">Signup</a> today!
</shiro:guest>
```
guest 標簽與user 標簽邏輯相反。
### The user tag
user 標簽將顯示它包含的內容,僅當當前的 Subject 被認為是 'user' 時。'user' 在上下文中被定義為一個已知身份 ID 的 Subject,或是成功通過身份驗證及通過'RememberMe'服務的。請注意這個標簽在語義上與authenticated 標簽是 不同的,authenticated 標簽更為嚴格。
```
<shiro:user>
Welcome back John! Not John? Click <a href="login.jsp">here<a> to login.
</shiro:user>
```
usre 標簽與 guest 標簽邏輯相反。
### The authenticated tag
僅僅只當當前用戶在當前會話中成功地通過了身份驗證 authenticated 標簽才會顯示包含的內容。它比 'user' 標簽更為嚴格。它在邏輯上與'notAuthenticated'標簽相反。
authenticated 標簽只有當當前 Subject 在其當前的會話中成功地通過了身份驗證才會顯示包含的內容。它比 user 標簽更為嚴格,authenticated 標簽通常在敏感的工作流中用來確保身份 ID 是可靠的。
例子:
```
<shiro:authenticated>
<a href="updateAccount.jsp">Update your contact information</a>.
</shiro:authenticated>
```
authenticated 標簽與 notAuthenticated 標簽邏輯相反。
### The notAuthenticated tag
notAuthenticated 標簽將會顯示它所包含的內容,如果當前 Subject 還沒有在其當前會話中成功地通過驗證。
例子:
```
<shiro:notAuthenticated>
Please <a href="login.jsp">login</a> in order to update your credit card information.
</shiro:notAuthenticated>
```
notAuthenticated 標簽與 Authenticated 標簽邏輯相反。
### The principal tag
principal 標簽將會輸出 Subject 的主體(標識屬性)或主要的屬性。 若沒有任何標簽屬性,則標簽將使用 principal 的 toString()值來呈現頁面。例如(假設 principal 是一個字符串的用戶名):
```
Hello, <shiro:principal/>, how are you today?
```
這(大部分地)等價于下面:
```
Hello, <%= SecurityUtils.getSubject().getPrincipal().toString() %>, how are you today?
```
#### Typed principal
principal 標簽默認情況下,假定該 principal 輸出的是subject.getPrincipal() 的值。但若你想輸出一個不是主要 principal 的值,而是屬于另一個 Subject 的 principal collection,你可以通過類型來獲取該 principal 并輸出該值。
例如,輸出 Subject 的用戶 ID(并不是 username ),假設該 ID 屬于 principal collection:
```
User ID: <principal type="java.lang.Integer"/>
```
這(大部分地)等價于下面:
```
User ID: <%= SecurityUtils.getSubject().getPrincipals().oneByType(Integer.class).toString() %>
```
#### Principal property
但如果該 principal (是默認主要的 principal 或是上面的'typed' principal)是一個復雜的對象而不是一個簡單的字符串,而且你希望引用該 principal 上的一個屬性該怎么辦呢?你可以使用 property 屬性來來表示 property 的名稱來理解(必須通過 JavaBeans 兼容的 getter 方法訪問)。例如(假主要的principal 是一個User 對象):
```
Hello, <shiro:principal property="firstName"/>, how are you today?
```
這(大部分地)等價于下面:
```
Hello, <%= SecurityUtils.getSubject().getPrincipal().getFirstName().toString() %>, how are you today?
```
或者,結合類型屬性:
```
Hello, <shiro:principal type="com.foo.User" property="firstName"/>, how are you today?
```
這也很大程度地等價于下面:
```
Hello, <%= SecurityUtils.getSubject().getPrincipals().oneByType(com.foo.User.class).getFirstName().toString() %>, how are you today?
```
### The hasRole tag
hasRole 標簽將會顯示它所包含的內容,僅當當前 Subject 被分配了具體的角色。
例如:
```
<shiro:hasRole name="administrator">
<a href="admin.jsp">Administer the system</a>
</shiro:hasRole>
```
hasRole 標簽與lacksRole 標簽邏輯相反。
### The lacksRole tag
lacksRole 標簽將會顯示它所包含的內容,僅當當前 Subject 未被分配具體的角色。
例如:
```
<shiro:lacksRole name="administrator">
Sorry, you are not allowed to administer the system.
</shiro:lacksRole>
```
### The hasAnyRole tag
hasAnyRole 標簽將會顯示它所包含的內容,如果當前的 Subject 被分配了任意一個來自于逗號分隔的角色名列表中的具體角色。
例如:
```
<shiro:hasAnyRoles name="developer, project manager, administrator">
You are either a developer, project manager, or administrator.
</shiro:lacksRole>
```
### The hasPermission tag
hasPermission 標簽將會顯示它所包含的內容,僅當當前Subject“擁有”(蘊含)特定的權限。也就是說,用戶具有特定的能力。
例如:
```
<shiro:hasPermission name="user:create">
<a href="createUser.jsp">Create a new User</a>
</shiro:hasPermission>
```
hasPermission 標簽與lacksPermission 標簽邏輯相反。
### The lacksPermission tag
lacksPermission 標簽將會顯示它所包含的內容,僅當當前Subject 沒有擁有(蘊含)特定的權限。也就是說,用戶沒有特定的能力。
例如:
```
<shiro:lacksPermission name="user:delete">
Sorry, you are not allowed to delete user accounts.
</shiro:hasPermission>
```
## 為文檔加把手
我們希望這篇文檔可以幫助你使用 Apache Shiro 進行工作,社區一直在不斷地完善和擴展文檔,如果你希望幫助 Shiro 項目,請在你認為需要的地方考慮更正、擴展或添加文檔,你提供的任何點滴幫助都將擴充社區并且提升 Shiro。
提供你的文檔的最簡單的途徑是將它發送到用戶[論壇](http://shiro-user.582556.n2.nabble.com/)或[郵件列表](http://shiro.apache.org/mailing-lists.html)
*譯者注:*如果對本中文翻譯有疑議的或發現勘誤歡迎指正,[點此](https://github.com/waylau/apache-shiro-1.2.x-reference/issues)提問。
- Introduction
- 1. Introduction 介紹
- 2. Tutorial 教程
- 3. Architecture 架構
- 4. Configuration 配置
- 5. Authentication 認證
- 6. Authorization 授權
- 6.1. Permissions 權限
- 7. Realms
- 8. Session Management
- 9. Cryptography 密碼
- 10. Web
- 10.1. Configuration 配置
- 10.2. 基于路徑的 url 安全
- 10.3. Default Filters 默認過濾器
- 10.4. Session Management
- 10.5. JSP Tag Library
- 11. Caching 緩存
- 12. Concurrency & Multithreading 并發與多線程
- 13. Testing 測試
- 14. Custom Subjects 自定義 Subject
- 15. Spring Framework
- 16. Guice
- 17. CAS
- 18. Command Line Hasher
- 19. Terminology 術語
- 20. 10 Minute Tutorial 十分鐘教程
- 21. Beginner's Webapp Tutorial 初學者web應用教程
- 22. Application Security With Apache Shiro 用Shiro保護你的應用安全
- 23. CacheManager 緩存管理
- 24. Apache Shiro Cryptography Features 加密功能