Spring Security ด้วย Spring Boot 2.0
วันนี้ผมจะมีบทความง่าย ๆ เกี่ยวกับการสร้าง secured endpoints ด้วย Spring Security ใน Sping Boot 2.0.x นะครับ
เราจะมาสร้าโปรเจคส์ด้วย maven กันนะครับ โครงสร้างตามนี้ครับ
สร้าง pom ไฟล์ตามนี้เลยครับ
<?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.zengcode.sping.security</groupId>
<artifactId>zengcode-spring-security</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<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>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
ต่อไปเรามา Extends WebSecurityConfigurerAdapter และกำหนด security rules กัน
กำหนด user “admin” ให้เข้าถึง /admin และ /customer ได้
กำหนด user “customer” ให้เข้าถึง/customer ได้
package com.zengcode.spring.security.configuration;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.access.AccessDeniedHandler;
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/", "/welcome").permitAll()
.antMatchers("/admin").hasAnyRole("ADMIN")
.antMatchers("/customer").hasAnyRole("CUSTOMER", "ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.defaultSuccessUrl("/welcome")
.and()
.logout()
.permitAll();
}
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("customer").password("{noop}123").roles("CUSTOMER")
.and()
.withUser("admin").password("{noop}123").roles("ADMIN");
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/templates/**","/resources/**", "/static/**", "/css/**", "/js/**", "/images/**");
}
}
ไฟล์ login.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spring Security Tutorial</title>
<link rel="stylesheet" type="text/css" th:href="@{/css/login.css}"/>
<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.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<form th:action="@{/login}" method="POST" class="form-signin">
<h3 class="form-signin-heading" th:text="Welcome"></h3>
<br/>
<input type="text" id="username" name="username" th:placeholder="Username"
class="form-control"/> <br/>
<input type="password" th:placeholder="Password"
id="password" name="password" class="form-control"/> <br/>
<div align="center" th:if="${param.error}">
<p style="font-size: 20; color: #FF1C19;">Email or Password invalid, please verify</p>
</div>
<button class="btn btn-lg btn-primary btn-block" name="Submit" value="Login" type="Submit"
th:text="Login"></button>
</form>
</div>
</body>
</html>
ส่วนไฟล์ html อื่นๆ ก็แค่ print static text ธรรมดาครับ
เมื่อรัน project แล้วพยายามเข้า http://localhost:8080/admin หรือ /customer จะ redirect ไปหน้า http://localhost:8080/login อัตโนมัตครับ
เมื่อ login แล้วก็จะเข้าไปหน้าต่างๆ ที่มี permission แต่ถ้าไม่มี permission เช่น login เป็น customer แต่เข้าหน้า admin ก็จะ redirect ไปหน้า error page ครับ