ฉันได้รับการทำงานโดยใช้คำตอบจาก ลิงค์ @John และ @Arpad และ @RobWinchลิงก์
ฉันใช้ Spring Security 3.2.9 และ jQuery 1.10.2
ขยายคลาสของ Spring เพื่อให้เกิดการตอบสนอง 4XX จากคำขอ AJAX เท่านั้น:
public class CustomLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
public CustomLoginUrlAuthenticationEntryPoint(final String loginFormUrl) {
super(loginFormUrl);
}
// For AJAX requests for user that isn't logged in, need to return 403 status.
// For normal requests, Spring does a (302) redirect to login.jsp which the browser handles normally.
@Override
public void commence(final HttpServletRequest request,
final HttpServletResponse response,
final AuthenticationException authException)
throws IOException, ServletException {
if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
} else {
super.commence(request, response, authException);
}
}
}
ApplicationContext-security.xml
<security:http auto-config="false" use-expressions="true" entry-point-ref="customAuthEntryPoint" >
<security:form-login login-page='/login.jsp' default-target-url='/index.jsp'
authentication-failure-url="/login.jsp?error=true"
/>
<security:access-denied-handler error-page="/errorPage.jsp"/>
<security:logout logout-success-url="/login.jsp?logout" />
...
<bean id="customAuthEntryPoint" class="com.myapp.utils.CustomLoginUrlAuthenticationEntryPoint" scope="singleton">
<constructor-arg value="/login.jsp" />
</bean>
...
<bean id="requestCache" class="org.springframework.security.web.savedrequest.HttpSessionRequestCache">
<property name="requestMatcher">
<bean class="org.springframework.security.web.util.matcher.NegatedRequestMatcher">
<constructor-arg>
<bean class="org.springframework.security.web.util.matcher.MediaTypeRequestMatcher">
<constructor-arg>
<bean class="org.springframework.web.accept.HeaderContentNegotiationStrategy"/>
</constructor-arg>
<constructor-arg value="#{T(org.springframework.http.MediaType).APPLICATION_JSON}"/>
<property name="useEquals" value="true"/>
</bean>
</constructor-arg>
</bean>
</property>
</bean>
ใน JSP ของฉันเพิ่มตัวจัดการข้อผิดพลาด AJAX ทั่วโลกตามที่แสดงไว้ที่นี่
$( document ).ajaxError(function( event, jqxhr, settings, thrownError ) {
if ( jqxhr.status === 403 ) {
window.location = "login.jsp";
} else {
if(thrownError != null) {
alert(thrownError);
} else {
alert("error");
}
}
});
และลบตัวจัดการข้อผิดพลาดที่มีอยู่ออกจากการโทร AJAX ในหน้า JSP:
var str = $("#viewForm").serialize();
$.ajax({
url: "get_mongoDB_doc_versions.do",
type: "post",
data: str,
cache: false,
async: false,
dataType: "json",
success: function(data) { ... },
// error: function (jqXHR, textStatus, errorStr) {
// if(textStatus != null)
// alert(textStatus);
// else if(errorStr != null)
// alert(errorStr);
// else
// alert("error");
// }
});
ฉันหวังว่ามันจะช่วยผู้อื่น
Update1
ฉันพบว่าฉันจำเป็นต้องเพิ่มตัวเลือก (always-use-default-target = "true") ในการกำหนดค่าแบบฟอร์มการเข้าสู่ระบบ สิ่งนี้จำเป็นเนื่องจากหลังจากที่คำขอ AJAX ถูกเปลี่ยนเส้นทางไปยังหน้าเข้าสู่ระบบ (เนื่องจากเซสชันหมดอายุ) Spring จะจดจำคำขอ AJAX ก่อนหน้าและเปลี่ยนเส้นทางอัตโนมัติไปยังหน้าหลังจากเข้าสู่ระบบ สิ่งนี้ทำให้ JSON ที่ส่งคืนถูกแสดงบนหน้าเบราว์เซอร์ แน่นอนไม่ใช่สิ่งที่ฉันต้องการ
Update2
แทนที่จะใช้always-use-default-target="true"
ให้ใช้ @RobWinch ตัวอย่างของการบล็อกคำขอ AJAX จาก requstCache วิธีนี้ช่วยให้ลิงก์ปกติสามารถเปลี่ยนเส้นทางไปยังเป้าหมายดั้งเดิมของพวกเขาหลังจากเข้าสู่ระบบ แต่ AJAX ไปที่หน้าแรกหลังจากเข้าสู่ระบบ