页面加载后清除Spring SecurityContext

时间:2014-08-11 08:59:56

标签: spring spring-security zk

我正在将ZK与Spring Security集成,到目前为止,我已经配置了后者,因此除登录页面外,所有URL都是安全的。当通过导航到不同的URL进行页面切换时,这当然可以正常工作。

但是,当我动态更改某些内容时(即通过更改ZK中Include元素的src属性),然后在该新内容的控制器内,我调用SecurityContextHolder.getContext()。getAuthentication() ,我没有获得任何类型的凭据,但是作为Authentication对象的null。我的猜测是调试中这一行指出了罪魁祸首:

SecurityContextPersistenceFilter:97 - SecurityContextHolder now cleared, as request processing completed

问题是我从使用基本身份验证的REST Web服务获取所有数据,因此我需要在每个请求上获取用户的凭据,包括动态加载内容的凭据。

我已经看到我可以将我的SecurityContext级别设置为全局,但我也读过它是不好的做法,它可能会导致用户获取其他人的凭据。

PS:有趣的是,如果不是:

  Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

我用:

Authentication authentication = ((org.springframework.security.core.context.SecurityContextImpl)session().getAttribute("SPRING_SECURITY_CONTEXT")).getAuthentication();

我的身份验证对象实际上就在那里。所以我必须在这里找到一些东西。

编辑:这是我的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>XESAC</display-name>


    <!-- Spring Security -->
    <!-- A servlet filter capturing every user requests and sending them to 
        the configured security filters to make sure access is authorized. -->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>



    <context-param>
        <param-name>webAppRootKey</param-name>
        <param-value>sigur-ui.root</param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/spring/appcontext-spring.xml,classpath:/spring/appcontext-security.xml</param-value>
    </context-param>


    <listener>
        <description>Spring Loader</description>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <description>Used to cleanup when a session is destroyed</description>
        <display-name>ZK Session Cleaner</display-name>
        <listener-class>org.zkoss.zk.ui.http.HttpSessionListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>



    <servlet>
        <description>
            The ZK loader for ZUML pages</description>
        <servlet-name>zkLoader</servlet-name>
        <servlet-class>org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>
        <init-param>
            <param-name>update-uri</param-name>
            <param-value>/zkau</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
        <description>The asynchronous update engine for ZK</description>
        <servlet-name>auEngine</servlet-name>
        <servlet-class>org.zkoss.zk.au.http.DHtmlUpdateServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>zkLoader</servlet-name>
        <url-pattern>*.zul</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>zkLoader</servlet-name>
        <url-pattern>*.zhtml</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>auEngine</servlet-name>
        <url-pattern>/zkau/*</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>dspLoader</servlet-name>
        <servlet-class>org.zkoss.web.servlet.dsp.InterpreterServlet</servlet-class>
        <init-param>
            <param-name>class-resource</param-name>
            <param-value>true</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>dspLoader</servlet-name>
        <url-pattern>*.dsp</url-pattern>
    </servlet-mapping>



    <welcome-file-list>
        <welcome-file>index.zul</welcome-file>
    </welcome-file-list>

    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>

    <error-page>
        <exception-type>java.lang.Throwable</exception-type>
        <location>/error.zul</location>
    </error-page>
</web-app>

appcontext-security.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:zksp="http://www.zkoss.org/2008/zkspring/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security-3.1.xsd">

    <global-method-security secured-annotations="enabled" pre-post-annotations="disabled"/>

    <http pattern="/resources/**" security="none" />
    <http pattern="/zkau/**" security="none" />

    <http auto-config="true" use-expressions="true">
        <!-- En funcion del rol de cada usuario -->
        <intercept-url pattern="/login.zul" access="permitAll" />
        <intercept-url pattern="/timeout.zul" access="permitAll" />
        <intercept-url pattern="/css/**" access="permitAll" />
        <intercept-url pattern="/img/**" access="permitAll" />
        <intercept-url pattern="/**" access="isAuthenticated()" />
        <!-- Areas Patterns -->
        <form-login login-page="/login.zul" authentication-failure-url="/login.zul?login_error=1" default-target-url="/index.zul" />
        <logout logout-success-url="/login.zul" logout-url="/logout" invalidate-session="true" />
    </http>

    <!-- Autenticación mock para las pruebas -->
    <authentication-manager erase-credentials="false">
        <authentication-provider ref="myProvider" />
    </authentication-manager>

    <beans:bean id="myProvider" class="com.myapp.provider.MyProvider" />

</beans:beans>

MyProvider.java(这是我自己的一个类,它针对REST端点进行身份验证):

public class MyProvider implements AuthenticationProvider {

    @Autowired
    private IAuthenticationService authenticationService;

    @Autowired
    private HttpSession session;



    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = authentication.getCredentials().toString();
        UserDetailsDTO userDetails = authenticationService.doAuthenticate(authentication);
        if (null != userDetails && !userDetails.isAnonymous()) {
            session.setAttribute("user", userDetails);
            List<GrantedAuthority> grantedAuths = new ArrayList<>();
            //should set the roles here
            return new UsernamePasswordAuthenticationToken(userDetails, password, grantedAuths);
        }
        else {
            return null;
        }

    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }

}

2 个答案:

答案 0 :(得分:3)

在您的安全配置中,您有这一行:

<http pattern="/zkau/**" security="none" />

/zkau开头的所有网址完全绕过spring安全过滤器。如果ZK使用那些未由spring security处理的URL,则Authentication将为null。

您至少应该从appcontext-security.xml

中删除该行

答案 1 :(得分:1)

行为绝对正确。首先,REST要求无状态,因此必须协商每个请求。如果您希望对人机界面保持持久性,则必须执行以下操作:

<beans:bean id="securityContextPersistenceFilter"
    class="org.springframework.security.web.context.SecurityContextPersistenceFilter" />

但是说

<security:http pattern="/rest/**" create-session="stateless" />