Last Modified 2018.4.24

Migrating to Spring Security 4

Modify pom.xml as follows.

pom.xml
<properties>
	<spring.version>5.2.0.RELEASE</spring.version>
	<spring.security.version>5.2.0.RELEASE</spring.security.version>
	<jdk.version>11</jdk.version>
</properties>
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-web</artifactId>
	<version>${spring.security.version}</version>
</dependency>
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-taglibs</artifactId>
	<version>${spring.security.version}</version>
</dependency>
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-config</artifactId>
	<version>${spring.security.version}</version>
</dependency>

After building and rerunning Tomcat, go to the login page and try to log in. You will see a blank screen.
There is no error message in the log.
This is because the CSRF prevention function of Spring Security 4 is working.
Since Spring Security 4, this function is enabled by default.
Therefore, you must include the CSRF token in the PATCH, POST, PUT, and DELETE requests.
Open the /users/login.jsp file and add the following to the form:

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />

Forms that use Springform tags automatically add token parameters, so you do not need the above code.

Try to log in again.
This time you will get a 404 error that you can not find /j_spring_security_check.

Attributes of form-login with default values changed in Spring Security 4

The default value of the login-processing-url attribute is changed from /j_spring_security_check to /login of POST method.
The default value of the username-parameter attribute is changed from j_username to username.
The default value for the password-parameter attribute is changed from J_password to password.
The default value of the authentication-failure-url attribute is changed to /login?error=1.
Modify security.xml as follows.

security.xml
<form-login 
	login-page="/users/login"
	authentication-failure-url="/users/login?error=1"  
	default-target-url="/bbs/list?boardCd=chat&page=1" />

The default value of the login-page attribute is /login, the default value of the authentication-failure-url attribute is /login?error=1.
If you omit the attribute from the configuration file, it is set to the default value of the attribute.
To use the user login page and go back to the user login page when a login fails, specify the authentication-failure-url attribute in addition to the login-page attribute in the security configuration file and the following are required.

<http use-expressions="true">
    <intercept-url pattern="/users/login" access="permitAll" />

The default value of use-expressions has been changed from false to true, so it can be omitted as shown below.

<http>
    <intercept-url pattern="/users/login" access="permitAll" />

Modify login.jsp

Modify login.jsp as follows.

/users/login.jsp
<c:if test="${param.error != null }">
        <h2>Username/Password not corrrect</h2>
</c:if>
<c:url var="loginUrl" value="/login" />
<form action="${loginUrl }" method="post">
<p style="margin:0; padding: 0;">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</p>
<table>
<tr>
    <td style="width: 200px;"><spring:message code="user.email" /></td>
    <td style="width: 390px"><input type="text" name="username" style="width: 99%;" /></td>
</tr>
<tr>
    <td><spring:message code="user.password" /></td>
    <td><input type="password" name="password" style="width: 99%;" /></td>
</tr>
</table>

Build and rerun Tomcat.
Try to login and logout.
When you log out, you will see a blank screen again.
This is because the default value of the logout-url attribute is changed from /j_spring_security_logout to /logout of POST method.
Open the /inc/header.jsp file and add the following between <head> and </head>

<input type="button" value="<spring:message code="user.logout" />" id="logout" />

Add the following at the bottom of header.jsp.

<form id="logoutForm" action="/logout" method="post" style="display:none">
	<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>

<script>
$(document).ready(function() {
    $('#logout').click(function() {
        $('#logoutForm').submit();
        return false;
    });
});
</script>

Add the following code to the JSP page that shows the screen.

<script type="text/javascript" src="/js/jquery-3.2.1.min.js"></script>

Test logout again.
If the logout test succeeds, test the new write.
In the new write test, you will see a blank screen again.
When uploading attachments, you must include the CSRF token in the query string.
This is true even if you are using Springform tags.
Open the write.jsp and modify.jsp files and delete the <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />.
Modify the form's action attribute as shown below.

write.jsp
<sf:form action="write?${_csrf.parameterName}=${_csrf.token}" method="post" ...
modify.jsp
<sf:form action="modify?${_csrf.parameterName}=${_csrf.token}" method="post" ...
References