이 답변에 게시 된 수많은 솔루션으로 어려움을 겪은 후 <http>
네임 스페이스 구성을 사용할 때 작동하는 것을 시도한 후 마침내 실제로 사용 사례에 맞는 접근 방식을 찾았습니다. 나는 실제로 Spring Security가 세션을 시작하지 않을 것을 요구하지 않는다 (왜냐하면 나는 애플리케이션의 다른 부분에서 세션을 사용하기 때문이다). 단지 세션에서 인증을 전혀 "기억"하지 않는다는 것 (다시 확인되어야한다) 모든 요청).
우선 위에서 설명한 "null 구현"기법을 수행하는 방법을 알아낼 수 없었습니다. securityContextRepository를 설정해야하는지 null
또는 no-op 구현 으로 설정해야하는지 명확하지 않았습니다 . 전자 NullPointerException
는에서 던져 지기 때문에 작동하지 않습니다 SecurityContextPersistenceFilter.doFilter()
. no-op 구현의 경우 상상할 수있는 가장 간단한 방법으로 구현해 보았습니다.
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;
}
}
이것은 유형 ClassCastException
과 관련된 이상한 점 때문에 내 응용 프로그램에서 작동하지 않습니다 response_
.
(단순히 세션에 컨텍스트를 저장하지 않음으로써) 작동하는 구현을 찾았다 고 가정하더라도 <http>
구성에 의해 구축 된 필터에이를 주입하는 방법에 대한 문제가 여전히 있습니다. 문서 에 따라 단순히 SECURITY_CONTEXT_FILTER
위치 에서 필터를 교체 할 수는 없습니다 . 내가 커버 아래에 만들어진 것에 연결하는 유일한 방법 은 못생긴 콩 을 작성하는 것입니다 .SecurityContextPersistenceFilter
ApplicationContextAware
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());
}
}
}
}
}
}
}
어쨌든 실제로 작동하는 솔루션에 대해 매우 hackish하지만. 일을 할 때 찾는 Filter
세션 항목을 삭제하는 a 를 사용하십시오 HttpSessionSecurityContextRepository
.
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_);
}
}
그런 다음 구성에서 :
<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>