Spring Security is a framework that provides authentication / authorization functions for applications created with Spring. You can add the following functions to your Web application just by adding a few settings.
--Vulnerability countermeasures --Session fixation measures --Clickjacking measures --CSRF measures --Authentication / authorization --Login mechanism using forms authentication, etc. --Access control using roles
This time, we will use the Spring Security feature to achieve the following:
--Authentication
--Form authentication using user and password
-Use the user and password that you have in memory (although you can do it in the database)
--Returns an error message if the user or password is wrong
--Authorization
--Separate roles for administrator account and general user
--Administrators can access / admin
and / user
--General users can only access / user
This time, I will describe the procedure to enable security for Spring Boot application.
Spring Boot uses 1.4 series and Spring Securiry uses 4.x series. Please note that different versions have different grammars.
The sample code that actually works is published on GitHub. If you can read the code, please go to the following directly.
This time, we will build the server side with Spring Boot and use Tymeleaf as the template engine to draw the screen. The following libraries are required for that.
spring-boot-starter-web
spring-boot-starter-thymeleaf
In addition, the following libraries are required to enable the Spring Securirty function.
spring-boot-starter-security
spring-security-web
spring-security-config
This time, let's add the following libraries to integrate Spring Security and Tymeleaf.
thymeleaf-extras-springsecurity4
In summary, the following settings will be added to build.gradle
.
dependencies {
compile("org.springframework.boot:spring-boot-starter-web:1.4.1.RELEASE")
compile("org.springframework.boot:spring-boot-starter-thymeleaf:1.4.1.RELEASE")
compile("org.springframework.boot:spring-boot-starter-security:1.4.1.RELEASE")
compile("org.thymeleaf.extras:thymeleaf-extras-springsecurity4:2.1.3.RELEASE")
compile("org.springframework.security:spring-security-core:4.2.3.RELEASE")
compile("org.springframework.security:spring-security-web:4.2.3.RELEASE")
compile("org.springframework.security:spring-security-config:4.2.3.RELEASE")
}
Controller
First, create a screen for the administrator and a screen for general users.
ʻAdminController for administrators and ʻUserController
for general users, respectively.
@Controller
@RequestMapping("/admin")
@Slf4j
public class AdminController {
@RequestMapping
public String index() {
return "admin";
}
}
@Controller
@RequestMapping("/user")
@Slf4j
public class UserController {
@RequestMapping
public String index() {
return "user";
}
}
Template
Prepare the Tymeleaf template corresponding to the above Controller.
Let's say ʻadmin.html and ʻuser.html
, respectively (see sample code for details).
After that, create ʻApplication.javaaccording to the method of SpringBoot, and if
gradle bootRun` passes, you are ready.
Now that we're ready, let's move on to Spring Security.
Config
First, create a configuration class to enable Spring Security. Spring Security is enabled by providing a class that inherits WebSecurityConfigurerAdapter
and has @EnableWebSecurity
.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static String ROLE_USER = "USER";
private static String ROLE_ADMIN = "ADMIN";
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/user").hasAnyRole(ROLE_USER, ROLE_ADMIN)
.antMatchers("/admin").hasRole(ROLE_ADMIN)
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/user")
.usernameParameter("username")
.passwordParameter("password")
.permitAll()
.and()
.logout()
.permitAll()
.and()
.csrf();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/*.html", "/*.css")
.antMatchers("/bootstrap/**");
}
}
To briefly explain what we are doing in the above example,
#configure(HttpSecurity)
--Enable access control
-- / user
should be accessible by the roles of general user and administrator user
--/ admin
can only be accessed by admin users
--Enable form login
--The URL of the login page should be / login
--Username is ʻusernamePassword is property name
password--Transition to
/ user` if login is successful
--Exceptionally disable access control for login pages
--Exceptionally disable access control for logout pages
--Enable tokens for CSRF#configure(WebSecurity)
--With the default settings, access control will be applied to static files as well, so the following are excluded.
- html
- css
--BootStrap template fileLike this. I think that the implementation is such that you can imagine the settings.
This time, in order to work with Tymeleaf, it is necessary to set an instance of TemplateResolver
in SpringTemplateEngine
. The specific implementation is as follows.
@Autowired
public TemplateResolver templateResolver;
@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.addDialect(new SpringSecurityDialect());
engine.setTemplateResolver(templateResolver);
return engine;
}
In addition, set the user name and password information used for authentication. This time, for simplification of implementation, it is set in-memory instead of from the database. See the sample code for ʻUserDto`.
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
UserDto support = supportUser();
UserDto admin = adminUser();
auth.inMemoryAuthentication()
.withUser(support.getUsername()).password(support.getPassword()).roles(ROLE_USER)
.and()
.withUser(admin.getUsername()).password(admin.getPassword()).roles(ROLE_ADMIN);
}
@Bean
@ConfigurationProperties("inmotion.admin")
public UserDto adminUser() {
return new UserDto();
}
@Bean
@ConfigurationProperties("inmotion.user")
public UserDto supportUser() {
return new UserDto();
}
I will leave the actual user name and password in ʻapplication.yml`.
inmotion:
user:
username: user
password: pass12345
admin:
username: admin
password: pass12345
Controller After that, prepare a Controller corresponding to the login screen,
@Controller
public class AuthenticationController {
@RequestMapping({"/", "/login"})
public String login(@RequestParam(value = "error", required = false) String error, Model model) {
if (error != null) {
//Processing to output an error message
}
return "login";
}
}
Template
All you have to do is prepare a login form for POST with / login
.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
<form class="form-signin" method="post" th:action="@{/login}">
<div class="alert alert-dismissible alert-danger" th:if="${errorMessage}">
<button type="button" class="close" data-dismiss="alert">×</button>
<p th:text="${errorMessage}"></p>
</div>
<h2 class="form-signin-heading">Please sign in</h2>
<label for="username" class="sr-only">Username</label>
<input type="text" id="username" name="username" class="form-control" placeholder="UserName"/>
<label for="password" class="sr-only">Password</label>
<input type="password" id="password" name="password" class="form-control" placeholder="Password"/>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
</div>
</body>
</html>
Start the application with gradle bootRun
and
--You must be able to log in with the specified user name and password. --Access control is enabled --403 is returned when trying to access an unauthorized screen --A token for CSRF measures has been generated.
Let's check.
Recommended Posts