我正在将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);
}
}
答案 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" />