Shiro User Manual-Web Support

阅读更多
1. Configuration
将Shiro集成到web应用中非常简单,只需要在web.xml中配置ContextListener和Filter即可。需要注意的是,如果是Spring web应用,请参考Shiro与Spring集成那节。
a. web.xml
Shiro1.2及其以后版本,在web.xml中添加:

    org.apache.shiro.web.env.EnvironmentLoaderListener


...


    ShiroFilter
    org.apache.shiro.web.servlet.ShiroFilter



    ShiroFilter
    /*
    REQUEST 
    FORWARD 
    INCLUDE 
    ERROR


这种配置,可以将INI文件放到以下任意一处:
1. /WEB-INF/shiro.ini
2. shiro.ini在classpath下
上面的配置会执行以下操作:
1. EnvironmentLoaderListener初始化WebEnvironment(此接口包含了Shiro所有的操作)接口,并将它设置到ServletContext,之后,就可以通过WebUtils.getRequiredWebEnvironment(servletContext)获取WebEnvironment实例。
2. 对所有的请求,ShiroFilter将使用WebEnvironment执行所有的安全操作。
3. filter-mapping的配置使得所有的请求都要经过ShiroFilter,以保证请求的安全性。
建议将ShiroFilter filter-mapping配到其他Filter filter-mapping之前以确保Shiro好用。

b. Custom WebEnvironment Class
默认情况下,EnvironmentLoaderListener会创建IniWebEnvironment实例(即配置文件为INI格式)。可以通过设置ServletContext的context-param参数自定义WebEnvironment实例:

    shiroEnvironmentClass
    com.foo.bar.shiro.MyWebEnvironment


自定义WebEnvironment实例允许你以其他方式解析配置文件。还可以继承IniWebEnvironment进行一些其他的操作,甚至支持不同的文件配置。比如,如果想通过XML方式配置Shiro,就可以创建基于XML形式的XmlWebEnvironment实现。

c. Custom Configuration Locations
在web.xml中,添加context-param参数,以改变配置文件的存放位置:

    shiroConfigLocations
    YOUR_RESOURCE_LOCATION_HERE


默认使用ServletContext.getResource加载配置文件,即相对于应用根路径"/"。可以使用资源前缀将配置指向文件系统,类路径,URL:
file:/home/foobar/myapp/shiro.ini
classpath:com/foo/bar/shiro.ini
url:http://confighost.mycompany.com/myapp/shiro.ini


Shiro1.1及其以前版本的配置:

    ShiroFilter
    org.apache.shiro.web.servlet.IniShiroFilter


...





    ShiroFilter
    /*
    REQUEST 
    FORWARD 
    INCLUDE 
    ERROR


这个配置,需要你的Shiro配置文件为INI格式,且需要放在classpath下(比如: classpath:shiro.ini)。
如果你想替换默认的文件(/WEB-INF/shiro.ini or classpath:shiro.ini),可以通过指定init-param参数:

    ShiroFilter
    org.apache.shiro.web.servlet.IniShiroFilter
    
        configPath
        /WEB-INF/anotherFile.ini
    


不指定资源前缀的话,就使用默认的ServletContext.getResource加载配置文件。需要注意的是:ServletContext资源路径是1.2及其以后版本的功能,1.2以后版本配置configPath,必须指定资源前缀classpath:, file: 或 url: 。
通过指定资源前缀配置文件:

    configPath
    url:http://configHost/myApp/shiro.ini


也可以把INI文件中的内容直接写在web.xml中:

    ShiroFilter
    org.apache.shiro.web.servlet.IniShiroFilter
    config

    # INI Config Here

    



2. Web INI configuration
在Configuation那章,我们已经讲述了[main], [users] and [roles]的配置,这里我们只讲述[urls]的配置。
# [main], [users] and [roles] above here
...
[urls]

[urls]
这部分允许你为不同URL定义专门的过滤器。定义格式:
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"]

a. URL Path Expressions
等号左边是相对于应用根路径的Ant风格路径表达式,比如:
/account/** = ssl, authc

这行表示,对于请求路径是/account或其子路劲(/account/foo, /account/bar/baz等)将触发'ssl, authc'过滤器链。需要注意,所有表达式都是相对应用根路径(/)。
1. Order Matters!
URL定义的顺序很重要,对于传入的请求,它会按顺序依次匹配,最先匹配的即使用这个过滤器链。比如:
/account/** = ssl, authc
/account/signup = anon

如果一个请求的路径是/account/signup/index.html(可被匿名用户访问),请求将不能被处理。因为/account/**匹配请求的路径,并将短路所有其他路径。
b. Filter Chain Definitions
等号右边是以逗号","分隔的过滤器定义,如果和请求路径匹配,将使用这些过滤器进行处理。它必须符合以下格式:
filter1[optional_config1], filter2[optional_config2], ..., filterN[optional_configN]

  1. filterN是定义在[main]部分的过滤器。
  2. [optional_configN]选填内容,用于特殊过滤器的配置,如果过滤器对URL没有特殊的配置,简写为filterN。
需要注意,过滤器的配置顺序即为调用顺序。当请求的执行条件不满足时,过滤器可以对response进行任何操作,比如执行跳转,返回HTTP错误码等。如果请求条件满足,会进入下一个过滤器,直至到最后的视图。
如果想自定义过滤器,继承org.apache.shiro.web.filter.PathMatchingFilter即可。
c. Available Filters
[main]定义的过滤器都可以在此处引用:
[main]
...
myFilter = com.company.web.some.FilterImplementation
myFilter.property1 = value1
...

[urls]
...
/some/path/** = myFilter


3. Default Filters
对于web应用,Shiro会默认创建一些过滤器,并可以在[main]部分引用。
[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字段即为过滤器的名字:
Filter Name   Class
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


4. Enabling and Disabling Filters
如果某个过滤器不使用的话,我们可以直接删除掉。Shiro1.2版本,通过父类OncePerRequestFilter支持,可以将不使用的过滤器关闭,那么请求就不会经过这个过滤器。Shiro默认的所有过滤器都继承了这个类,所以,这些过滤器都可以进行打开和关闭操作。
a. General Enabling/Disabling
OncePerRequestFilter可控制过滤器对请求的打开和关闭,也可基于每次请求进行打开和关闭。通过设置过滤器的enabled属性即可,默认为true:
[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]

b. Request-specific Enabling/Disabling
OncePerRequestFilter实际上通过filter的isEnabled方法判断过滤器是否打开或关闭。该方法默认返回enabled属性值。如果你想基于请求条件决定其打开与否,可覆写isEnabled(request,response)方法。
c. Path-specific Enabling/Disabling
PathMatchingFilter可以根据配置的特殊路径进行过滤。就是说,可以依据配置的路径决定打开还是关闭过滤器。如果你想通过这种方式,需要覆写PathMatchingFilter的PathMatchingFilter isEnabled(request,response,path,pathConfig)方法。

5. Session Management
a. Servlet Container Sessions
在web环境下,ServletContainerSessionManager为SessionManager的实现类。它把所有session的管理全部委托给了容器,好的一面是,对于当前的session配置,完全有效。不好的一面是,session的行为依赖容器,比如说,你想做集群,如果测试用Jetty,但是生产环境是Tomcat,那么移植会很麻烦。
b. Servlet Container Session Timeout
如果使用容器支持的session管理,配置session的超时如下:

  
  30


c. Native Sessions
如果想让session的配置和集群可在容器间移植,或者想定义session的特性,可以使用Shiro自带的session管理,即native session management。
d. DefaultWebSessionManager
如果想使用自带的session管理器,需要在ini文件中,将DefaultWebSessionManager实例配置到SecurityManager:
[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后,可以进行相应属性的设置。具体请参考 Session Management那节。
e. Native Session Timeout
对于自带session的超时设置,请查看Session Management那节。
f. Session Cookie
DefaultWebSessionManager有两个和web相关的属性:
sessionIdCookieEnabled (a boolean)
sessionIdCookie, a Cookie instance

如果配置了Cookie实例,可通过sessionIdCookie属性将session ID设置到HTTP Cookie的头信息里。
g. Session Cookie Configuration
DefaultWebSessionManager的sessionIdCookie默认为SimpleCookie。可通过SimpleCookie属性设置任何值到HTTP Cookie里:
[main]
...
securityManager.sessionManager.sessionIdCookie.domain = foo.com

默认使用JSESSIONID为cookie的名。在Servlet2.4和2.5环境下,支持HttpOnly。
h. Disabling the Session Cookie
如果不想使用cookie,可将sessionIdCookieEnabled设置为false:
[main]
...
securityManager.sessionManager.sessionIdCookieEnabled = false

6. Remember Me Services
如果AuthenticationToken实现了org.apache.shiro.authc.RememberMeAuthenticationToken接口,就具有了rememberMe服务。RememberMeAuthenticationToken接口有一个方法:
boolean isRememberMe();

如果方法返回true,Shiro就会在本次会话中记住用户的标识。UsernamePasswordToken实现了这个接口并具有rememberMe功能。

6.1 Programmatic Support
对实现了org.apache.shiro.authc.RememberMeAuthenticationToken接口的类,只需要设置其setRememberMe发true即可。
UsernamePasswordToken token = new UsernamePasswordToken(username, password);

token.setRememberMe(true);

SecurityUtils.getSubject().login(token);


6.2 Form-based Login
对于web应用,过滤器authc的默认实现为FormAuthenticationFilter,它通过将rememberMe字段设置到请求参数里,以开启Remember Me服务:
[main]
authc.loginUrl = /login.jsp

[urls]

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

在login.jsp页面中加一个复选框:
Username:
Password: ... Remember Me? ...

过滤器FormAuthenticationFilter默认使用username, password和rememberMe作为参数名。可通过如下设置重新定义参数名:
[main]
...
authc.loginUrl = /whatever.jsp
authc.usernameParam = somethingOtherThanUsername
authc.passwordParam = somethingOtherThanPassword
authc.rememberMeParam = somethingOtherThanRememberMe
...


6.3 Cookie configuration
可以通过RememberMeManager设置cookie相关的属性:
[main]
...

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



6.4 Custom RememberMeManager
如果默认的RememberMeManager不能满足你的需求,可以自定义RememberMeManager 实现:
[main]
...
rememberMeManager = com.my.impl.RememberMeManager
securityManager.rememberMeManager = $rememberMeManager


7. JSP / GSP Tag Library
Shiro提供了JSP/GSP标签库,可以根据当前Subject的状态,控制JSP,JSTL,GSP的内容输出。

7.1 Tag Library Configuration
  在页面中引入如下配置即可(TLD文件绑定在shiro-web.jar的META-INF/shiro.tld里):
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>


7.2 The guest tag
guest标签中的内容只能被Guest用户所看到。(guest用户指没有登录或没有从Remember Me服务中获取标识身份的Subject)。

    Hi there!  Please Login or Signup today!



7.3 The user tag
user标签和guest标签正好相反。user标签中的内容必须为登录或者从Remember Me服务中获取标识的用户所看到。需要注意,它和authenticated有语义上的不同。

    Welcome back John!  Not John? Click here to login.



7.4 The authenticated tag
authenticated标签表示当前的用户必须被本次会话所认证过。

    Update your contact information.



7.5 The notAuthenticated tag
notAuthenticated标签语义正好和authenticated相反,表示当前用户还没有被当前会话所认证过:

    Please login in order to update your credit card information.



7.6 The principal tag
principal标签会输出当前用户(Subject)的标识:
Hello, , how are you today?

如果当前用户没有任何表示信息,会输出toString方法值。相当于:
Hello, <%= SecurityUtils.getSubject().getPrincipal().toString() %>, how are you today?


7.7 Typed principal
principal标签默认输出subject.getPrincipal()的值,如果你不想输出主要的标识信息,可以通过查找标识的类型,输出其他值:
User ID: 

等同于:
User ID: <%= SecurityUtils.getSubject().getPrincipals().oneByType(Integer.class).toString() %>


7.8 Principal property
如果标识的信息不单单是字符串,而是一个引用类型,又想使用引用类型的属性,可使用property属性:
Hello, , how are you today?

等同于:
Hello, <%= SecurityUtils.getSubject().getPrincipal().getFirstName().toString() %>, how are you today?

还可以和type组合起来使用:
Hello, , how are you today?

等同于:
Hello, <%= SecurityUtils.getSubject().getPrincipals().oneByType(com.foo.User.class).getFirstName().toString() %>, how are you today?

7.9 The hasRole tag
hasRole标签表示当前的用户必须具有指定的角色:

    Administer the system



7.10 The lacksRole tag
和hasRole相反,lacksRole标签表示当前用户不具有指定的角色:

    Sorry, you are not allowed to administer the system.



7.11 The hasAnyRole tag
hasAnyRole标签表示,当前用户必须具有任意角色列表中的一项。角色列表使用逗号分隔:

    You are either a developer, project manager, or administrator.



7.12 The hasPermission tag
hasPermission标签表示当前用户必须具有指定的权限:

    Create a new User



7.13 The lacksPermission tag
和hasPermission相反,lacksPermission标签表示,当前用户不具有指定的权限:

    Sorry, you are not allowed to delete user accounts.

你可能感兴趣的:(Shiro,Security,Authentication,Authorization)