ฉันจะใช้ Spring Security โดยไม่มีเซสชันได้อย่างไร


100

ฉันกำลังสร้างเว็บแอปพลิเคชันที่มี Spring Security ซึ่งจะใช้งานได้บน Amazon EC2 และใช้ Elastic Load Balancers ของ Amazon น่าเสียดายที่ ELB ไม่รองรับเซสชันที่ติดหนึบดังนั้นฉันต้องตรวจสอบให้แน่ใจว่าแอปพลิเคชันของฉันทำงานได้อย่างถูกต้องโดยไม่มีเซสชัน

จนถึงตอนนี้ฉันได้ตั้งค่า RememberMeServices เพื่อกำหนดโทเค็นผ่านคุกกี้และมันก็ใช้ได้ดี แต่ฉันต้องการให้คุกกี้หมดอายุพร้อมกับเซสชันเบราว์เซอร์ (เช่นเมื่อเบราว์เซอร์ปิด)

ฉันต้องจินตนาการว่าฉันไม่ใช่คนแรกที่ต้องการใช้ Spring Security โดยไม่มีเซสชัน ... มีข้อเสนอแนะหรือไม่?

คำตอบ:


125

ใน Spring Security 3 ที่มีJava Configคุณสามารถใช้HttpSecurity.sessionManagement () :

@Override
protected void configure(final HttpSecurity http) throws Exception {
    http
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}

2
นี่คือคำตอบที่ถูกต้องสำหรับการกำหนดค่า Java โดยสะท้อนสิ่งที่ @sappenin ระบุไว้อย่างถูกต้องสำหรับการกำหนดค่า xml ในความคิดเห็นเกี่ยวกับคำตอบที่ยอมรับ เราใช้วิธีนี้และแน่นอนว่าแอปพลิเคชันของเราไม่มีเซสชัน
พอล

สิ่งนี้มีผลข้างเคียง คอนเทนเนอร์ Tomcat จะต่อท้าย "; jsessionid = ... " ในคำขอสำหรับรูปภาพสไตล์ชีท ฯลฯ เนื่องจาก Tomcat ไม่ต้องการเป็นคนไร้สัญชาติและ Spring Security จะบล็อกเนื้อหาเหล่านี้ในการโหลดครั้งแรกเนื่องจาก "URL มี String ที่อาจเป็นอันตราย ';' "
workerjoe

@workerjoe ดังนั้นสิ่งที่คุณพยายามจะพูดโดยการกำหนดค่า java นี้เซสชันไม่ได้ถูกสร้างขึ้นโดยการรักษาความปลอดภัยในฤดูใบไม้ผลิแทนที่จะเป็นแมวตัวผู้?
Vishwas Atrey

@VishwasAtrey ในความเข้าใจของฉัน (ซึ่งอาจจะผิด) Tomcat สร้างและดูแลเซสชัน Spring ใช้ประโยชน์จากมันโดยเพิ่มข้อมูลของตัวเอง ฉันพยายามสร้างเว็บแอปพลิเคชันไร้สัญชาติ แต่ไม่ได้ผลดังที่กล่าวไว้ข้างต้น ดูคำตอบสำหรับคำถามของฉันเองสำหรับข้อมูลเพิ่มเติม
workerjoe

28

ดูเหมือนว่าจะง่ายยิ่งขึ้นใน Spring Securitiy 3.0 หากคุณใช้การกำหนดค่าเนมสเปซคุณสามารถทำได้ดังนี้:

<http create-session="never">
  <!-- config -->
</http>

หรือคุณอาจจะกำหนดค่า SecurityContextRepository เป็นโมฆะและไม่มีอะไรจะเคยได้รับการบันทึกไว้ว่าวิธีการเช่นกัน


5
สิ่งนี้ไม่ได้ผลอย่างที่คิด แต่มีความคิดเห็นด้านล่างที่แยกความแตกต่างระหว่าง "ไม่เคย" และ "ไร้สัญชาติ" เมื่อใช้ "ไม่เคย" แอปของฉันยังคงสร้างเซสชันอยู่ เมื่อใช้ "ไร้สัญชาติ" แอปของฉันก็ไร้สัญชาติและฉันไม่จำเป็นต้องใช้การลบล้างใด ๆ ที่กล่าวถึงในคำตอบอื่น ๆ ดูปัญหา JIRA ที่นี่: jira.springsource.org/browse/SEC-1424
sappenin

27

