การเข้าสู่ระบบและออกจากระบบความปลอดภัยของ Spring

ฉันต้องการสร้างเว็บแอปพลิเคชันโดยใช้ระบบรักษาความปลอดภัยแบบสปริง แต่ฉันรู้สึกว่ามีบางอย่างผิดปกติหรือขาดหายไป

นี่คือรหัสของฉัน:

ความปลอดภัย.xml:

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/security
       http://www.springframework.org/schema/security/spring-security.xsd">

<http use-expressions="true" disable-url-rewriting="true">
    <intercept-url pattern="/index.htm" access="hasRole('ROLE_ADMIN')" />
    <form-login login-processing-url="/login" login-page="/login.htm"
        username-parameter="userName" password-parameter="password"
        default-target-url="/index.htm" always-use-default-target="true"
        authentication-failure-url="/login.htm?auth=fail" />
    <logout logout-url="/logout.htm" logout-success-url="/login?out=1"
        delete-cookies="JSESSIONID" invalidate-session="true" />
</http>

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="drs" password="123456" authorities="ROLE_ADMIN" />
            <user name="dr" password="123456" authorities="ROLE_USER" />
        </user-service>
    </authentication-provider>
</authentication-manager>
</beans:beans>

ตัวควบคุม:

@Controller
public class SecurityController {
    @RequestMapping(value = "/logout.htm", method = RequestMethod.GET)
    public String logoutPage() {
        return "logoutPage";
    }

    @RequestMapping(value = "/login.htm", method = RequestMethod.GET)
    public String login() {
        return "loginPage";
    }
}

เข้าสู่ระบบ.jsp:

<form:form action="${pageContext.request.contextPath}/login" method="POST">
    <c:if test="${not empty param.err}">
        <div>
            <c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" />
        </div>
    </c:if>
    <c:if test="${not empty param.out}">
        <div>You've logged out successfully.</div>
    </c:if>
    <c:if test="${not empty param.time}">
        <div>You've been logged out due to inactivity.</div>
    </c:if>

    Username:<br>
    <input type="text" name="userName" value="" />
    <br>
    <br> Password:<br>
    <input type="password" name="password" value="" />
    <input value="Login" name="submit" type="submit" />
</form:form>

logout.jsp:

<a href="/th${pageContext.request.contextPath}/login.htm">Login</a>

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

และอีกปัญหาหนึ่งที่ฉันคิดไม่ออก เมื่อฉันเปลี่ยนแบบฟอร์มการเข้าสู่ระบบ:

<form:form action="${pageContext.request.contextPath}/login" method="POST">

to:

<form name='loginform' action="<c:url value='j_spring_security_check' />" method='POST'>

ฉันได้รับข้อผิดพลาด:

สถานะ HTTP 404 - /Dronomy_2.1/j_spring_security_check

ใครสามารถช่วยฉันได้บ้าง?


person Drastaro    schedule 16.07.2015    source แหล่งที่มา
comment
คุณจะไม่ไปที่ /logout.htm เมื่อคลิกลิงก์ของคุณ โดยพื้นฐานแล้วคุณจะไม่ออกจากระบบเลย คุณสมบัติ login-processing-url ของคุณตั้งค่าเป็น /login ดังนั้นเมื่อส่งแบบฟอร์ม คุณจะต้องส่งไปที่ /login   -  person M. Deinum    schedule 16.07.2015


คำตอบ (3)


ในแง่ของการออกจากระบบโดยเปิดใช้งาน CSRF ตำแหน่งสำคัญสองตำแหน่งในโค้ดของคุณคือ:

logout-url="/logout.htm"

และ

@RequestMapping(value = "/logout.htm", method = RequestMethod.GET)

