6.2. Spring Security Tutorial¶
Table of Contents
6.2.1. Introduction¶
6.2.1.1. Topics covered in this tutorial¶
- Basic authentication/authorization using Spring Security
- Login using the account information in the database
- How to fetch authenticated account object
6.2.1.2. Target Audience¶
- Completed implementation of Tutorial (Todo Application)(MyBatis3 should be used for implementing infrastructure layer)
- Understands the basic operations of Maven
6.2.2. Overview of application to be created¶
- Login to application is possible by specifying ID and password on login page.
- Store account information required for login in the database.
- There is a Welcome page and Account information display page which can be viewed only by the logged in users.
- Logout from application is possible.
Overview of application is shown in the following figure.
URL list is shown below.
Sr. No. | Process name | HTTP method | URL | Description |
---|---|---|---|---|
1 | Login form display | GET | /login.jsp | Displays login form |
2 | Login | POST | /authentication | Authenticates using username and password entered from login form (performed by Spring Security) |
3 | Welcome page display | GET | / | Displays Welcome page. |
4 | Account information display | GET | /account | Displays account information of logged-in user. |
5 | Logout | POST | /logout | Performs logout (performed by Spring Security) |
6.2.3. Creating environment¶
6.2.3.1. Creating a project¶
Create A blank project of TERASOLUNA Server Framework for Java (5.x) using Maven archetype.
In this tutorial, a blank project is created for MyBatis3.
Basic knowledge such as how to import to Spring Tool Suite(STS), how to start an application server, etc. is omitted in this tutorial, since it is already described in Tutorial (Todo Application).
mvn archetype:generate -B^
-DarchetypeCatalog=http://repo.terasoluna.org/nexus/content/repositories/terasoluna-gfw-releases^
-DarchetypeGroupId=org.terasoluna.gfw.blank^
-DarchetypeArtifactId=terasoluna-gfw-web-blank-mybatis3-archetype^
-DarchetypeVersion=5.0.2.RELEASE^
-DgroupId=com.example.security^
-DartifactId=first-springsecurity^
-Dversion=1.0.0-SNAPSHOT
Most of the settings which are required for executing this tutorial are already performed in blank project. It is not mandatory to understand these settings just for executing the tutorial; however, it is recommended that you understand the settings which are required to run the application.
For description about settings required to run the application (configuration file), refer to “Description of configuration file”.
6.2.4. Creating an application¶
6.2.4.1. Implementing domain layer¶
The flow of authentication process of Spring Security is as follows:
- Search user information from the entered
username
. - When user information exists, compare the password stored in the corresponding user information with the hashed password that has been entered.
- When passwords match, authentication is considered to be successful.
If user information is not found or if the passwords do not match, authentication fails.
In domain layer, process to fetch Account object from user name is essential. The process is implemented in the following order.
- Creation of Domain Object(
Account
) - Creation of
AccountRepository
- Creation of
AccountSharedService
6.2.4.1.1. Creating a Domain Object¶
Account
class that stores authentication information (user name and password).src/main/java/com/example/security/domain/model/Account.java
package com.example.security.domain.model;
import java.io.Serializable;
public class Account implements Serializable {
private static final long serialVersionUID = 1L;
private String username;
private String password;
private String firstName;
private String lastName;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "Account [username=" + username + ", password=" + password
+ ", firstName=" + firstName + ", lastName=" + lastName + "]";
}
}
6.2.4.1.2. Creating AccountRepository¶
Implement a process to fetch Account
object from the database.
AccountRepository
interface.src/main/java/com/example/security/domain/repository/account/AccountRepository.java
package com.example.security.domain.repository.account;
import com.example.security.domain.model.Account;
public interface AccountRepository {
Account findOne(String username);
}
Account
record, in Mapper file.src/main/resources/com/example/security/domain/repository/account/AccountRepository.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.security.domain.repository.account.AccountRepository">
<resultMap id="accountResultMap" type="Account">
<id property="username" column="username" />
<result property="password" column="password" />
<result property="firstName" column="first_name" />
<result property="lastName" column="last_name" />
</resultMap>
<select id="findOne" parameterType="String" resultMap="accountResultMap">
SELECT
username,
password,
first_name,
last_name
FROM
account
WHERE
username = #{username}
</select>
</mapper>
6.2.4.1.4. Creating Authentication Service¶
src/main/java/com/example/security/domain/service/userdetails/SampleUserDetails.java
package com.example.security.domain.service.userdetails;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import com.example.security.domain.model.Account;
public class SampleUserDetails extends User { // (1)
private static final long serialVersionUID = 1L;
private final Account account; // (2)
public SampleUserDetails(Account account) {
// (3)
super(account.getUsername(), account.getPassword(), AuthorityUtils
.createAuthorityList("ROLE_USER")); // (4)
this.account = account;
}
public Account getAccount() { // (5)
return account;
}
}
Sr. No. | Description |
---|---|
(1)
|
Implement
org.springframework.security.core.userdetails.UserDetails interface.Here, implement project specific
UserDetails class, by inheriting org.springframework.security.core.userdetails.User class that implements UserDetails . |
(2)
|
Maintain account information of this project in Spring’s authentication user class.
|
(3)
|
Call constructor of
User class. The first argument is user name, the second is password and the third is authority list. |
(4)
|
As a simple implementation, create an authority having only a role named as
"ROLE_USER" . |
(5)
|
Create getter of account information. This enables fetching of
Account object of login user. |
src/main/java/com/example/security/domain/service/userdetails/SampleUserDetailsService.java
package com.example.security.domain.service.userdetails;
import javax.inject.Inject;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.terasoluna.gfw.common.exception.ResourceNotFoundException;
import com.example.security.domain.model.Account;
import com.example.security.domain.service.account.AccountSharedService;
@Service
public class SampleUserDetailsService implements UserDetailsService { // (1)
@Inject
AccountSharedService accountSharedService; // (2)
@Transactional(readOnly=true)
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
try {
Account account = accountSharedService.findOne(username); // (3)
return new SampleUserDetails(account); // (4)
} catch (ResourceNotFoundException e) {
throw new UsernameNotFoundException("user not found", e); // (5)
}
}
}
Sr. No. | Description |
---|---|
(1)
|
Implement
org.springframework.security.core.userdetails.UserDetailsService interface. |
(2)
|
Inject
AccountSharedService . |
(3)
|
Delegate the process of fetching
Account object from username to AccountSharedService . |
(4)
|
Create project specific
UserDetails object using the fetched Account object, and return as the return value of method. |
(5)
|
Throw
UsernameNotFoundException when target user is not found. |
6.2.4.1.5. Setting database initialization script¶
In this tutorial, H2 database (in memory database) is used as a database to store account information. As a result, database initialization is necessary by executing SQL at the time of starting the application server.
src/main/resources/META-INF/spring/first-springsecurity-env.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
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.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
<bean id="dateFactory" class="org.terasoluna.gfw.common.date.jodatime.DefaultJodaTimeDateFactory" />
<bean id="realDataSource" class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${database.driverClassName}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
<property name="defaultAutoCommit" value="false" />
<property name="maxTotal" value="${cp.maxActive}" />
<property name="maxIdle" value="${cp.maxIdle}" />
<property name="minIdle" value="${cp.minIdle}" />
<property name="maxWaitMillis" value="${cp.maxWait}" />
</bean>
<bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource">
<constructor-arg index="0" ref="realDataSource" />
</bean>
<!-- REMOVE THIS LINE IF YOU USE JPA
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
REMOVE THIS LINE IF YOU USE JPA -->
<!-- REMOVE THIS LINE IF YOU USE MyBatis2
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
REMOVE THIS LINE IF YOU USE MyBatis2 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- (1) -->
<jdbc:initialize-database data-source="dataSource" ignore-failures="ALL">
<!-- (2) -->
<jdbc:script location="classpath:/database/${database}-schema.sql" />
<jdbc:script location="classpath:/database/${database}-dataload.sql" />
</jdbc:initialize-database>
</beans>
Sr. No. | Description |
---|---|
(1)
|
Perform settings to execute SQL script that initializes the database in Define these settings in |
(2)
|
Specify the SQL file where DDL statement for creating a table that stores account information is mentioned. As per blank project settings, |
(3)
|
Specify SQL file, where DML statement to register the demo user is mentioned. As per blank project settings, |
src/main/resources/database/H2-schema.sql
CREATE TABLE account(
username varchar(128),
password varchar(60),
first_name varchar(128),
last_name varchar(128),
constraint pk_tbl_account primary key (username)
);
src/main/resources/database/H2-dataload.sql
INSERT INTO account(username, password, first_name, last_name) VALUES('demo', '$2a$10$oxSJl.keBwxmsMLkcT9lPeAIxfNTPNQxpeywMrF7A3kVszwUTqfTK', 'Taro', 'Yamada'); -- (1)
COMMIT;
Sr. No. | Description |
---|---|
(1)
|
As per blank project settings, In this tutorial, a string called |
6.2.4.1.6. Package Explorer after creating Domain Layer¶
Confirm the file created in domain layer.
“Hierarchical” is being used for Package Presentation of Package Explorer.
6.2.4.2. Implementing Application Layer¶
6.2.4.2.1. Spring Security settings¶
Perform authentication/authorization settings using Spring Security in spring-security.xml
.
Following are URL patterns to be handled by the application created in this tutorial.
URL
|
Description
|
---|---|
/login.jsp
|
URL to display login form
|
/login.jsp?error=true
|
URL to display transition page (login page) in case of authentication error
|
/authenticate
|
URL for authentication
|
/logout
|
URL for logout
|
/
|
URL to display welcome page
|
/account
|
URL to display account information of login user.
|
src/main/resources/META-INF/spring/spring-security.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:sec="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.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.xsd">
<sec:http pattern="/resources/**" security="none"/>
<sec:http auto-config="true" use-expressions="true">
<sec:headers>
<sec:cache-control />
<sec:content-type-options />
<sec:hsts />
<sec:frame-options />
<sec:xss-protection />
</sec:headers>
<sec:csrf />
<sec:access-denied-handler ref="accessDeniedHandler"/>
<sec:custom-filter ref="userIdMDCPutFilter" after="ANONYMOUS_FILTER"/>
<sec:session-management />
<!-- (1) -->
<sec:form-login
login-page="/login.jsp"
authentication-failure-url="/login.jsp?error=true"
login-processing-url="/authenticate" />
<!-- (2) -->
<sec:logout
logout-url="/logout"
logout-success-url="/"
delete-cookies="JSESSIONID" />
<!-- (3) -->
<sec:intercept-url pattern="/login.jsp" access="permitAll" />
<sec:intercept-url pattern="/**" access="isAuthenticated()" />
</sec:http>
<sec:authentication-manager>
<!-- com.example.security.domain.service.userdetails.SampleUserDetailsService
is scanned by component scan with @Service -->
<!-- (4) -->
<sec:authentication-provider
user-service-ref="sampleUserDetailsService">
<!-- (5) -->
<sec:password-encoder ref="passwordEncoder" />
</sec:authentication-provider>
</sec:authentication-manager>
<!-- Change View for CSRF or AccessDenied -->
<bean id="accessDeniedHandler"
class="org.springframework.security.web.access.DelegatingAccessDeniedHandler">
<constructor-arg index="0">
<map>
<entry
key="org.springframework.security.web.csrf.InvalidCsrfTokenException">
<bean
class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage"
value="/WEB-INF/views/common/error/invalidCsrfTokenError.jsp" />
</bean>
</entry>
<entry
key="org.springframework.security.web.csrf.MissingCsrfTokenException">
<bean
class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage"
value="/WEB-INF/views/common/error/missingCsrfTokenError.jsp" />
</bean>
</entry>
</map>
</constructor-arg>
<constructor-arg index="1">
<bean
class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage"
value="/WEB-INF/views/common/error/accessDeniedError.jsp" />
</bean>
</constructor-arg>
</bean>
<!-- Put UserID into MDC -->
<bean id="userIdMDCPutFilter" class="org.terasoluna.gfw.security.web.logging.UserIdMDCPutFilter">
</bean>
</beans>
Sr. No. | Description |
---|---|
(1)
|
Perform settings related to login form using Perform following settings in
|
(2)
|
Perform settings for logout using Perform following settings in
|
(3)
|
Perform authorization settings for each URL using Perform following settings in
However, all users can access the URL under |
(4)
|
Perform settings of By default, Specify component bean name where |
(5)
|
Perform settings for a class ( In this tutorial, |
Note
Default URL provided by Spring Security is changed for the URLs that perform authentication and logout process.
This is because, a string (spring_security
) that implies the usage of Spring Security is included in these URLs.
When default URL is used as it is and if security vulnerability is detected in Spring Security,
please be careful as it becomes easy to receive attacks from a malicious user.
6.2.4.2.2. Creating login page¶
src/main/webapp/login.jsp
<!DOCTYPE html>
<html>
<head>
<title>Login Page</title>
<link rel="stylesheet"
href="${pageContext.request.contextPath}/resources/app/css/styles.css">
</head>
<body>
<div id="wrapper">
<h3>Login with Username and Password</h3>
<!-- (1) -->
<c:if test="${param.error}">
<!-- (2) -->
<t:messagesPanel messagesType="error"
messagesAttributeName="SPRING_SECURITY_LAST_EXCEPTION" />
</c:if>
<!-- (3) -->
<form:form action="${pageContext.request.contextPath}/authenticate">
<table>
<tr>
<td><label for="j_username">User:</label></td>
<td><input type="text" id="j_username"
name="j_username" value='demo'>(demo)</td><!-- (4) -->
</tr>
<tr>
<td><label for="j_password">Password:</label></td>
<td><input type="password" id="j_password"
name="j_password" value="demo" />(demo)</td><!-- (5) -->
</tr>
<tr>
<td> </td>
<td><input name="submit" type="submit" value="Login" /></td>
</tr>
</table>
</form:form>
</div>
</body>
</html>
Sr. No. | Description |
---|---|
(1)
|
When authentication fails, display login page by calling "/login.jsp?error=true" .
Therefore, use <c:if> tag, so that error message is displayed only at the time after the display of authentication error. |
(2)
|
Display an error message using When authentication fails, an exception object of authentication error is stored with attribute name |
(3)
|
Set URL for authentication ( Send parameters necessary for authentication (user name and password) using POST method. |
(4)
|
Create a text box to specify user name. Spring Security’s default parameter name is |
(5)
|
Create a text box to specify password (text box for password). Spring Security’s default parameter name is |
src/main/webapp/WEB-INF/views/common/include.jsp
<%@ page session="true"%> <!-- (6) -->
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec"%>
<%@ taglib uri="http://terasoluna.org/functions" prefix="f"%>
<%@ taglib uri="http://terasoluna.org/tags" prefix="t"%>
Sr. No. | Description |
---|---|
(6)
|
Set session attribute of page directive to true . |
Note
As per default settings of blank project, session scope cannot be accessed from JSP. This is to ensure that the session cannot be easily used; however, in case of fetching an exception object of authentication error from JSP, it is necessary to be accessible from a JSP by session scope.
login-page
attribute of <sec:form-login>
tag (http://localhost:8080/first-springsecurity/login.jsp), and the screen below is displayed.6.2.4.2.3. Accessing account information of login user from JSP¶
src/main/webapp/WEB-INF/views/welcome/home.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Home</title>
<link rel="stylesheet"
href="${pageContext.request.contextPath}/resources/app/css/styles.css">
</head>
<!-- (1) -->
<sec:authentication property="principal.account" var="account" />
<body>
<div id="wrapper">
<h1>Hello world!</h1>
<p>The time on the server is ${serverTime}.</p>
<!-- (2) -->
<p>Welcome ${f:h(account.firstName)} ${f:h(account.lastName)} !!</p>
<ul>
<li><a href="${pageContext.request.contextPath}/account">view account</a></li>
</ul>
</div>
</body>
</html>
Sr. No. | Description |
---|---|
(1)
|
Access By using In this tutorial, |
(2)
|
Access Account object of login user and display firstName and lastName . |
Click Login button on login page to display welcome page.
6.2.4.2.4. Adding logout button¶
src/main/webapp/WEB-INF/views/welcome/home.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Home</title>
<link rel="stylesheet"
href="${pageContext.request.contextPath}/resources/app/css/styles.css">
</head>
<sec:authentication property="principal.account" var="account" />
<body>
<div id="wrapper">
<h1>Hello world!</h1>
<p>The time on the server is ${serverTime}.</p>
<p>Welcome ${f:h(account.firstName)} ${f:h(account.lastName)} !!</p>
<p>
<!-- (1) -->
<form:form action="${pageContext.request.contextPath}/logout">
<button type="submit">Logout</button>
</form:form>
</p>
<ul>
<li><a href="${pageContext.request.contextPath}/account">view account</a></li>
</ul>
</div>
</body>
</html>
Sr. No. | Description |
---|---|
(1)
|
Add a form for logout using Add Logout button by specifying the URL for logout ( |
Click Logout button to log out from the application (login page is displayed).
6.2.4.2.5. Accessing account information of login user from Controller¶
src/main/java/com/example/security/app/account/AccountController.java
package com.example.security.app.account;
import org.springframework.security.web.bind.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.example.security.domain.model.Account;
import com.example.security.domain.service.userdetails.SampleUserDetails;
@Controller
@RequestMapping("account")
public class AccountController {
@RequestMapping
public String view(
@AuthenticationPrincipal SampleUserDetails userDetails, // (1)
Model model) {
// (2)
Account account = userDetails.getAccount();
model.addAttribute(account);
return "account/view";
}
}
Sr. No. | description |
---|---|
(1)
|
Receive
UserDetails object of login user by specifying @AuthenticationPrincipal annotation. |
(2)
|
Fetch
Account object which is retained by SampleUserDetails object and store it in Model in order to pass it to View. |
src/main/webapp/WEB-INF/views/account/view.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Home</title>
<link rel="stylesheet"
href="${pageContext.request.contextPath}/resources/app/css/styles.css">
</head>
<body>
<div id="wrapper">
<h1>Account Information</h1>
<table>
<tr>
<th>Username</th>
<td>${f:h(account.username)}</td>
</tr>
<tr>
<th>First name</th>
<td>${f:h(account.firstName)}</td>
</tr>
<tr>
<th>Last name</th>
<td>${f:h(account.lastName)}</td>
</tr>
</table>
</div>
</body>
</html>
Click ‘view account’ link on welcome page to display “Show account information” page of login user.
6.2.4.2.6. Package explorer after creating application layer¶
Confirm the file created in application layer.
“Hierarchical” is being used for Package Presentation of Package Explorer.
6.2.5. Summary¶
We have covered the following topics in this tutorial.
- Basic authentication/authorization using Spring Security
- How to customize authentication user object
- Authentication settings using Repository and Service class
- How to access logged in account information from JSP
- How to access logged in account information from Controller
6.2.6. Appendix¶
6.2.6.1. Description of configuration file¶
Describe configuration file to understand which settings are necessary for using Spring Security.
6.2.6.1.1. spring-security.xml¶
Perform definitions related to Spring Security in spring-security.xml
.
src/main/resources/META-INF/spring/spring-security.xml
of the blank project which has been created has following settings.
<?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:sec="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.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.xsd">
<!-- (1) -->
<sec:http pattern="/resources/**" security="none"/>
<sec:http auto-config="true" use-expressions="true">
<!-- (2) -->
<sec:headers>
<sec:cache-control />
<sec:content-type-options />
<sec:hsts />
<sec:frame-options />
<sec:xss-protection />
</sec:headers>
<!-- (3) -->
<sec:csrf />
<!-- (4) -->
<sec:access-denied-handler ref="accessDeniedHandler"/>
<!-- (5) -->
<sec:custom-filter ref="userIdMDCPutFilter" after="ANONYMOUS_FILTER"/>
<!-- (6) -->
<sec:session-management />
</sec:http>
<!-- (7) -->
<sec:authentication-manager></sec:authentication-manager>
<!-- (4) -->
<!-- Change View for CSRF or AccessDenied -->
<bean id="accessDeniedHandler"
class="org.springframework.security.web.access.DelegatingAccessDeniedHandler">
<constructor-arg index="0">
<map>
<entry
key="org.springframework.security.web.csrf.InvalidCsrfTokenException">
<bean
class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage"
value="/WEB-INF/views/common/error/invalidCsrfTokenError.jsp" />
</bean>
</entry>
<entry
key="org.springframework.security.web.csrf.MissingCsrfTokenException">
<bean
class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage"
value="/WEB-INF/views/common/error/missingCsrfTokenError.jsp" />
</bean>
</entry>
</map>
</constructor-arg>
<constructor-arg index="1">
<bean
class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage"
value="/WEB-INF/views/common/error/accessDeniedError.jsp" />
</bean>
</constructor-arg>
</bean>
<!-- (5) -->
<!-- Put UserID into MDC -->
<bean id="userIdMDCPutFilter" class="org.terasoluna.gfw.security.web.logging.UserIdMDCPutFilter">
</bean>
</beans>
Sr. No. | Description |
---|---|
(1)
|
Control authentication/authorization for HTTP access using As per the default settings of blank project , URL to access static resources (js, css, image files, etc.) is out of authentication/authorization scope. |
(2)
|
Control the response header for security measures using For usage method, refer to “Settings to assign a secure HTTP header”. |
(3)
|
Control CSRF measures using For usage method, refer to “CSRF Countermeasures”. |
(4)
|
Control action after access is denied using Following settings are performed as default settings of blank project.
|
(5)
|
Enable servlet filter to store authentication user name of Spring Security in logger MDC. Once this setting is enabled, authentication user name is output in log thereby enhancing the traceability. |
(6)
|
Control session management method of Spring Security using For usage method, refer to “Session management in Spring Security”. |
(7)
|
Control authentication using For usage method, refer to “Setting authentication process”. |
6.2.6.1.2. spring-mvc.xml¶
Perform settings to link Spring Security and Spring MVC in spring-mvc.xml
.
src/main/resources/META-INF/spring/spring-mvc.xml
of the blank project that has been created has following settings.
Description of settings not related to Spring Security is omitted.
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:property-placeholder
location="classpath*:/META-INF/spring/*.properties" />
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean
class="org.springframework.data.web.PageableHandlerMethodArgumentResolver" />
<!-- (1) -->
<bean
class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
<mvc:default-servlet-handler />
<context:component-scan base-package="com.example.security.app" />
<mvc:resources mapping="/resources/**"
location="/resources/,classpath:META-INF/resources/"
cache-period="#{60 * 60}" />
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/resources/**" />
<mvc:exclude-mapping path="/**/*.html" />
<bean
class="org.terasoluna.gfw.web.logging.TraceLoggingInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/resources/**" />
<mvc:exclude-mapping path="/**/*.html" />
<bean
class="org.terasoluna.gfw.web.token.transaction.TransactionTokenInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/resources/**" />
<mvc:exclude-mapping path="/**/*.html" />
<bean class="org.terasoluna.gfw.web.codelist.CodeListInterceptor">
<property name="codeListIdPattern" value="CL_.+" />
</bean>
</mvc:interceptor>
<!-- REMOVE THIS LINE IF YOU USE JPA
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/resources/**" />
<mvc:exclude-mapping path="/**/*.html" />
<bean
class="org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor" />
</mvc:interceptor>
REMOVE THIS LINE IF YOU USE JPA -->
</mvc:interceptors>
<!-- Settings View Resolver. -->
<mvc:view-resolvers>
<mvc:jsp prefix="/WEB-INF/views/" />
</mvc:view-resolvers>
<bean id="requestDataValueProcessor"
class="org.terasoluna.gfw.web.mvc.support.CompositeRequestDataValueProcessor">
<constructor-arg>
<util:list>
<!-- (2) -->
<bean class="org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor" />
<bean
class="org.terasoluna.gfw.web.token.transaction.TransactionTokenRequestDataValueProcessor" />
</util:list>
</constructor-arg>
</bean>
<!-- Setting Exception Handling. -->
<!-- Exception Resolver. -->
<bean class="org.terasoluna.gfw.web.exception.SystemExceptionResolver">
<property name="exceptionCodeResolver" ref="exceptionCodeResolver" />
<!-- Setting and Customization by project. -->
<property name="order" value="3" />
<property name="exceptionMappings">
<map>
<entry key="ResourceNotFoundException" value="common/error/resourceNotFoundError" />
<entry key="BusinessException" value="common/error/businessError" />
<entry key="InvalidTransactionTokenException" value="common/error/transactionTokenError" />
<entry key=".DataAccessException" value="common/error/dataAccessError" />
</map>
</property>
<property name="statusCodes">
<map>
<entry key="common/error/resourceNotFoundError" value="404" />
<entry key="common/error/businessError" value="409" />
<entry key="common/error/transactionTokenError" value="409" />
<entry key="common/error/dataAccessError" value="500" />
</map>
</property>
<property name="defaultErrorView" value="common/error/systemError" />
<property name="defaultStatusCode" value="500" />
</bean>
<!-- Setting AOP. -->
<bean id="handlerExceptionResolverLoggingInterceptor"
class="org.terasoluna.gfw.web.exception.HandlerExceptionResolverLoggingInterceptor">
<property name="exceptionLogger" ref="exceptionLogger" />
</bean>
<aop:config>
<aop:advisor advice-ref="handlerExceptionResolverLoggingInterceptor"
pointcut="execution(* org.springframework.web.servlet.HandlerExceptionResolver.resolveException(..))" />
</aop:config>
</beans>
Sr. No. | Description |
---|---|
(1)
|
Settings to ensure that Specify |
(2)
|
Settings to embed CSRF token value in HTML form using Specify |