Sunday, December 8, 2019

Spring Security - Cấu hình Security cho Web MVC trong Spring Boot

Trong bài viết này, tôi sẽ hướng dẫn bạn cách cấu hình Security cho ứng dụng web SpringMVC.

I. Mục tiêu:

Chúng ta sẽ tạo ứng dụng web SpringBoot MVC như bên dưới:



Với 5 urls:

- "/": được truy cập bởi tất cả mọi người.


- "/login": trang dùng để login.


- "/user": phải xác thực và được truy cập với người dùng có ROLE là {USER, ADMIN}.


- "/admin": được truy cập bởi người dùng có ROLE là ADMIN.



- "/403": HTTP Error 403 cấm truy cập.

II. Thực hành:

Các bước thực hiện:

- Tạo project Spring Boot.
- Tạo Controller.
- Tạo các Pages View.
- Cấu hình WebSecurity.

1. Tạo project Spring Boot.

Sử dụng IDE ưu thích của bạn để tạo project SpringBoot với các dependencies như bên dưới:


<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

 

2. Tạo Controller.

package com.mpt.springsecurity.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class WebController {
  
    @RequestMapping(value={"/","home"})
        public String home(){
            return "home";
        }
 
    @RequestMapping(value="/user")
    public String user(){
        return "user";
    }
    @RequestMapping(value="/admin")
    public String admin(){
        return "admin";
    }
  
    @RequestMapping(value="/login")
    public String login(){
        return "login";
    }
  
    @RequestMapping(value="/403")
    public String Error403(){
        return "403";
    }
}

 

3. Tạo các trang View.

 

home.html


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:th="http://www.thymeleaf.org"
  xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Security with Spring Boot</title>
</head>
<body>
  <h1>Hello, This is Home page!</h1>
  <a style="color: blue" th:href="@{/user}">User Page</a>
  <br />
  <a style="color: blue" th:href="@{/admin}">Admin Page</a>
</body>
</html>

 

user.html


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:th="http://www.thymeleaf.org"
  xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Welcome Security with Spring Boot!</title>
</head>
<body>
  <h1>Hello, the page is for Users!</h1>
  <a style="color: blue" th:href="@{/}">Home</a>
  <form th:action="@{/logout}" method="post">
    <input type="submit" value="Sign Out" />
  </form>
</body>
</html>

 

admin.html


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:th="http://www.thymeleaf.org"
  xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Welcome Security with Spring Boot!</title>
</head>
<body>
  <h1>Hello, the page is for Admin!</h1>
  <a style="color: blue" th:href="@{/}">Home</a>
  <form th:action="@{/logout}" method="post">
    <input type="submit" value="Sign Out" />
  </form>
</body>
</html>

 

login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:th="http://www.thymeleaf.org"
  xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
  <title>Welcome Security with Spring Boot!</title>
  <meta charset="utf-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
  <link rel="stylesheet"
    href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"/>
  <script
    src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"> 
</script>
  <script
    src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"> 
</script>
</head>
<body class="container" style="margin:50px">
  <div class="row col-sm-6"
        style="border: 1px ridge #003312; padding:20px; float: none;
  margin: 0 auto;">
    <h5 class="text-center" style="font-size: 25px">Sign In</h5>
    <div th:if="${param.error}">
      <p style="color: red">UserName or PassWord is wrong. Please
        check again!</p>
  
    </div>
    <div th:if="${param.logout}">
      <h1 style="color: blue">Logged out.</h1>
    </div>
    <form th:action="@{/login}" method="post">
      <div class="form-group">
        <label for="username">User Name: </label>
        <input type="text" class="form-control" id="username"
  placeholder="Enter UserName" name="username"/>
      </div>
      <div class="form-group">
        <label for="password">Password: </label>
        <input type="password" class="form-control" id="password" 
  placeholder="Enter Password" name="password"/>
      </div>
      <button type="submit" class="btn btn-primary btn-block">Submit</button>
    </form>
  </div>
</body>
</html>

 

403.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:th="http://www.thymeleaf.org"
  xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Security with Spring Boot</title>
</head>
<body>
  <h1>Access is Denied!</h1>
  <a style="color: blue" th:href="@{/}">Home</a>
  <form th:action="@{/logout}" method="post">
    <input type="submit" value="Sign Out" />
  </form>
</body>
</html>

 

4. Cấu hình WebSecurity.

Chúng ta sử dụng WebSecurityConfigurerAdapter để tạo ra một WebSecurityConfigurer

Ứng dụng web này có 2 người dùng:
- Admin: admin/admin.
- User: user/user.

package com.mpt.springsecurity.config;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
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 
.WebSecurityConfigurerAdapter;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
        http
          .authorizeRequests()
          .antMatchers("/","/home").permitAll()
          .antMatchers("/admin").hasRole("ADMIN")
          .anyRequest().authenticated()
          .and()
          .formLogin()
          .loginPage("/login")
          .permitAll()
          .and()
          .logout()
          .permitAll();
        http.exceptionHandling().accessDeniedPage("/403");
  }
  @Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) 
  throws Exception {
        auth
         .inMemoryAuthentication()
          .withUser("user").password("{noop}user").roles("USER")
.and()
         .withUser("admin").password("{noop}admin").roles("ADMIN");
    }
}