เราทำงานในปัญหาเดียวกันนี้ (การฉีด SecurityContextRepository แบบกำหนดเองไปยัง SecurityContextPersistenceFilter) เป็นเวลา 4-5 ชั่วโมงในวันนี้ ในที่สุดเราก็คิดออก ก่อนอื่นในหัวข้อ 8.3 ของ Spring Security ref. doc มีนิยาม SecurityContextPersistenceFilter bean

<bean id="securityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
    <property name='securityContextRepository'>
        <bean class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
            <property name='allowSessionCreation' value='false' />
        </bean>
    </property>
</bean>

และหลังจากคำจำกัดความนี้มีคำอธิบายนี้: "อีกทางหนึ่งคุณสามารถจัดเตรียมอินเตอร์เฟส SecurityContextRepository แบบ null ซึ่งจะป้องกันไม่ให้จัดเก็บบริบทความปลอดภัยแม้ว่าจะมีการสร้างเซสชันแล้วในระหว่างการร้องขอก็ตาม

เราจำเป็นต้องฉีด SecurityContextRepository ที่กำหนดเองของเราลงใน SecurityContextPersistenceFilter ดังนั้นเราจึงเปลี่ยนคำจำกัดความของ bean ด้านบนด้วย im ที่กำหนดเองและใส่ลงในบริบทความปลอดภัย

เมื่อเราเรียกใช้แอปพลิเคชันเราตรวจสอบบันทึกและเห็นว่า SecurityContextPersistenceFilter ไม่ได้ใช้ im ที่กำหนดเองของเรามันกำลังใช้ HttpSessionSecurityContextRepository

หลังจากลองทำอย่างอื่นแล้วเราพบว่าเราต้องให้ SecurityContextRepository ที่กำหนดเองของเราด้วยแอตทริบิวต์ "security-context-repository-ref" ของเนมสเปซ "http" หากคุณใช้เนมสเปซ "http" และต้องการแทรกนัย SecurityContextRepository ของคุณเองให้ลองใช้แอตทริบิวต์ "security-context-repository-ref"

เมื่อใช้เนมสเปซ "http" คำจำกัดความ SecurityContextPersistenceFilter แยกกันจะถูกละเว้น ตามที่ฉันคัดลอกข้างต้นเอกสารอ้างอิง ไม่ได้ระบุว่า

โปรดแก้ไขฉันหากฉันเข้าใจผิด


ขอบคุณนี่คือข้อมูลที่มีค่า ฉันจะลองใช้ในแอปพลิเคชันของฉัน
Jeff Evans

ขอบคุณนั่นคือสิ่งที่ฉันต้องการสำหรับฤดูใบไม้ผลิ 3.0
Justin Ludwig

1
คุณค่อนข้างแม่นยำเมื่อคุณบอกว่าเนมสเปซ http ไม่อนุญาตให้ใช้ SecurityContextPersistenceFilter แบบกำหนดเองฉันใช้เวลาสองสามชั่วโมงในการดีบักเพื่อที่จะคิดออก
Jaime Hablutzel

ขอบคุณมากสำหรับการโพสต์สิ่งนี้! ฉันกำลังจะฉีกผมเล็ก ๆ ออก ฉันสงสัยว่าทำไมเมธอด setSecurityContextRepository ของ SecurityContextPersistenceFilter จึงเลิกใช้งาน (เอกสารบอกว่าให้ใช้ constructor injection ซึ่งไม่ถูกต้องเช่นกัน)
fool4jesus

10

ดูที่SecurityContextPersistenceFilterชั้นเรียน กำหนดวิธีการSecurityContextHolderเติมข้อมูล โดยค่าเริ่มต้นจะใช้HttpSessionSecurityContextRepositoryเพื่อจัดเก็บบริบทความปลอดภัยในเซสชัน http

SecurityContextRepositoryฉันได้ดำเนินการกลไกนี้ค่อนข้างง่ายด้วยการกำหนดเอง

