页面加载后正在清除Spring SecurityContext

页面加载后正在清除Spring SecurityContext,spring,spring-security,zk,Spring,Spring Security,Zk,我正在将ZK与Spring安全性集成,到目前为止,我已经配置了Spring安全性,因此除了登录页面之外,所有URL都是安全的。当通过导航到不同的URL进行页面切换时,这当然很好 但是,当我动态更改某些内容时,即通过更改ZK中包含元素的src属性,然后在该新内容的控制器内调用SecurityContextHolder.getContext.getAuthentication,我不会获得任何类型的凭据,但会获得一个空值作为身份验证对象。我的猜测是,罪魁祸首在调试中被这一行指出: SecurityCo

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

但是,当我动态更改某些内容时,即通过更改ZK中包含元素的src属性,然后在该新内容的控制器内调用SecurityContextHolder.getContext.getAuthentication,我不会获得任何类型的凭据,但会获得一个空值作为身份验证对象。我的猜测是,罪魁祸首在调试中被这一行指出:

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);
    }

}

这种行为是绝对正确的。首先,REST要求是无状态的,所以每个请求都必须经过协商。如果您希望在人机界面上持久化,则必须执行以下操作:

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

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

这种行为是绝对正确的。首先,REST要求是无状态的,所以每个请求都必须经过协商。如果您希望在人机界面上持久化,则必须执行以下操作:

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

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

在安全配置中,您有以下行:

<http pattern="/zkau/**" security="none" />
所有以/zkau开头的URL都会完全绕过spring安全过滤器。如果ZK使用那些未经spring security处理的URL,则身份验证将为空


您至少应该从appcontext security.xml中删除该行,在您的安全配置中,您有该行:

<http pattern="/zkau/**" security="none" />
所有以/zkau开头的URL都会完全绕过spring安全过滤器。如果ZK使用那些未经spring security处理的URL,则身份验证将为空


您至少应该从appcontext security.xml中删除该行,这里涉及到两层,REST层和UI层。我的问题来自UI层,其中有一个用户会话,因为它是一个web应用程序。我没有在我的REST端点上保留状态,这就是为什么我需要为我发出的每个请求获取用户和密码,并将它们放在我正在使用的基本身份验证中的身份验证头中。你的陈述想说什么?尝试上面的代码片段。如果您的REST是一个调用UI的浏览器,那么可以将其保留下来,否则不建议这样做。此外,我将清空REST服务的两个端点。一个用于浏览器,一个用于真正的REST客户端。这应该能解决你的问题。但我不明白你的答案,你建议我把这些台词放在哪里?你能详细解释一下你的答案吗?我的问题是,在从UI对REST端点的不同调用之间,我丢失了UI层上的SecurityContext。我在REST层很好,或者至少我认为我很好,如果我不好,请纠正我,我捕获每个请求,然后通过基本身份验证获取每个请求的用户信息,并且它正在工作。谁在执行REST调用?服务器是否使用JSESSIONID响应,客户端是否提供了JSESSIONID?否;UI层正在进行这些调用。对于用户来说,无论是否调用REST端点都是透明的。不,我没有使用任何sessionId信息,因为我的REST是无状态的,我不应该依赖它,对吗?该过程如下:用户加载一个需要数据访问的页面,数据取决于用户,REST请求使用授权头加上用户+密码完成;REST设置为基本身份验证服务接收请求,根据数据库检查这些凭据,并允许在REST层上使用@PreAuthorize注释访问请求的方法Im。这里涉及两层,REST层和UI层。我的问题来自UI层,其中有一个用户会话,因为它是一个web应用程序。我没有在我的REST端点上保留状态,这就是为什么我需要为我发出的每个请求获取用户和密码,并将它们放在我正在使用的基本身份验证中的身份验证头中。你的陈述想说什么?尝试上面的代码片段。如果您的REST是一个调用UI的浏览器,那么可以将其保留下来,否则不建议这样做。此外,我将清空REST服务的两个端点。一个用于浏览器,一个用于真正的REST客户端。这应该能解决你的问题。但我不明白你的答案,你建议我把这些台词放在哪里?你能扩展一下吗
你的回答解释了原因吗?我的问题是,在从UI对REST端点的不同调用之间,我丢失了UI层上的SecurityContext。我在REST层很好,或者至少我认为我很好,如果我不好,请纠正我,我捕获每个请求,然后通过基本身份验证获取每个请求的用户信息,并且它正在工作。谁在执行REST调用?服务器是否使用JSESSIONID响应,客户端是否提供了JSESSIONID?否;UI层正在进行这些调用。对于用户来说,无论是否调用REST端点都是透明的。不,我没有使用任何sessionId信息,因为我的REST是无状态的,我不应该依赖它,对吗?该过程如下:用户加载一个需要数据访问的页面,数据取决于用户,REST请求使用授权头加上用户+密码完成;REST设置为基本身份验证服务接收请求,根据数据库检查这些凭据,并允许使用REST层上的@PreAuthorize注释访问请求的方法Im。我对ZK了解不多,但这一行在appcontext-security.xm中意味着什么?如果ZK使用这些URL,它们不会被spring安全性处理,身份验证将被null处理;这不知怎么地使它工作了,我从其他地方复制的那部分代码,你能告诉我URL模式是什么吗?很遗憾,这破坏了我的登录页面,我如何修复它?我对ZK不太了解,但这一行在你的appcontext-security.xm中意味着什么?如果ZK使用这些URL,它们不会被spring安全性处理,身份验证将被null处理;这不知怎么地使它工作了,我从别处复制的那部分代码,你能告诉我URL模式是什么吗?很遗憾,这破坏了我的登录页面,我如何修复它?