Setelah berjuang dengan banyak solusi yang diposting dalam jawaban ini, untuk mencoba mendapatkan sesuatu yang berfungsi saat menggunakan <http>konfigurasi namespace, saya akhirnya menemukan pendekatan yang benar-benar berfungsi untuk kasus penggunaan saya. Saya sebenarnya tidak mengharuskan Spring Security tidak memulai sesi (karena saya menggunakan sesi di bagian lain aplikasi), hanya saja Spring Security tidak "mengingat" otentikasi dalam sesi sama sekali (harus diperiksa ulang setiap permintaan).
Untuk memulainya, saya tidak dapat menemukan cara untuk melakukan teknik "implementasi nol" yang dijelaskan di atas. Tidak jelas apakah Anda harus menyetel securityContextRepository ke nullatau ke implementasi tanpa operasi. Yang pertama tidak berfungsi karena a NullPointerExceptionterlempar ke dalam SecurityContextPersistenceFilter.doFilter(). Sedangkan untuk implementasi tanpa operasi, saya mencoba menerapkan dengan cara yang paling sederhana yang dapat saya bayangkan:
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;
}
}
Ini tidak berfungsi di aplikasi saya, karena ada yang aneh ClassCastExceptiondengan response_jenisnya.
Bahkan dengan asumsi saya berhasil menemukan implementasi yang berfungsi (dengan tidak menyimpan konteks dalam sesi), masih ada masalah tentang bagaimana menyuntikkannya ke dalam filter yang dibangun oleh <http>konfigurasi. Anda tidak bisa begitu saja mengganti filter pada SECURITY_CONTEXT_FILTERposisi tersebut, sesuai dengan dokumen . Satu-satunya cara saya menemukan untuk mengaitkan SecurityContextPersistenceFilteryang dibuat di bawah sampul adalah dengan menulis ApplicationContextAwarekacang jelek :
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());
}
}
}
}
}
}
}
Bagaimanapun, ke solusi yang benar-benar berfungsi, meskipun sangat hackish. Cukup gunakan Filteryang menghapus entri sesi yang HttpSessionSecurityContextRepositorydicari saat melakukan tugasnya:
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_);
}
}
Kemudian di konfigurasi:
<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>