หลังจากต่อสู้กับวิธีแก้ปัญหามากมายที่โพสต์ไว้ในคำตอบนี้เพื่อพยายามหาบางสิ่งที่ใช้งานได้เมื่อใช้การกำหนดค่า<http>
เนมสเปซในที่สุดฉันก็พบวิธีการที่ใช้งานได้จริงสำหรับกรณีการใช้งานของฉัน จริงๆแล้วฉันไม่ต้องการให้ Spring Security ไม่เริ่มเซสชัน (เพราะฉันใช้เซสชันในส่วนอื่น ๆ ของแอปพลิเคชัน) เพียงแต่ว่ามันไม่ "จำ" การรับรองความถูกต้องในเซสชันเลย (ควรตรวจสอบอีกครั้ง ทุกคำขอ).
เริ่มต้นด้วยฉันไม่สามารถหาวิธีใช้เทคนิค "การใช้งานแบบว่าง" ที่อธิบายไว้ข้างต้นได้ ไม่ชัดเจนว่าคุณควรตั้งค่า securityContextRepository เป็นnull
หรือเพื่อการใช้งานแบบไม่ใช้ระบบ อดีตไม่ทำงานเพราะได้รับโยนภายใน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());
}
}
}
}
}
}
}
อย่างไรก็ตามวิธีการแก้ปัญหาที่ใช้งานได้จริงแม้ว่าจะแฮ็คมากก็ตาม เพียงใช้สิ่งFilter
ที่ลบรายการเซสชันที่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>