Web項目中集成Shrio(web.xml):
<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.存放在classpath的根目錄中(classpath:shiro.ini)。
配置文檔功能介紹:
1.EnvironmentLoaderListener的功能是創建IniWebEnvironment實例初始化Shiro的運行環境,獲取shiro.ini信息。如果需要自定義初始化,可以使用WebUtils.getRequiredWebEnvironment(servletContext)來進行環境初始化。
2.ShiroFilter將對初始化後的web應用執行過濾操作。
3.filter-mapping設定過濾規則。
(一般情況下,需要將Shiro的filter-mapping定義在最前面,以保證過濾器可以率先執行全局過濾。)
自定義配置文件加載所需配置(捨棄EnvironmentLoaderListener的初始化。web.xml):
<context-param> <param-name>shiroEnvironmentClass</param-name> <param-value>com.foo.bar.shiro.MyWebEnvironment</param-value> </context-param>
自定義的初始化工具類可以加載xml等不同的配置文件。
一、配置文件的路徑設置(使用Resource.Utils定義的資源路徑前綴)
1.2及以後版本中可以如此定義:
1./WEB-INF/shiro.ini;
2.存放在classpath的根目錄中(classpath:shiro.ini)。
在早期版本中必須如此定義:
1.文件系統式:file:/home/foobar/myapp/shiro.ini;
2.相對路徑式:classpath:com/foo/bar/shiro.ini;
3.URL式:url:http://confighost.mycompany.com/myapp/shiro.ini。
二、可以在web.xml中直接寫shiro.ini的內容:
<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 //將ini文件中的配置全部寫在這裏 </param-value></init-param> </filter> ...
一般會將shiro的配置獨立寫在另外的文件:
1.shiro的配置很多,與web.xml中的配置寫在一塊顯得很亂,且不美觀;
2.shiro配置需要和web.xml分割開,需要一定獨立性;
3.保證web.xml的易讀性;
4.保持shiro配置的可重用性。
Web集成Shiro的早期配置方法(web.xml):
<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>
如果shiro.ini文件既不在classpath根目錄,也不在Web-INF下,則需要爲其設定路徑:
<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.ini中urls塊的配置:
...
[urls]
/index.html = anon
/user/create = anon
/user/** = authc
/admin/** = authc, roles[administrator]
/rest/** = authc, rest
/remoting/rpc/** = authc, perms["remote:invoke"]
等號左邊是需要過濾的對象,右邊是過濾所執行的過濾器的名字,過濾器的名字在 main區域中會有定義。如果過濾器需要特殊定義,可以寫成filterName[filterUrlPath-過濾器路徑]。
過濾器會按照所寫的順序執行。
案例一:
/account/** = ssl, authc
含義:任何通過/account路徑,或者其拓展路徑/account/foo,/account/bar/baz的行爲都會觸發ssl、authc過濾器的過濾啓動。
案例二:
/account/** = ssl, authc
/account/signup = anon
第二行配置永遠執行不了,因爲第一行的過濾器已經將符合第二行規則的用戶全部過慮掉了(以爲這些用戶不符合第一行規則)。所以,設定過濾器的順序很重要。
如果需要實現自定義filter,需要繼承org.apache.shiro.web.filter.PathMatchingFilter類。並且在main區域加以配置:
[main]
...
myFilter = com.company.web.some.FilterImplementation
myFilter.property1 = value1
...
[urls]
...
/some/path/** = myFilter
Shiro自帶多個filter:
[main]
...
# Notice how we didn't define the class for the FormAuthenticationFilter ('authc') - it is instantiated and available already:
authc.loginUrl = /login.jsp //我們並沒有在main區域定義名字爲‘authc’的filter,但是shiro本身已經定義了,所以可以直接引用。
...
[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:
在Shiro1.2之前如果需要使filter失效,需要將其從配置文件中刪除或註釋,現在只需添加其狀態爲不可用即可。
[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]
...
實質上,OncePerRequestFilter通過它的isEnabled(request, response)方法來控制某一個filter的啓用或停用,可以根據需要重寫。它的子類PathMatchingFilter則可以控制路徑匹配的過濾,可以根據需要重寫。
ServletContainerSessionManager是SessionManager的子類,它可以實現Shiro的session與servlet的session之間的互通與共享。
優點:session擁有共同的配置屬性。
缺點:配置屬性具有不可移植性。
如果想要對Shiro的session做特殊的配置,則需要啓用Shiro的自己的sessionManager機制來代替servlet的session管理機制接管應用中所有的session(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
另外,Shiro的本地sessionManager可以設定cookie
1.sessionIdCookieEnabled (a boolean) 設定cookie的可用
2.sessionIdCookie 初始化cookie實例
創建cookie模板(shiro.ini):
[main]
...
securityManager.sessionManager.sessionIdCookie.domain = foo.com
禁用cookie(shiro.ini):
[main]
...
securityManager.sessionManager.sessionIdCookieEnabled = false
記住我功能實現:
java:
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
token.setRememberMe(true);
SecurityUtils.getSubject().login(token);
...
shiro.ini:
[main]
authc.loginUrl = /login.jsp
[urls]
# your login form page here:
login.jsp = authc
jsp:
<form ...>
Username: <input type="text" name="username"/> <br/>
Password: <input type="password" name="password"/>
...
<input type="checkbox" name="rememberMe" value="true"/>Remember Me?
...
</form>
其中這三個參數名字是shiro限定的,如果要改變,需要在shiro.ini中進行配置:
[main]
...
authc.loginUrl = /whatever.jsp
authc.usernameParam = somethingOtherThanUsername
authc.passwordParam = somethingOtherThanPassword
authc.rememberMeParam = somethingOtherThanRememberMe
...
設置記住我的cookie(shiro.ini):
[main]
...
securityManager.rememberMeManager.cookie.name = foo
securityManager.rememberMeManager.cookie.maxAge = blah
...
當然記住我功能是可以定製的(shiro.ini):
[main]
...
rememberMeManager = com.my.impl.RememberMeManager
securityManager.rememberMeManager = $rememberMeManager
JSP引用Shiro
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
案例一(遊客登錄):
<shiro:guest>
Hi there! Please <a href="login.jsp">Login</a> or <a href="signup.jsp">Signup</a> today!
</shiro:guest>
案例二(用戶登錄):
<shiro:user>
Welcome back John! Not John? Click <a href="login.jsp">here<a> to login.
</shiro:user>
案例三(驗證用戶登錄):
<shiro:authenticated>
<a href="updateAccount.jsp">Update your contact information</a>.
</shiro:authenticated>
案例四(未認證用戶登錄):
<shiro:notAuthenticated>
Please <a href="login.jsp">login</a> in order to update your credit card information.
</shiro:notAuthenticated>
案例五(principal標籤輸出用戶驗證信息):
Hello, <shiro:principal/>, how are you today?
等同於
Hello, <%= SecurityUtils.getSubject().getPrincipal().toString() %>, how are you today?
案例六(principal從驗證屬性中取出類型匹配的屬性):
User ID: <principal type="java.lang.Integer"/>
等同於
User ID: <%= SecurityUtils.getSubject().getPrincipals().oneByType(Integer.class).toString() %>
案例七(直接通過屬性名來取值):
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?
案例八(指定特定角色):
<shiro:hasRole name="administrator">
<a href="admin.jsp">Administer the system</a>
</shiro:hasRole>
案例九(去除特定角色):
<shiro:lacksRole name="administrator">
Sorry, you are not allowed to administer the system.
</shiro:lacksRole>
案例十(擁有角色集中的某一個):
<shiro:hasAnyRoles name="developer, project manager, administrator">
You are either a developer, project manager, or administrator.
</shiro:lacksRole>
案例十一(擁有特定權限):
<shiro:hasPermission name="user:create">
<a href="createUser.jsp">Create a new User</a>
</shiro:hasPermission>
案例十二(去除特定權限者):
<shiro:hasPermission name="user:create">
<a href="createUser.jsp">Create a new User</a>
</shiro:hasPermission>