Last Modified 2021.11.29

Migrating to Spring Security 4

Modify pom.xml as follows.

pom.xml
<properties>
  <spring.version>5.3.13</spring.version>
  <spring.security.version>5.6.0</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 the project and rerunning Tomcat, go to the login page and try to log in. A blank screen is displayed, and there are no log messages about it. The cause of the blank screen is that the CSRF protection in Spring Security 4 is working. Spring Security 4 enables this feature by default. So, to migrate from Spring Security 3 to 4, you must include the CSRF token in all PATCH, POST, PUT and DELETE requests in your project.

Open the login.jsp file and add the following to the form:

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

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

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

login-processing-url

/j_spring_security_check --> /login (of POST method)

username-parameter

j_username --> username

password-parameter

j_password --> password

authentication-failure-url

/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, and the default value of the authentication-failure-url attribute is /login?error=1. If you omit these attributes from the configuration file, Spring Security uses these default values.

To use a custom login page, you must specify the login-page and the authentication-failure-url attributes in the security configuration file, and then also add the following:

<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 that you can omit it like below.

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

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 the project and rerun Tomcat. Try to log in and log out.

When you log out, you will see a blank screen again because the default value of the logout-url attribute is changed from /j_spring_security_logout to /logout of POST method.

Open the header.jsp file and modify the code of the logout button between <head> and </head> by referring to the following.

<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 all JSP page that shows the screen.

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

How to add CSRF token parameter when uploading files

When uploading attachments in a new post, you need to include the CSRF token in the query string even if you use Springform tags.

Open the write.jsp and modify.jsp files and delete the <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> in both files.

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