I have the following Spring security configuration:
<security:http>
<security:intercept-url pattern="/**" access="ROLE_USER"/>
<security:intercept-url pattern="/auth/**" access="ROLE_ADMIN"/>
....
</security:http>
I would like to revoke "ROLE_ADMIN" authority from the user when he navigates out of "/auth/**" zone.
How can I achieve such functionality? Can I put some开发者_开发百科 kind of filter on all URLs except /auth/** which revokes Authority from the user?
Can I revoke it "on the fly"?
I would like to revoke "ROLE_ADMIN" authority from the user when he navigates out of "/auth/**" zone.
How can I achieve such functionality? Can I put some kind of filter on all URLs except /auth/** which revokes Authority from the user?
Can I revoke it "on the fly"?
I think you are misunderstanding the meaning of the intercept-url
element:
<security:intercept-url pattern="/auth/**" access="ROLE_ADMIN"/>
This does NOT say "grant the user ROLE_ADMIN
in the /auth/**
tree". It says, "a user who has ROLE_ADMIN
is allowed to access pages in the /auth/**
tree".
The idea that a user's role changes depending on what he / she is looking at is strange, to say the least.
What I'm trying to do is to validate username and password each time the user hits "/auth/**" psth.
OK, that kind of makes sense as a requirement. (Though, as a hypothetical user I would find it mysterious and/or annoying that simply navigating around the site cause me to be logged out.)
But I don't think you should do that by changing the user's role(s) on the fly. If you do that you are liable to get "Permission denied" responses instead of redirects to the login page.
What you really need to do is to put them back into the "not logged in" state. But even that can be a bit tricky. If pages in the /auth/**
tree have links to stylesheets or script files, then when the browser fetches those links the security filters are liable to think that the user has navigated out of the /auth/**
tree and log him out.
You should make custom chain configuration and insert custom filter in it. It will be something like this:
Spring security configuration file:
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<security:filter-chain-map path-type="ant">
<security:filter-chain pattern="/**" filters="
securityContextPersistenceFilter,
revokeAuthRoleFilter,
.. all the other filters here
filterSecurityInterceptor"
/>
</security:filter-chain-map>
</bean>
<!--Stores SecurityContext between requests and clears SecutityContextHolder-->
<bean id="securityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>
<bean id="revokeAuthRoleFilter" class="com.package.RevokeAuthRoleFilter">
<!--This filter is called when user is authenticated. It grants access to resources-->
<bean id="filterSecurityInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="securityMetadataSource">
<security:filter-security-metadata-source use-expressions="true">
<security:intercept-url pattern='auth/**/' access="hasAnyRole('ROLE_ADMIN')"/>
<security:intercept-url pattern='/**' access="hasAnyRole('ROLE_USER')"/>
</security:filter-security-metadata-source>
</property>
</bean>
RevokeAuthRoleFilter better to define after securityContextPersistenceFilter that populates and clears Application context. Than in your custom filter you will be able to get access to Authentication object through SecurityContextHolder and to change its authorities.
public class RevokeAuthRoleFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//check current URI or URL for specific conditions (/auth/)
String uri = reques.getRequestURI();
if(uri.contains("/auth/")) {
//get Authentication object from Security and do something with it
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
}
//pass execution to other filters in chain
filterChain.doFilter(request, response);
}
}
精彩评论