Après avoir lutté avec les nombreuses solutions publiées dans cette réponse, pour essayer de faire fonctionner quelque chose lors de l'utilisation de la <http>
configuration de l' espace de noms, j'ai finalement trouvé une approche qui fonctionne réellement pour mon cas d'utilisation. Je n'ai pas vraiment besoin que Spring Security ne démarre pas une session (parce que j'utilise session dans d'autres parties de l'application), mais simplement qu'il ne se "souvienne" pas du tout de l'authentification dans la session (il devrait être revérifié chaque demande).
Pour commencer, je n'ai pas pu comprendre comment faire la technique "d'implémentation nulle" décrite ci-dessus. Il n'était pas clair si vous êtes censé définir le securityContextRepository sur null
ou sur une implémentation sans opération. Le premier ne fonctionne pas car un NullPointerException
est jeté à l'intérieur SecurityContextPersistenceFilter.doFilter()
. En ce qui concerne l'implémentation no-op, j'ai essayé de l'implémenter de la manière la plus simple que je puisse imaginer:
public class NullSpringSecurityContextRepository implements SecurityContextRepository {
@Override
public SecurityContext loadContext(final HttpRequestResponseHolder requestResponseHolder_) {
return SecurityContextHolder.createEmptyContext();
}
@Override
public void saveContext(final SecurityContext context_, final HttpServletRequest request_,
final HttpServletResponse response_) {
}
@Override
public boolean containsContext(final HttpServletRequest request_) {
return false;
}
}
Cela ne fonctionne pas dans mon application, à cause d'un étrange ClassCastException
rapport avec le response_
type.
Même en supposant que j'ai réussi à trouver une implémentation qui fonctionne (en ne stockant simplement pas le contexte en session), il reste le problème de savoir comment l'injecter dans les filtres construits par la <http>
configuration. Vous ne pouvez pas simplement remplacer le filtre à la SECURITY_CONTEXT_FILTER
position, comme indiqué dans la documentation . Le seul moyen que j'ai trouvé pour accrocher dans le SecurityContextPersistenceFilter
qui est créé sous les couvertures était d'écrire un ApplicationContextAware
haricot laid :
public class SpringSecuritySessionDisabler implements ApplicationContextAware {
private final Logger logger = LoggerFactory.getLogger(SpringSecuritySessionDisabler.class);
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(final ApplicationContext applicationContext_) throws BeansException {
applicationContext = applicationContext_;
}
public void disableSpringSecuritySessions() {
final Map<String, FilterChainProxy> filterChainProxies = applicationContext
.getBeansOfType(FilterChainProxy.class);
for (final Entry<String, FilterChainProxy> filterChainProxyBeanEntry : filterChainProxies.entrySet()) {
for (final Entry<String, List<Filter>> filterChainMapEntry : filterChainProxyBeanEntry.getValue()
.getFilterChainMap().entrySet()) {
final List<Filter> filterList = filterChainMapEntry.getValue();
if (filterList.size() > 0) {
for (final Filter filter : filterList) {
if (filter instanceof SecurityContextPersistenceFilter) {
logger.info(
"Found SecurityContextPersistenceFilter, mapped to URL '{}' in the FilterChainProxy bean named '{}', setting its securityContextRepository to the null implementation to disable caching of authentication",
filterChainMapEntry.getKey(), filterChainProxyBeanEntry.getKey());
((SecurityContextPersistenceFilter) filter).setSecurityContextRepository(
new NullSpringSecurityContextRepository());
}
}
}
}
}
}
}
Quoi qu'il en soit, à la solution qui fonctionne réellement, bien que très hackish. Utilisez simplement un Filter
qui supprime l'entrée de session HttpSessionSecurityContextRepository
recherchée quand il fait son truc:
public class SpringSecuritySessionDeletingFilter extends GenericFilterBean implements Filter {
@Override
public void doFilter(final ServletRequest request_, final ServletResponse response_, final FilterChain chain_)
throws IOException, ServletException {
final HttpServletRequest servletRequest = (HttpServletRequest) request_;
final HttpSession session = servletRequest.getSession();
if (session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY) != null) {
session.removeAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
}
chain_.doFilter(request_, response_);
}
}
Puis dans la configuration:
<bean id="springSecuritySessionDeletingFilter"
class="SpringSecuritySessionDeletingFilter" />
<sec:http auto-config="false" create-session="never"
entry-point-ref="authEntryPoint">
<sec:intercept-url pattern="/**"
access="IS_AUTHENTICATED_REMEMBERED" />
<sec:intercept-url pattern="/static/**" filters="none" />
<sec:custom-filter ref="myLoginFilterChain"
position="FORM_LOGIN_FILTER" />
<sec:custom-filter ref="springSecuritySessionDeletingFilter"
before="SECURITY_CONTEXT_FILTER" />
</sec:http>