Nachdem Sie mit den zahlreichen Lösungen in dieser Antwort zu kämpfen haben, versuchen Sie, etwas zum Laufen zu bringen, wenn Sie das verwenden <http>
Namespace-Konfiguration Laufen zu bringen, fand ich endlich einen Ansatz, der tatsächlich für meinen Anwendungsfall funktioniert. Ich benötige eigentlich nicht, dass Spring Security keine Sitzung startet (da ich die Sitzung in anderen Teilen der Anwendung verwende), sondern dass es sich überhaupt nicht an die Authentifizierung in der Sitzung "erinnert" (sie sollte erneut überprüft werden) jede Anfrage).
Zunächst konnte ich nicht herausfinden, wie die oben beschriebene "Null-Implementierung" -Technik durchgeführt wird. Es war nicht klar, ob Sie das securityContextRepository auf null
oder auf eine No-Op-Implementierung setzen sollen. Ersteres funktioniert nicht, weil ein NullPointerException
nach innen geworfen wird SecurityContextPersistenceFilter.doFilter()
. Bei der No-Op-Implementierung habe ich versucht, sie so einfach wie möglich zu implementieren:
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;
}
}
Dies funktioniert in meiner Anwendung nicht, da etwas Seltsames ClassCastException
mit dem response_
Typ zu tun hat .
Selbst wenn ich es geschafft habe, eine Implementierung zu finden, die funktioniert (indem ich den Kontext einfach nicht in der Sitzung speichere), gibt es immer noch das Problem, wie ich das in die von der <http>
Konfiguration erstellten Filter einfügen kann. Sie können den Filter nicht einfach an der SECURITY_CONTEXT_FILTER
Position gemäß den Dokumenten ersetzen . Der einzige Weg, wie ich mich in das einhaken konnte SecurityContextPersistenceFilter
, was unter der Decke entsteht, war, eine hässliche ApplicationContextAware
Bohne zu schreiben :
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());
}
}
}
}
}
}
}
Wie auch immer, zu der Lösung, die tatsächlich funktioniert, wenn auch sehr hackisch. Verwenden Sie einfach a Filter
, das den Sitzungseintrag löscht, nach dem HttpSessionSecurityContextRepository
gesucht wird, wenn es seine Sache macht:
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_);
}
}
Dann in der Konfiguration:
<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>