Apache Shiro Web Support學習筆記

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:

anon org.apache.shiro.web.filter.authc.AnonymousFilter
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
logout org.apache.shiro.web.filter.authc.LogoutFilter
noSessionCreation org.apache.shiro.web.filter.session.NoSessionCreationFilter
perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
port org.apache.shiro.web.filter.authz.PortFilter
rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
ssl org.apache.shiro.web.filter.authz.SslFilter
user org.apache.shiro.web.filter.authc.UserFilter


在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>




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章