ฉันเดาว่าคุณไม่จำเป็นต้องจัดเตรียมหน้าออกจากระบบด้วยตัวเอง ในการออกจากระบบ คุณต้องมีเบราว์เซอร์ของผู้ใช้ทำการ POST ไปที่ /logout.htm ในโพสต์นี้ คุณต้องรวมค่า csrf ของคุณด้วย โพสต์นี้ส่งไปยังจุดสิ้นสุดความปลอดภัยของสปริงที่คุณกำหนดค่าด้วย logout-url="/logout.htm" และไม่ใช่การออกจากระบบในคอนโทรลเลอร์ของคุณ

เอกสารประกอบของ Spring มีตัวเลือก 2-3 ตัวเลือกเกี่ยวกับวิธีการดำเนินการนี้ วิธีหนึ่งคือการรวมแบบฟอร์มไว้ในเพจทั้งหมดที่ผู้ใช้สามารถออกจากระบบได้ และส่งแบบฟอร์มด้วย Javascript เมื่อผู้ใช้คลิกที่ลิงก์เมนูออกจากระบบ

หากคุณทำเช่นนี้ คุณสามารถลบการแมปคำขอที่ฉันระบุไว้ข้างต้นได้

person geoff.weatherall    schedule 18.07.2015

ฉันเพิ่งเปลี่ยน security.xml เป็น

<http use-expressions="true" disable-url-rewriting="true">
    <intercept-url pattern="/listUsers.htm" access="hasRole('ROLE_ADMIN')" />
    <intercept-url pattern="/play.htm" access="hasRole('ROLE_USER')" />
    <form-login login-page="/login.htm" login-processing-url="/j_spring_security_check"
        username-parameter="userName" password-parameter="password"
        default-target-url="/index.htm" always-use-default-target="true"
        authentication-failure-url="/login.htm?auth=fail" />
    <logout logout-url="/logout.htm" logout-success-url="/login.htm" />
</http>

เพิ่ม

</c:if>
                <form method="post"
                    action="<c:url value='j_spring_security_check' />">

และลบการเปลี่ยนเส้นทางเพื่อออกจากระบบออกจากคอนโทรลเลอร์ ตอนนี้ทำงานได้ดี :)

person Drastaro    schedule 18.07.2015

ใช้งานได้ดี ปัญหาเดียวคือเมื่อฉันกดออกจากระบบก็ไม่ทำอะไรเลย

คุณกำลังนำทางผู้ใช้ไปยังหน้าเข้าสู่ระบบ เซสชันไม่ถูกต้อง วัตถุ SecurityContext ไม่ได้ถูกล้าง

คุณต้องใช้ spring security /j_spring_security_logout เพื่อออกจากระบบผู้ใช้

<a href="/th/j_spring_security_logout">LogOut</a>

ลองดูตัวอย่างนี้

สำหรับแบบฟอร์มเข้าสู่ระบบของคุณลอง

<form name='loginform' action="<c:url value='/j_spring_security_check' />" method='POST'>

ข้อผิดพลาด 404 เกิดขึ้นโดยทั่วไปเกิดขึ้นเนื่องจากการคำนวณเส้นทางบริบท

person underdog    schedule 16.07.2015
comment
ใช่และไม่. เขากำหนดค่า URL ใหม่เพื่อไม่ให้ใช้ URL เริ่มต้นอีกต่อไป - person M. Deinum; 16.07.2015
comment
Deinum ฉันจำปัญหาได้ไม่ชัดเจน เกิดขึ้นกับโค้ดของฉัน การแก้ไขคือเส้นทางบริบท ดังนั้นเพิ่งเขียนไว้ในคำตอบ :) - person underdog; 16.07.2015
comment
ฉันเห็น. แต่ฉันใช้แบบฟอร์มของคุณ ฉันได้รับข้อผิดพลาดโทเค็น csrf: สถานะ HTTP 403 - ไม่พบโทเค็น CSRF ที่คาดหวัง เซสชั่นของคุณหมดอายุแล้วหรือยัง? และเมื่อฉันกดปุ่มออกจากระบบ ฉันจะได้รับลิงก์นี้เท่านั้น: localhost:8080/j_spring_security_logout - person Drastaro; 16.07.2015