Spring security深入使用(2)
通过ACL的授权
通过‹http›的‹intercept-url›进行配置:
<sec:http access-decision-manager-ref="accessDecisionManager">
<sec:intercept-url pattern="/app/messageList*" access="ROLE_USER,ROLE_ANONYMOUS"/>
<sec:intercept-url pattern="/app/messagePost*" access="ROLE_USER"/>
<sec:intercept-url pattern="/app/messageDelete*" access="ROLE_ADMIN"/>
<sec:intercept-url pattern="/app/*" access="ROLE_USER"/>
<form-login login-page="/login.jsp" default-target-url="/app/messagePost"
authentication-failure-url="/login.jsp?error=true"/>
<!-- Other settings -->
</sec:http>
每个 intercept-url 规定了一个 url模式和角色,具有这个角色的用户可以访问这些URL。注意url-pattern总是以 ‘*’结束,如果 ‘*’ 没有规定,提供黑客在url中提供一些参数绕过安全机制。
Spring将这些URL拦截到FilterSecurityInterceptor. 下面是没有使用‹intercept-url›:另外一种类似配置。
<sec:custom-filter position="FILTER_SECURITY_INTERCEPTOR" ref="filterSecurityInterceptor" />
<bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="securityMetadataSource">
<sec:filter-security-metadata-source lowercase-comparisons="true" request-matcher="ant" use-expressions="true">
<sec:intercept-url pattern="/app/messageList*" access="ROLE_USER,ROLE_ANONYMOUS"/>
<sec:intercept-url pattern="/app/messagePost*" access="ROLE_USER"/>
<sec:intercept-url pattern="/app/messageDelete*" access="ROLE_ADMIN"/>
<sec:intercept-url pattern="/app/*" access="ROLE_USER"/>
</sec:filter-security-metadata-source>
</property>
</bean>
从上面的代码可以看出,匿名用户只能访问messageList的页面,其他页面必须登录。
如果你仔细观察的bean声明,有一个属性'的AccessDecisionManager “ 。这样做的目的是什么?
这个bean这实际上实现访问控制决策。它有实现AccessDecisionManager接口。 Spring提供了三个内置的访问决策管理。
在了解访问决策管理器是如何工作之前,我们需要知道AccessDecisionVoter是什么。AccessDecisionManager实际上是由一个或多个决定是否访问的投票者的组合体。这个组合封装了允许/拒绝/放弃观看资源的用户逻辑。投票者决定结果是通过ACCESS_GRANTED , ACCESS_DENIED和ACCESS_ABSTAIN中的AccessDecisionVoter接口中定义的常量字段来表示。我们可以定义自定义访问决策,并注入到我们的访问决策管理器中。
看看内置决策管理者:
AffirmativeBased :至少一个投票者必须决定授予访问权限
ConsensusBased :多数投票者必须授予访问权限
UnanimousBased :所有投票者都必须投票或放弃投票授予访问权限(无投票表决拒绝访问)
默认情况下, AffirmativeBased访问决策管理器将由两个投票者初始化:RoleVoter和AuthenticatedVoter 。
如果用户具有访问资源的角色,RoleVoter授权访问,角色必须有“ ROLE_ ”前缀,下面我们看到也可以定制其他前缀。
AuthenticatedVoter是在用户被验证是授权访问,接受的身份验证级别有:IS_AUTHENTICATED_FULLY , IS_AUTHENTICATED_REMEMBERED和IS_AUTHENTICATED_ANONYMOUSLY
下面展示假设我们要定义一个自定义的投票者,并把它添加到访问决策管理器:
<sec:http access-decision-manager-ref="accessDecisionManager" auto-config="true">
<!-- filters declaration go here-->
</sec:http>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<property name="decisionVoters">
<list>
<bean class="org.springframework.security.access.vote.RoleVoter">
<!-- Customize the prefix-->
<property name="rolePrefix" value="ROLE_"/>
</bean>
<bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
<bean class="com.pramati.security.voters.CustomVoter"/>
</list>
</property>
</bean>
登录退出
登录退出配置如下:
<sec:http>
<!-- Other filter declarations here -->
<sec:logout />
</sec:http>
缺省登出页面的URL是/j_spring_security_logout,可以规定 logout-url attribute.优化这个URL.
退出成功后,缺省是根路径,通过下面可以指定退出成功后的URL:
<sec:logout logout-url="/j_logMeOut" logout-success-url="/app/messageList"/>
如果你想在登陆页面不是默认的,而是一个特定的在不同的场景不同URL,那么我们必须实现LogoutSuccessHandler并提供了一个参考<logout>元素
<sec:logout logout-url="/j_logMeOut" success-handler-ref="customLogoutSuccessHandler"/>
然后定义Bean:
<sec:custom-filter position="LOGOUT_FILTER" ref="logoutFilter" />
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="/pages/Security/logout.html" />
<constructor-arg>
<list>
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
<property name="filterProcessesUrl" value="/j_logMeOut"/>
</bean>
匿名登录
缺省Spring创建anonymous角色。当你规定角色是ROLE_ANONYMOUS’ 或‘IS_AUTHENTICATED_ANONYMOUSLY’, 任何人都可以访问资源。
在AffirmativedBased 访问控制器中,RoleVoter看到‘ROLE_ANONYMOUS’设置就授权访问,类似AuthenticatedVoter 看到‘IS_AUTHENTICATED_ANONYMOUSLY’.授权访问。
假设你要分配给匿名用户不同的角色名,则可以覆盖默认的配置如下:
<sec:http>
<sec:intercept-url pattern="/login.jsp*" filters="none"/>
<sec:intercept-url pattern="/*" access="ROLE_USER"/>
<!-- Defines a custom role in place of ROLE_ANONYMOUS.
ROLE_ANONYMOUS will no more work, use ROLE_GUEST instead of it-->
<sec:anonymous username="guest" granted-authority="ROLE_GUEST" />
</sec:http>
<p style="text-align: justify;">Here is the how the underlying filter can be defined if you don't want to use ?anonymous? element:</p>
1
<sec:custom-filter position="ANONYMOUS_FILTER" ref="anonymousFilter" />
<bean id="anonymousFilter" class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter" >
<property name="userAttribute" value="ROLE_GUEST" />
</bean>