我正在试验Spring安全性,我遇到了一个问题,我现在几乎无法解决。我的默认/登录URL的登录表单工作正常,csrf已启用。调用 MyAuthenticationSuccessHandler 中的 onAuthenticationSuccess 方法,并在成功登录后重定向到所需的页面。我的问题涉及/注销URL。我搜索了许多页面寻求解决方案,但无法找到合适的答案。当我试图通过header.jsp HTTP状态405中的/ logout URL注销时?显示不允许的方法页面,消息为请求方法' POST'不支持。我是通过POST
<form id="logoutForm" action="${pageContext.request.contextPath}/logout" method="POST" >
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
onLogoutSuccess 方法并注销用户,但重定向在/ logout URL上停止,并显示该405错误页面。它无法达到 MyLogoutSuccessHandler 中指定的/loginController/showLogout
重定向。我无法弄清楚搞砸了什么
这是我的代码:
安全-context.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:security="http://www.springframework.org/schema/security"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
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-4.3.xsd">
<jee:jndi-lookup jndi-name="jdbc/spring" id="dataSource"
expected-type="javax.sql.DataSource">
</jee:jndi-lookup>
<bean id="activeUserStore" class="com.springtutorial.authentication.ActiveUserStore" />
<bean id="myAuthenticationSuccessHandler"
class="com.springtutorial.authentication.MyAuthenticationSuccessHandler">
<property name="activeUserStore" ref="activeUserStore"></property>
</bean>
<bean id="myLogoutSuccessHandler"
class="com.springtutorial.authentication.MyLogoutSuccessHandler" />
<security:authentication-manager>
<security:authentication-provider >
<security:jdbc-user-service
data-source-ref="dataSource"
users-by-username-query="select username, password, enabled from simple_users where binary username = ?"
authorities-by-username-query="select username, role from authorities where binary username = ?" />
<security:password-encoder ref="passwordEncoder"></security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<security:http use-expressions="true">
<security:intercept-url pattern="/loggedUsers"
access="hasRole('ROLE_ADMIN')" />
<security:intercept-url pattern="/adminPage"
access="hasRole('ROLE_ADMIN')" />
<security:intercept-url pattern="/offerController/processCreateOfferForm"
access="isAuthenticated()" />
<security:intercept-url pattern="/offerController/showCreateOfferForm"
access="isAuthenticated()" />
<security:intercept-url pattern="/offerController/offerCreated"
access="isAuthenticated()" />
<security:intercept-url pattern="/" access="permitAll" />
<security:intercept-url pattern="/showAccessDenied"
access="permitAll" />
<security:intercept-url pattern="/loginController/showRegisterUserForm"
access="permitAll" />
<security:intercept-url pattern="/loginController/processRegisterUserForm"
access="permitAll" />
<security:intercept-url pattern="/loginController/userRegistered"
access="permitAll" />
<security:intercept-url pattern="/loginController/showLoginForm"
access="permitAll" />
<security:intercept-url pattern="/loginController/showLogout"
access="permitAll" />
<security:intercept-url pattern="/resources/**"
access="permitAll" />
<security:intercept-url pattern="/offerController/showOffers"
access="permitAll" />
<security:intercept-url pattern="/**" access="denyAll" />
<security:form-login login-page="/loginController/showLoginForm"
authentication-failure-url="/loginController/showLoginForm?error=true"
authentication-success-handler-ref="myAuthenticationSuccessHandler" />
<security:logout invalidate-session="true"
success-handler-ref="myLogoutSuccessHandler" />
<security:access-denied-handler error-page="/showAccessDenied" />
<security:remember-me key="offersAppKey" />
<security:csrf />
</security:http>
<bean id="passwordEncoder"
class="org.springframework.security.crypto.password.StandardPasswordEncoder">
</bean>
我正在使用apache tiles 3进行查看,并且我在loginForm.jsp磁贴中重定向到默认/登录URL: 的 loginForm.jsp中
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<script type="text/javascript">
$(document).ready(function() {
document.username.focus()
});
</script>
<h3>My Login</h3>
<c:if test="${param.error}">
<p class="errors">Login failed. Username or password are wrong.</p>
</c:if>
<form action='${pageContext.request.contextPath}/login' method='POST'>
<table>
<tr>
<td>User:</td>
<td><input type='text' id='username' name='username' ></td>
</tr>
<tr>
<td>Password:</td>
<td><input type='password' name='password' /></td>
</tr>
<tr>
<td>Remember me:</td>
<td><input type='checkbox' name='remember-me' checked="checked" /></td>
</tr>
<tr>
<td colspan='2'><input name="submit" type="submit"
value="Login" /></td>
</tr>
<tr>
<td><input name="_csrf" type="hidden"
value="${_csrf.token}" /></td>
</tr>
</table>
</form>
<p><a href="<c:url value="showRegisterUserForm"/>">Create new User</a></p>
并重定向到header.jsp tile中的default / logout URL:
header.jsp中
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="sec"
uri="http://www.springframework.org/security/tags"%>
<a class="title"
href="${pageContext.request.contextPath}/">Offers</a>
<sec:authorize access="!isAuthenticated()">
<a class="login"
href="${pageContext.request.contextPath}/loginController/showLoginForm">Login</a>
</sec:authorize>
<sec:authorize access="isAuthenticated()">
<!-- <a class="login" href="${pageContext.request.contextPath}/logout">Logout</a> -->
<a class="login" id="logoutLink" href="#">Logout</a>
<form id="logoutForm" action="${pageContext.request.contextPath}/logout" method="POST" >
<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />
</form>
</sec:authorize>
<script type="text/javascript">
$(document).ready(function() {
$('#logoutLink').click(function() {
$('#logoutForm').submit();
});
});
</script>
这些是 AuthenticationSuccessHandler 和 LogoutSuccessHandler 的实现:
MyAuthenticationSuccessHandler
public class MyAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
@Autowired
private ActiveUserStore activeUserStore;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(request, response);
HttpSession session = request.getSession(false);
if (session != null) {
LoggedUser user = new LoggedUser(authentication.getName(), activeUserStore);
session.setAttribute("user", user);
}
if (savedRequest == null) {
getRedirectStrategy().sendRedirect(request, response, "/");
} else {
String targetUrl = savedRequest.getRedirectUrl();
getRedirectStrategy().sendRedirect(request, response, targetUrl);
}
}
public ActiveUserStore getActiveUserStore() {
return activeUserStore;
}
public void setActiveUserStore(ActiveUserStore activeUserStore) {
this.activeUserStore = activeUserStore;
}
}
MyLogoutSuccessHandler
public class MyLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
System.out.println("co jest");
HttpSession session = request.getSession();
if (session != null) {
session.removeAttribute("user");
}
String URL = request.getContextPath() + "/loginController/showLogout";
getRedirectStrategy().sendRedirect(request, response, URL);
}
}
我实现了这些,因为我想跟踪登录的用户:)