ดูsecurityContext.xmlด้านล่าง:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:sec="http://www.springframework.org/schema/security"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">

    <context:annotation-config/>

    <sec:global-method-security secured-annotations="enabled" pre-post-annotations="enabled"/>

    <bean id="securityContextRepository" class="com.project.server.security.TokenSecurityContextRepository"/>

    <bean id="securityContextFilter" class="com.project.server.security.TokenSecurityContextPersistenceFilter">
        <property name="repository" ref="securityContextRepository"/>
    </bean>

    <bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
        <constructor-arg value="/login.jsp"/>
        <constructor-arg>
            <list>
                <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
            </list>
        </constructor-arg>
    </bean>

    <bean id="formLoginFilter"
          class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="authenticationSuccessHandler">
            <bean class="com.project.server.security.TokenAuthenticationSuccessHandler">
                <property name="defaultTargetUrl" value="/index.html"/>
                <property name="passwordExpiredUrl" value="/changePassword.jsp"/>
                <property name="alwaysUseDefaultTargetUrl" value="true"/>
            </bean>
        </property>
        <property name="authenticationFailureHandler">
            <bean class="com.project.server.modules.security.CustomUrlAuthenticationFailureHandler">
                <property name="defaultFailureUrl" value="/login.jsp?failure=1"/>
            </bean>
        </property>
        <property name="filterProcessesUrl" value="/j_spring_security_check"/>
        <property name="allowSessionCreation" value="false"/>
    </bean>

    <bean id="servletApiFilter"
          class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter"/>

    <bean id="anonFilter" class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
        <property name="key" value="ClientApplication"/>
        <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
    </bean>


    <bean id="exceptionTranslator" class="org.springframework.security.web.access.ExceptionTranslationFilter">
        <property name="authenticationEntryPoint">
            <bean class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
                <property name="loginFormUrl" value="/login.jsp"/>
            </bean>
        </property>
        <property name="accessDeniedHandler">
            <bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
                <property name="errorPage" value="/login.jsp?failure=2"/>
            </bean>
        </property>
        <property name="requestCache">
            <bean id="nullRequestCache" class="org.springframework.security.web.savedrequest.NullRequestCache"/>
        </property>
    </bean>

    <alias name="filterChainProxy" alias="springSecurityFilterChain"/>

    <bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
        <sec:filter-chain-map path-type="ant">
            <sec:filter-chain pattern="/**"
                              filters="securityContextFilter, logoutFilter, formLoginFilter,
                                        servletApiFilter, anonFilter, exceptionTranslator, filterSecurityInterceptor"/>
        </sec:filter-chain-map>
    </bean>

    <bean id="filterSecurityInterceptor"
          class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
        <property name="securityMetadataSource">
            <sec:filter-security-metadata-source use-expressions="true">
                <sec:intercept-url pattern="/staticresources/**" access="permitAll"/>
                <sec:intercept-url pattern="/index.html*" access="hasRole('USER_ROLE')"/>
                <sec:intercept-url pattern="/rpc/*" access="hasRole('USER_ROLE')"/>
                <sec:intercept-url pattern="/**" access="permitAll"/>
            </sec:filter-security-metadata-source>
        </property>
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="accessDecisionManager" ref="accessDecisionManager"/>
    </bean>

    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
        <property name="decisionVoters">
            <list>
                <bean class="org.springframework.security.access.vote.RoleVoter"/>
                <bean class="org.springframework.security.web.access.expression.WebExpressionVoter"/>
            </list>
        </property>
    </bean>

    <bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
        <property name="providers">
            <list>
                <bean name="authenticationProvider"
                      class="com.project.server.modules.security.oracle.StoredProcedureBasedAuthenticationProviderImpl">
                    <property name="dataSource" ref="serverDataSource"/>
                    <property name="userDetailsService" ref="userDetailsService"/>
                    <property name="auditLogin" value="true"/>
                    <property name="postAuthenticationChecks" ref="customPostAuthenticationChecks"/>
                </bean>
            </list>
        </property>
    </bean>

    <bean id="customPostAuthenticationChecks" class="com.project.server.modules.security.CustomPostAuthenticationChecks"/>

    <bean name="userDetailsService" class="com.project.server.modules.security.oracle.UserDetailsServiceImpl">
        <property name="dataSource" ref="serverDataSource"/>
    </bean>

</beans>

1
สวัสดี Lukas คุณสามารถให้รายละเอียดเพิ่มเติมเกี่ยวกับการใช้งานที่เก็บบริบทความปลอดภัยของคุณได้หรือไม่?
Jim Downing

1
คลาส TokenSecurityContextRepository มี HashMap <String, SecurityContext> contextMap ในวิธี loadContext () ตรวจสอบว่ามี SecurityContext สำหรับรหัสแฮชของเซสชันที่ส่งผ่านโดย requestParameter sid หรือคุกกี้หรือ requestHeader ที่กำหนดเองหรือการรวมกันข้างต้นหรือไม่ ส่งคืน SecurityContextHolder.createEmptyContext () ถ้าบริบทไม่สามารถแก้ไขได้ เมธอด saveContext ทำให้บริบทที่แก้ไขแล้วเป็น contextMap
Lukas Herman

