Spring5 MVC Web application development with Visual Studio Code Spring Security usage 1/3 [Preparation]

Introduction

We will extend the project created in SQL Server Connection. If you copy and paste in order, you will have a moving object for the time being. I was particular about the order in which errors do not occur during copying. So, does this code exist at this time? Do you need it? There is also a part called. The error checking process is incomplete. Please be forewarned.

Created with the following specifications.

-Extend the project created in SQL Server Connection. --Create your own user table and authenticate. --Create two administrative users and two general users so that you can see the difference in behavior depending on the role. --Only administrative users can register general users. --Only one admin user can be created. --Do not use CSS or JavaScript.

environment

OS:Windows 10 Pro 64bit DB:SQL Server 2019(Cent OS 8 on Hyper-V) Editor:Visual Studio Code 1.44.2 JDK:AdoptOpenJDK 11.0.6+10 x64 Apache Maven:v3.6.3 Apache Tomcat:v9.0.31

Creation procedure

  1. Create a table to store user information
  2. Creation of entity and repository required for DB access
  3. Settings for using Spring Security
  4. Create an administrative user registration page
  5. Creating a general user registration page

Create a table to store user information

Create a UserInfo table to save user information and a UserRoles table to save roles in the DB created in here.

UserInfo


CREATE TABLE [dbo].[UserInfo](
	[UserId] [varchar](255) NOT NULL,
	[Password] [varchar](255) NOT NULL,
	[UserNameJP] [nvarchar](255) NOT NULL,
	[SectionNameJP] [nvarchar](255) NOT NULL,
	[Enabled] [bit] NOT NULL,
 CONSTRAINT [PK_UserInfo] PRIMARY KEY CLUSTERED 
(
	[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY];

UserRoles


CREATE TABLE [dbo].[UserRoles](
	[UserId] [varchar](255) NOT NULL,
	[Authority] [varchar](255) NOT NULL,
 CONSTRAINT [PK_UserRoles] PRIMARY KEY CLUSTERED 
(
	[UserId] ASC,
	[Authority] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY];

Project creation

I copied the project created in SQL Server Connection to "D: \ JAVA \ Project \ securitySample" and created it.

pom.xml Add the Repository required for Spring Security and the Repository used to check the number of characters in the password.

<properties>
	<spring-security.version>5.3.0.RELEASE</spring-security.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-config</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.hibernate.validator</groupId>
    	<artifactId>hibernate-validator</artifactId>
    	<version>6.1.2.Final</version>
    	<scope>compile</scope>
</dependency>

The entire pom.xml.

pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.example</groupId>
	<artifactId>securitySample1</artifactId>
	<version>1.0-SNAPSHOT</version>
	<packaging>war</packaging>
 
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>11</java.version>
		<spring.version>5.2.4.RELEASE</spring.version>
		<spring-security.version>5.3.0.RELEASE</spring-security.version>
        <!-- web.Run the build even if you don't have xml-->
        <failOnMissingWebXml>false</failOnMissingWebXml>
	</properties>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>${java.version}</source>
					<target>${java.version}</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
			<scope>compile</scope>
		</dependency>

		<dependency>
    		<groupId>org.springframework</groupId>
    		<artifactId>spring-context-support</artifactId>
    		<version>${spring.version}</version>
    		<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${spring.version}</version>
			<scope>compile</scope>
		</dependency>

		<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-config</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>com.microsoft.sqlserver</groupId>
    		<artifactId>mssql-jdbc</artifactId>
    		<version>8.2.1.jre11</version>
    		<scope>runtime</scope>
		</dependency>

		<dependency>
		    <groupId>com.zaxxer</groupId>
		    <artifactId>HikariCP</artifactId>
		    <version>3.4.2</version>
		    <scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>org.thymeleaf</groupId>
			<artifactId>thymeleaf-spring5</artifactId>
			<version>3.0.11.RELEASE</version>
			<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>org.thymeleaf.extras</groupId>
			<artifactId>thymeleaf-extras-java8time</artifactId>
			<version>3.0.4.RELEASE</version>
			<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
	    	<groupId>org.hibernate.validator</groupId>
	    	<artifactId>hibernate-validator</artifactId>
	    	<version>6.1.2.Final</version>
	    	<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.10</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>
</project>

entity creation

Create an entity to store user information.

D:\JAVA\Project\securitySample\src\main\java\com\example\persistence
└─entity
  ├─UserInfo.java
  └─UserRoles.java

UserRoles.java Stores roles (privileges).

UserRoles.java


package com.example.persistence.entity;

import lombok.Data;

@Data
public class UserRoles {
	private String userId;
	private String authority;

	public UserRoles() {}

	public UserRoles(String userId, String authority) {
		this.userId = userId;
		this.authority = authority;
	}

}

UserInfo.java Stores user information.

UserInfo.java


package com.example.persistence.entity;

import java.util.List;

import lombok.Data;

@Data
public class UserInfo {
    private String userId;
	private String password;
	private String userNameJP;
	private String sectionNameJP;
	private Boolean enabled;
	private List<UserRoles> userRolesList;

	public UserInfo() {}

	public UserInfo(String userId, String userNameJP, String sectionNameJP, Boolean enabled) {
		this.userId = userId;
		this.userNameJP = userNameJP;
		this.sectionNameJP = sectionNameJP;
		this.enabled = enabled;
	}
}

Creating repository

Create a repository to access the DB.

D:\JAVA\Project\securitySample\src\main\java\com\example\persistence
└─repository
  ├─UserInfoRepository.java
  ├─UserInfoRepositoryImpl.java
  ├─UserRolesRepository.java
  └─UserRolesRepositoryImpl.java

UserInfoRepository.java

UserInfoRepository.java


package com.example.persistence.repository;

import java.util.List;
import java.util.Optional;

import com.example.persistence.entity.UserInfo;

public interface UserInfoRepository {
    Optional<UserInfo> selectDetailByUserId(String id);

	Integer insert(UserInfo userInfo);

	Integer update(UserInfo userInfo);

	Integer delete(String userId);

	List<UserInfo> findUserAll();
}

UserInfoRepositoryImpl.java

UserInfoRepositoryImpl.java


package com.example.persistence.repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

import com.example.persistence.entity.UserInfo;
import com.example.persistence.entity.UserRoles;

@Repository
public class UserInfoRepositoryImpl implements UserInfoRepository{
    @Autowired
    NamedParameterJdbcTemplate jdbcTemplate;

    private static final RowMapper<UserInfo> INFO_MAPPER = (rs, rowNum) ->
    new UserInfo(rs.getString("UserId"),
            rs.getString("UserNameJP"),
            rs.getString("SectionNameJP"),
            rs.getBoolean("Enabled")
            );

    private static final RowMapper<UserRoles> ROLES_MAPPER = (rs, rowNum) ->
    new UserRoles(rs.getString("UserId"),
            rs.getString("Authority")
            );

    @Override
    public Optional<UserInfo> selectDetailByUserId(String id) {
        try {

            UserInfo userInfo = new UserInfo();
            List<UserRoles> userRolesList = new ArrayList<UserRoles>();

            String sql = "SELECT UserInfo.UserId, UserInfo.Password, UserInfo.UserNameJP, UserInfo.SectionNameJP, UserInfo.Enabled"
                    + " , UserRoles.Authority"
                    + " FROM UserInfo INNER JOIN UserRoles ON UserInfo.UserId = UserRoles.UserId "
                    + " WHERE (UserInfo.UserId = :id)";

            MapSqlParameterSource parameterSource = new MapSqlParameterSource();
            parameterSource.addValue("id", id);
            List<Map<String, Object>> resultList = jdbcTemplate.queryForList(sql, parameterSource);

            for(Map<String, Object> result : resultList) {
                UserRoles userRoles = new UserRoles();
                userRoles.setUserId((String) result.get("UserId"));
                userRoles.setAuthority((String) result.get("Authority"));
                userRolesList.add(userRoles);

                userInfo.setUserId((String) result.get("UserId"));
                userInfo.setPassword((String) result.get("Password"));
                userInfo.setUserNameJP((String) result.get("UserNameJP"));
                userInfo.setSectionNameJP((String) result.get("SectionNameJP"));
                userInfo.setEnabled((Boolean) result.get("Enabled"));
            }

            userInfo.setUserRolesList(userRolesList);

            return Optional.of(userInfo);

        }catch (EmptyResultDataAccessException e) {

            return Optional.empty();
        }
    }

    @Override
    public Integer insert(UserInfo userInfo) {
        String sql = "INSERT INTO UserInfo"
                + " VALUES(:UserId, :Password, :UserNameJP, :SectionNameJP, :Enabled);";
        MapSqlParameterSource parameterSource = new MapSqlParameterSource();
        parameterSource.addValue("UserId",          userInfo.getUserId());
        parameterSource.addValue("Password",        userInfo.getPassword());
        parameterSource.addValue("UserNameJP",      userInfo.getUserNameJP());
        parameterSource.addValue("SectionNameJP",   userInfo.getSectionNameJP());
        parameterSource.addValue("Enabled",         userInfo.getEnabled());

        Integer rows = jdbcTemplate.update(sql, parameterSource);
        return rows;
    }

    @Override
    public Integer update(UserInfo userInfo) {
        String sql = "UPDATE UserInfo SET "
                + " Password = :Password "
                + ",UserNameJP = :UserNameJP "
                + ",SectionNameJP = :SectionNameJP "
                + ",Enabled = :Enabled "
                + " WHERE UserId = :UserId;";

        MapSqlParameterSource parameterSource = new MapSqlParameterSource();
        parameterSource.addValue("UserId",          userInfo.getUserId());
        parameterSource.addValue("Password",        userInfo.getPassword());
        parameterSource.addValue("UserNameJP",      userInfo.getUserNameJP());
        parameterSource.addValue("SectionNameJP",   userInfo.getSectionNameJP());
        parameterSource.addValue("Enabled",         userInfo.getEnabled());

        Integer rows = jdbcTemplate.update(sql, parameterSource);
        return rows;
    }

    @Override
    public Integer delete(String userId) {
        String sql = "DELETE FROM UserInfo WHERE UserId = :UserId;";
        MapSqlParameterSource parameterSource = new MapSqlParameterSource();
        parameterSource.addValue("UserId", userId);

        Integer rows = jdbcTemplate.update(sql, parameterSource);
        return rows;
    }

    @Override
    public List<UserInfo> findUserAll() {
        String sql1 = "SELECT DISTINCT UserInfo.UserId, UserInfo.UserNameJP, UserInfo.SectionNameJP, UserInfo.Enabled"
                + " FROM UserInfo INNER JOIN UserRoles ON UserInfo.UserId = UserRoles.UserId "
                + " WHERE UserRoles.Authority = 'ROLE_USER'"
                + " ORDER BY UserInfo.UserId;" ;

        List<UserInfo> userInfoList = jdbcTemplate.query(sql1, INFO_MAPPER);

        userInfoList.forEach(userInfo -> {
            String sql2 = "SELECT * FROM UserRoles WHERE UserId = :UserId;";
            MapSqlParameterSource parameterSource = new MapSqlParameterSource();
            parameterSource.addValue("UserId", userInfo.getUserId());
            List<UserRoles> userRolesList = jdbcTemplate.query(sql2, parameterSource, ROLES_MAPPER);

            userInfo.setUserRolesList(userRolesList);
        });

        return userInfoList;
    }
}

UserRolesRepository.java

UserRolesRepository.java


package com.example.persistence.repository;

import com.example.persistence.entity.UserRoles;

public interface UserRolesRepository {
	Integer insert(UserRoles userRoles);

	Integer update(UserRoles userRoles);

	Integer delete(String userId);

	Integer adminCheck();
}

UserRolesRepositoryImpl.java

UserRolesRepositoryImpl.java


package com.example.persistence.repository;

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

import com.example.persistence.entity.UserRoles;

@Repository
public class UserRolesRepositoryImpl implements UserRolesRepository {
    @Autowired
    NamedParameterJdbcTemplate jdbcTemplate;

    @Override
    public Integer insert(UserRoles userRoles) {
        String sql = "INSERT INTO UserRoles"
                + " VALUES(:UserId, :Authority);";
        MapSqlParameterSource parameterSource = new MapSqlParameterSource();
        parameterSource.addValue("UserId", userRoles.getUserId());
        parameterSource.addValue("Authority", userRoles.getAuthority());

        Integer rows = jdbcTemplate.update(sql, parameterSource);
        return rows;
    }

    @Override
    public Integer update(UserRoles userRoles) {
        String sql = "UPDATE UserRoles SET Authority = :Authority"
                + " WHERE UserId = :UserId;";
        MapSqlParameterSource parameterSource = new MapSqlParameterSource();
        parameterSource.addValue("UserId", userRoles.getUserId());
        parameterSource.addValue("Authority", userRoles.getAuthority());

        Integer rows = jdbcTemplate.update(sql, parameterSource);
        return rows;
    }

    @Override
    public Integer delete(String userId) {
        String sql = "DELETE FROM UserRoles WHERE UserId = :UserId;";
        MapSqlParameterSource parameterSource = new MapSqlParameterSource();
        parameterSource.addValue("UserId", userId);

        Integer rows = jdbcTemplate.update(sql, parameterSource);
        return rows;
    }

    @Override
    public Integer adminCheck() {
        Integer rows = 0;

        String sql = "SELECT COUNT(*) AS CNT"
                + " FROM UserRoles"
                + " WHERE Authority = 'ROLE_ADMIN';" ;
        MapSqlParameterSource parameterSource = new MapSqlParameterSource();

        Map<String, Object> result = jdbcTemplate.queryForMap(sql,parameterSource);
        rows = Integer.parseInt(result.get("CNT").toString());

        return rows;
    }
}

Security department creation

Create a "security" folder in "D: \ JAVA \ Project \ sqlSample \ src \ main \ java \ com \ example". Create a config folder directly under it. Create the following files in the config folder.

Create the following files directly under the security folder.

D:\JAVA\Project\securitySample\src\main\java\com\example\security
├─config
|  ├─SecurityConfig.java
|  └─SpringSecurityInitializer.java
├─MyAccessDeniedHandler.java
├─MyAuthenticationSuccessHandler.java
├─MyUserDetails.java
└─MyUserDetailsService.java

MyAuthenticationSuccessHandler.java Specify the page to be displayed when authentication is successful. It is also possible to divide by roll.

MyAuthenticationSuccessHandler.java


package com.example.security;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;


public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler  {
	@Override
    public void onAuthenticationSuccess(
        HttpServletRequest request, HttpServletResponse response, Authentication authentication)
        		throws IOException, ServletException {

        RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

        //Redirect destination after authentication
        if (authentication.getAuthorities().toString().contains("ADMIN")) {
            //The ADMIN role displays the user registration page.
        	redirectStrategy.sendRedirect(request, response, "/userReg/index");
        } else {
            //The page to be displayed for other roles.
        	redirectStrategy.sendRedirect(request, response, "/hello/index");
        }
    }
}

MyAccessDeniedHandler.java Specify the page to be displayed when an error occurs in the authentication process.

MyAccessDeniedHandler.java


package com.example.security;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.access.AccessDeniedHandler;

public class MyAccessDeniedHandler implements AccessDeniedHandler{
	@Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);

        RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
        redirectStrategy.sendRedirect(request, response, "/auth/403");
    }
}

MyUserDetails.java Add the items you want to add to the standard credentials. The Japanese item of the user name and the department name are added.

MyUserDetails.java


package com.example.security;

import java.util.List;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;

import com.example.persistence.entity.UserInfo;

public class MyUserDetails extends User {
    private static final long serialVersionUID = 1L;
    private final String userNameJP;
	private final String sectionNameJP;

	public MyUserDetails(UserInfo userInfo, List<? extends GrantedAuthority> authorityList) {
		super(userInfo.getUserId(), userInfo.getPassword(), userInfo.getEnabled(), true, true, true, authorityList);
		this.userNameJP = userInfo.getUserNameJP();
		this.sectionNameJP = userInfo.getSectionNameJP();
	}

	public String getUserNameJP() {
		return userNameJP;
	}

	public String getSectionNameJP() {
		return sectionNameJP;
	}
}

MyUserDetailsService.java

MyUserDetailsService.java


package com.example.security;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.example.persistence.entity.UserInfo;
import com.example.persistence.entity.UserRoles;
import com.example.persistence.repository.UserInfoRepository;

public class MyUserDetailsService implements UserDetailsService {
    @Autowired
    UserInfoRepository userInfoRepository;

    @Override
    public UserDetails loadUserByUsername(String userId) throws UsernameNotFoundException {
        Optional<UserInfo> userInfoOpt = userInfoRepository.selectDetailByUserId(userId);
        if (userInfoOpt == null) {
            throw new UsernameNotFoundException("");
        }

        UserInfo userInfo = userInfoOpt.get();

        List<SimpleGrantedAuthority> authorityList = new ArrayList<SimpleGrantedAuthority>();

        List<UserRoles> roles = userInfo.getUserRolesList();
        for (UserRoles role: roles) {
            authorityList.add(new SimpleGrantedAuthority(role.getAuthority()));
        }

        return new MyUserDetails(userInfo, authorityList);
    }
}

SecurityConfig.java Basic authentication is not used in this application, but it is described as an example to be used together with Form authentication. The description gives priority to Basic authentication.

SecurityConfig.java


package com.example.security.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.filter.CharacterEncodingFilter;

import com.example.security.MyAccessDeniedHandler;
import com.example.security.MyAuthenticationSuccessHandler;
import com.example.security.MyUserDetailsService;

@Configuration
@EnableWebSecurity
public class SecurityConfig {
	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(myUserDetailsService());
	}

	@Bean
	public UserDetailsService myUserDetailsService() {
		return new MyUserDetailsService();
	}

	@Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
	/**
	 *Basic authentication
	 */
	@Configuration
	@Order(Ordered.HIGHEST_PRECEDENCE)
	public class WebSecurityBasicConfig extends WebSecurityConfigurerAdapter {

		@Override
		protected void configure(HttpSecurity http) throws Exception {
			http
				.csrf().disable()
				.antMatcher("/api/**")
				.authorizeRequests()
					.antMatchers("/api/admin/**").hasAnyRole("ADMIN")
				.anyRequest().authenticated()
					.and()
					.httpBasic()
            ;
		}
	}

	/**
	 *Form authentication
	 */
	@Configuration
	public class WebSecurityFormConfig extends WebSecurityConfigurerAdapter {

		@Override
		protected void configure(HttpSecurity http) throws Exception {
			CharacterEncodingFilter filter = new CharacterEncodingFilter();
	        filter.setEncoding("UTF-8");
	        filter.setForceEncoding(true);

			  http
			  	.addFilterBefore(filter, CsrfFilter.class)
			  	.authorizeRequests()

			  	//Accessable for any role
		  		.antMatchers("/", "/resources/**", "/webjars/**", "/auth/**", "/adminReg/**").permitAll()

		  		//Access settings for roles
		  		// '/userReg/'URLs that start with'ADMIN'Only roles can be accessed
			    .antMatchers("/userReg/**").hasRole("ADMIN")

			  	.anyRequest().authenticated()
			  	.and()
			  		.formLogin()
			  		.loginProcessingUrl("/login")
			  		.loginPage("/auth/login")
			  		.failureUrl("/auth/login-error")
			  		.successHandler(new MyAuthenticationSuccessHandler())
			  		.permitAll()
		        .and()
		        //Logout processing settings
		        	.logout()
		            //URL for logout process
		            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
		            //Transition destination URL when logout is successful
		            .logoutSuccessUrl("/auth/login")
		            //Cookie name to delete when logging out
		            .deleteCookies("JSESSIONID")
		            //Enable session destruction on logout
		            .invalidateHttpSession(true)
		            .permitAll()
		        .and()
		        //Transition destination setting at the time of 403 error
		        	.exceptionHandling()
		        	.accessDeniedHandler(new MyAccessDeniedHandler())

		        ;
		}

	}
}

