对于web应用,Shiro提供了认证和授权的过滤器实现。
2. Architecture
a. ServletContextSupport
提供了对ServletContext访问的支持。
b. AbstractFilter
提供了对过滤器初始化的配置。如果想在过滤器初始化时添加逻辑,可通过覆写onFilterConfigSet方法。
c. NameableFilter
提供了重命名过滤器的单一功能。过滤器默认的名字为web.xml中配置的filter-name,可通过NameableFilter的name属性设置一个新的名字。
d. OncePerRequestFilter
每次请求,过滤器需要依次执行,OncePerRequestFilter保证了每次请求时,每个过滤器只执行一次。实际的业务逻辑,由子类通过doFilterInternal方法实现。
e. AdviceFilter
覆写了OncePerRequestFilter的doFilterInternal方法,将过滤操作细化为前置处理,后置处理以及清理操作。只有前置方法preHandle返回true时,才会调用下一个过滤器。
f. PathMatchingFilter
支持Ant风格路径匹配。如果请求的路劲与配置的路径匹配,由onPreHandle方法决定该请求将如何处理。对于过滤器AnonymousFilter的实现,onPreHandle方法总是返回true。对于过滤器AccessControlFilter,需要由isAccessAllowed和onAccessDenied方法共同决定。所有的认证和授权过滤器都继承AccessControlFilter类。
3. Authentication Filters
AuthenticationFilter为所有认证过滤器的基类,默认的isAccessAllowed方法返回subject.isAuthenticated的值。也就是说,如果请求的路径配置了authc过滤器,需要当前的subject被认证过。如果当前的subject没有被认证过,不同的实现,执行的操作有所不同。BasicHttpAuthenticationFilter实现会根据请求的头信息自动执行一次认证操作,如果认证失败,请求返回401代码。FormAuthenticationFilter实现会根据当前的请求路径与登陆路径匹配,如果为登陆请求,尝试执行一次认证操作,如果不为登陆请求,请求调转到登陆页。
3.1 AnonymousFilter
AnonymousFilter主要用于那些不需要认证即可访问的资源。
[urls] /user/signup/** = anon /user/** = authc
对于/user/signup,任何用户都可以访问。对于/user/,需要当前的subject已认证过。
3.2 UserFilter
如果配置了UserFilter,表示请求的Subject已认证过或被"remember me"记忆:
[urls] /news/**=user
对于/news/下的所有资源,只要用户登录过即可访问。
3.3 FormAuthenticationFilter
FormAuthenticationFilter需要当前的Subject必须被认证过,否则流程将跳转到设置的登陆url(通过setLoginUrl方法)。
[urls] /news/**=authc
3.4 BasicHttpAuthenticationFilter
如果请求的Subject.isAuthenticated方法返回false,BasicHttpAuthenticationFilter将通过HTTP基础认证方式进行认证(关于HTTP基础认证,请查阅相关资料):
[urls] /news/**=authcBasic
如果请求/news/,程序会执行Subject.isAuthenticated方法,如果返回false,执行HTTP基础认证。
4. Authorization Filters
AuthorizationFilter为所有授权过滤器的基类。默认的onAccessDenied方法中逻辑为,如果当前的Subject没有绑定任何标识信息,将请求转向登陆页面。如果Subject绑定了标识信息并且配置了unauthorizedUrl,请求将转向unauthorizedUrl,否则返回401代码。
4.1 PermissionsAuthorizationFilter
常用的AuthorizationFilter实现为PermissionsAuthorizationFilter,支持以权限的形式配置资源:
[urls] /system/getUsers=perms[0]
如果请求的路径为/system/getUsers,需要当前的Subject具有权限"0"(调用subject的isPermitted或isPermittedAll方法),才允许访问资源,否则不允许访问。
4.2 RolesAuthorizationFilter
RolesAuthorizationFilter过滤器支持以角色的形式配置资源:
[urls] /system/getUsers=roles[admin]
如果请求的路径为/system/getUsers,只有当前的Subject具有"admin"角色(调用subject的hasAllRoles方法),才允许访问资源,否则不允许访问。
4.3 PortFilter
PortFilter支持以端口的形式配置资源:
[urls] /some/path/** = port /another/path/** = port[8080]
如果请求的端口号与配置的资源映射端口号相同,则允许对资源进行访问。否则请求将被转向为对应资源映射端口的路劲。比如:如果请求地址为/another/path/test1,端口为9090,由于/another/path/test1需要8080端口才能够访问,那么请求将会被转向:http://localhost:8080//another/path/test1,亦即被转向了正确的url路劲。
4.4 HostFilter
HostFilter支持以主机的形式控制对资源的访问,Shiro1.1还没有完全实现对这种形式的支持。其isAccessAllowed方法将返回UnsupportedOperationException异常。
4.5 SslFilter
SslFilter支持以ssl的形式配置资源:
[urls] /secure/getUser = ssl
如果要访问资源/secure/getUser,需要请求的地址相同且必须为https,端口为443才允许访问。
4.6 HttpMethodPermissionFilter
HttpMethodPermissionFilter支持以HTTP请求方法的方式配置资源。其内部将HTTP请求方法转义为对应的HTTP操作,对应关系如下:
head | read |
get | read |
put | update |
post | create |
mkcol | create |
options | read |
trace | read |
以下是一个例子:
[urls] /user/** = rest[user]
如果使用GET方法访问/user/1234,由于GET方法对应着"read"操作,最后会转义为:Subject.isPermitted("user:read")。也就是说,当前的Subject必须具有user的read权限才允许对资源的访问。如果使用POST请求/user,会转义为Subject.isPermitted("user:create"),即当前Subject必须具有user的create权限。