8

จริงๆแล้วcreate-session="never"ไม่ได้หมายความว่าเป็นคนไร้สัญชาติอย่างสมบูรณ์ มีปัญหาในการจัดการปัญหา Spring Security


3

หลังจากต่อสู้กับวิธีแก้ปัญหามากมายที่โพสต์ไว้ในคำตอบนี้เพื่อพยายามหาบางสิ่งที่ใช้งานได้เมื่อใช้การกำหนดค่า<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>

เก้าปีต่อมานี่ยังคงเป็นคำตอบที่ถูกต้อง ตอนนี้เราสามารถใช้การกำหนดค่า Java แทน XML ได้แล้ว ฉันเพิ่มตัวกรองที่กำหนดเองในของฉันWebSecurityConfigurerAdapterด้วย " http.addFilterBefore(new SpringSecuritySessionDeletingFilter(), SecurityContextPersistenceFilter.class)"
workerjoe

3

หมายเหตุสั้น ๆ : มันเป็น "สร้างเซสชัน" มากกว่า "สร้างเซสชัน"

สร้างเซสชัน

ควบคุมความกระตือรือร้นที่จะสร้างเซสชัน HTTP

หากไม่ได้ตั้งค่าเริ่มต้นเป็น "ifRequired" ตัวเลือกอื่น ๆ คือ "always" และ "never"

การตั้งค่าของแอ็ตทริบิวต์นี้มีผลต่อคุณสมบัติ allowSessionCreation และ forceEagerSessionCreation ของ HttpSessionContextIntegrationFilter allowSessionCreation จะเป็นจริงเสมอเว้นแต่จะตั้งค่าแอตทริบิวต์นี้เป็น "never" forceEagerSessionCreation เป็น "เท็จ" เว้นแต่จะตั้งค่าเป็น "always"

ดังนั้นการกำหนดค่าเริ่มต้นจึงอนุญาตให้สร้างเซสชันได้ แต่ไม่บังคับ ข้อยกเว้นคือถ้าเปิดใช้งานการควบคุมเซสชันพร้อมกันเมื่อ forceEagerSessionCreation จะถูกตั้งค่าเป็นจริงไม่ว่าการตั้งค่าจะอยู่ที่นี่ การใช้ "never" จะทำให้เกิดข้อยกเว้นในระหว่างการเริ่มต้นของ HttpSessionContextIntegrationFilter

สำหรับรายละเอียดเฉพาะของการใช้งานเซสชันมีเอกสารที่ดีบางอย่างใน HttpSessionSecurityContextRepository javadoc


ทั้งหมดนี้เป็นคำตอบที่ดีมาก แต่ฉันก็เอาหัวโขกกำแพงพยายามคิดว่าจะทำยังไงให้สำเร็จเมื่อใช้องค์ประกอบ <htt <p> config แม้ว่าauto-config=falseคุณจะไม่สามารถแทนที่สิ่งที่อยู่ในSECURITY_CONTEXT_FILTERตำแหน่งด้วยตัวคุณเองได้ ฉันพยายามแฮ็กเพื่อปิดการใช้งานด้วยApplicationContextAwarebean (ใช้การสะท้อนเพื่อบังคับsecurityContextRepositoryให้ใช้งาน null ในSessionManagementFilter ) แต่ไม่มีลูกเต๋า และน่าเศร้าที่ฉันไม่สามารถเปลี่ยนไปใช้ spring-security 3.1 ปีที่จะให้create-session=statelessได้
Jeff Evans

กรุณาเยี่ยมชมเว็บไซต์นี้ให้ข้อมูลเสมอ หวังว่านี่จะช่วยคุณและคนอื่น ๆ เช่นกัน " baeldung.com/spring-security-session " • always - เซสชันจะถูกสร้างขึ้นเสมอหากไม่มีอยู่แล้ว• ifRequired - เซสชันจะถูกสร้างขึ้นเมื่อจำเป็นเท่านั้น (ค่าเริ่มต้น) • ไม่เคย - เฟรมเวิร์กจะไม่สร้างเซสชันเอง แต่จะใช้เซสชันหนึ่งหากมีอยู่แล้ว•ไร้รัฐ - Spring Security จะไม่สร้างหรือใช้
เซสชัน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.