SpringSecurityInitializer.java

SpringSecurityInitializer.java


package com.example.security.config;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {

}

Added WebAppInitializer.java

Add SecurityConfig.class to getRootConfigClasses of WebAppInitializer.

protected Class<?>[] getRootConfigClasses() {
    return new Class<?>[] {SecurityConfig.class, PersistenceConfig.class, ServiceConfig.class};
}

The entire WebAppInitializer.java.

WebAppInitializer.java


package com.example.web.config;

import java.nio.charset.StandardCharsets;

import javax.servlet.Filter;

import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import com.example.persistence.config.PersistenceConfig;
import com.example.security.config.SecurityConfig;
import com.example.service.config.ServiceConfig;

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    /**
     *Specifies Java Config classes for non-Spring MVC, such as business logic.
     */
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] {SecurityConfig.class, PersistenceConfig.class, ServiceConfig.class};
    }

    /**
     *Specifies the Java Config class for Spring MVC.
     */
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] {MvcConfig.class};
    }

    /**
     *Specifies the URL pattern for the DispatcherServlet.
     * "/"By specifying, DispatcherServlet receives all requests.
     */
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    /**
     *Specify the Servlet filter.
     *If there are multiple filters, they will be executed in the order specified in the array.
     */
    @Override
    protected Filter[] getServletFilters() {
        return new Filter[] {
                new CharacterEncodingFilter(StandardCharsets.UTF_8.name(), true)
            };
    }
}

Summary

This completes the necessary preparations for using Spring Security. Next, we will create a login page and an administrative user creation page.

Recommended Posts

Spring5 MVC Web application development with Visual Studio Code Spring Security usage 1/3 [Preparation]
Spring5 MVC Web application development with Visual Studio Code Spring Security usage 2/3 [Page creation 1/2]
Spring5 MVC Web application development with Visual Studio Code Spring Security usage 3/3 [Page creation 2/2]
Spring5 MVC web application development with Visual Studio Code SQL Server connection
Spring5 MVC Web application development with Visual Studio Code Maven template creation
Spring5 MVC Web App Development with Visual Studio Code Hello World Creation
Spring Boot2 Web application development with Visual Studio Code SQL Server connection
Spring Boot2 Web application development with Visual Studio Code Hello World creation
Spring5 MVC Web application development with Visual Studio Code Environment construction (Installation of JDK11, Maven, Tomcat, Visual Studio Code)
Build WebAPP development environment with Java + Spring with Visual Studio Code
Start web application development with Spring Boot
Spring Security usage memo: Cooperation with Spring MVC and Boot
Build Java program development environment with Visual Studio Code
Java web application development environment construction with VS Code (struts2)
Use PlantUML with Visual Studio Code
Run WEB application with Spring Boot + Thymeleaf
A record of setting up a Java development environment with Visual Studio Code
Introduction to Java development environment & Spring Boot application created with VS Code
Experience .NET 5 with Docker and Visual Studio Code
Getting started with Java programs using Visual Studio Code
Why can I develop Java with Visual Studio Code?
Roughly the flow of web application development with Rails.
Android application development preparation 7/15
Web application development memo with MVN, Tomcat, JSP / Servlet with VScode
The first WEB application with Spring Boot-Making a Pomodoro timer-
To receive an empty request with Spring Web MVC @RequestBody
Java Config with Spring MVC
Spring Security usage memo CSRF
Spring Security usage memo Run-As
[Spring Boot] Web application creation
Spring Security Usage memo Method security
Spring Security usage memo Remember-Me
Web application development article summary
Login function with Spring Security
Java in Visual Studio Code
Web application built with docker (1)
Spring Security usage memo CORS
Spring Security usage memo test
Comparison of WEB application development with Rails and Java Servlet + JSP
How to use PlantUML with Visual Studio Code (created on October 30, 2020)
Let's make a book management web application with Spring Boot part1
Let's make a book management web application with Spring Boot part3
Let's make a book management web application with Spring Boot part2
[Probably the easiest] WEB application development with Apache Tomcat + Java Servlet
What I learned from doing Java work with Visual Studio Code