summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamal Wickramanayake <kamal@inbox.lk>2026-06-13 18:13:59 +0530
committerKamal Wickramanayake <kamal@inbox.lk>2026-06-13 18:13:59 +0530
commit6ae21cd4e51756ea14b43b82a9d500bca9fb8032 (patch)
treea330377fff7709cae00fe9d39c9281809e09aa75
parentfa880db84ec4507010a4d29b7cb0308f82553834 (diff)
Added 08-spring-security-simple
-rw-r--r--spring-boot/08-spring-security-simple/.gitignore2
-rw-r--r--spring-boot/08-spring-security-simple/README19
-rw-r--r--spring-boot/08-spring-security-simple/pom.xml50
-rw-r--r--spring-boot/08-spring-security-simple/src/main/java/com/example/spring/Application.java12
-rw-r--r--spring-boot/08-spring-security-simple/src/main/java/com/example/spring/HomeController.java13
-rw-r--r--spring-boot/08-spring-security-simple/src/main/java/com/example/spring/contact/ContactController.java34
-rw-r--r--spring-boot/08-spring-security-simple/src/main/java/com/example/spring/contact/ContactForm.java45
-rw-r--r--spring-boot/08-spring-security-simple/src/main/resources/application.properties0
-rw-r--r--spring-boot/08-spring-security-simple/src/main/resources/config/application-dev.properties10
-rw-r--r--spring-boot/08-spring-security-simple/src/main/resources/static/css/main.css92
-rw-r--r--spring-boot/08-spring-security-simple/src/main/resources/templates/contact/form.html30
-rw-r--r--spring-boot/08-spring-security-simple/src/main/resources/templates/contact/result.html14
-rw-r--r--spring-boot/08-spring-security-simple/src/main/resources/templates/index.html11
-rw-r--r--spring-boot/08-spring-security-simple/src/main/resources/templates/layout/main.html34
14 files changed, 366 insertions, 0 deletions
diff --git a/spring-boot/08-spring-security-simple/.gitignore b/spring-boot/08-spring-security-simple/.gitignore
new file mode 100644
index 0000000..3df278e
--- /dev/null
+++ b/spring-boot/08-spring-security-simple/.gitignore
@@ -0,0 +1,2 @@
+target
+.vscode
diff --git a/spring-boot/08-spring-security-simple/README b/spring-boot/08-spring-security-simple/README
new file mode 100644
index 0000000..b0fab0c
--- /dev/null
+++ b/spring-boot/08-spring-security-simple/README
@@ -0,0 +1,19 @@
+This sample project shows how to add Spring Security to a Spring Boot application.
+
+To run with support for hot swap during development, use the dev profile as follows:
+
+ mvn spring-boot:run -Dspring-boot.run.profiles=dev
+
+Two dependencies have been added to pom.xml.
+
+After starting the application, look for the default password that appears on the console.
+
+The default user name is 'user' without quotes.
+
+Access the Contact page from a web browser and observe that a CSRF token has got added to the form html automatically.
+
+The application has been modified to show a logout link in the main navigation bar.
+
+Check how that link has been added in the main.html file where the link is visible only if the user has logged in.
+
+Since all pages of the application are secured (except the login page), the logout link could have been displayed without using the sec:authorize attribute. It has been used in the web page just to show the capability. It is useful in cases where some pages are shown to unauthenticated users. \ No newline at end of file
diff --git a/spring-boot/08-spring-security-simple/pom.xml b/spring-boot/08-spring-security-simple/pom.xml
new file mode 100644
index 0000000..6a29945
--- /dev/null
+++ b/spring-boot/08-spring-security-simple/pom.xml
@@ -0,0 +1,50 @@
+<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>com.example.spring.boot</groupId>
+ <artifactId>base-config</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <relativePath>../00-config</relativePath>
+ </parent>
+
+ <artifactId>thymeleaf-common-theme</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-thymeleaf</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-validation</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-security</artifactId>
+ </dependency>
+
+ <!-- Below is not always required when Spring Security is used.
+ But in layout/main.html, the logout link definition uses a capability in this
+ library (the sec:authorize attribyte)-->
+ <dependency>
+ <groupId>org.thymeleaf.extras</groupId>
+ <artifactId>thymeleaf-extras-springsecurity6</artifactId>
+ </dependency>
+
+ <!--This
+ is to automatically reload web pages during development -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-devtools</artifactId>
+ <optional>true</optional>
+ </dependency>
+
+ </dependencies>
+
+</project> \ No newline at end of file
diff --git a/spring-boot/08-spring-security-simple/src/main/java/com/example/spring/Application.java b/spring-boot/08-spring-security-simple/src/main/java/com/example/spring/Application.java
new file mode 100644
index 0000000..4393f3f
--- /dev/null
+++ b/spring-boot/08-spring-security-simple/src/main/java/com/example/spring/Application.java
@@ -0,0 +1,12 @@
+package com.example.spring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) throws Exception {
+ SpringApplication.run(Application.class, args);
+ }
+} \ No newline at end of file
diff --git a/spring-boot/08-spring-security-simple/src/main/java/com/example/spring/HomeController.java b/spring-boot/08-spring-security-simple/src/main/java/com/example/spring/HomeController.java
new file mode 100644
index 0000000..d6ead56
--- /dev/null
+++ b/spring-boot/08-spring-security-simple/src/main/java/com/example/spring/HomeController.java
@@ -0,0 +1,13 @@
+package com.example.spring;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+public class HomeController {
+
+ @RequestMapping("/")
+ public String home() {
+ return "index";
+ }
+}
diff --git a/spring-boot/08-spring-security-simple/src/main/java/com/example/spring/contact/ContactController.java b/spring-boot/08-spring-security-simple/src/main/java/com/example/spring/contact/ContactController.java
new file mode 100644
index 0000000..20c482d
--- /dev/null
+++ b/spring-boot/08-spring-security-simple/src/main/java/com/example/spring/contact/ContactController.java
@@ -0,0 +1,34 @@
+package com.example.spring.contact;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PostMapping;
+
+import jakarta.validation.Valid;
+
+@Controller
+public class ContactController {
+
+ @GetMapping("/contact")
+ public String showForm(Model model) {
+ model.addAttribute("contactForm", new ContactForm());
+ return "contact/form";
+ }
+
+ @PostMapping("/contact")
+ public String processSubmission(@Valid @ModelAttribute ContactForm contactForm, BindingResult bindingResult,
+ Model model) {
+ if (bindingResult.hasErrors()) {
+ return "contact/form";
+ }
+
+ // Do whatever needed with the submitted data here.
+ // For example, invoke a method in a service/componet bean to send an email to contact person.
+
+ return "contact/result";
+ }
+
+}
diff --git a/spring-boot/08-spring-security-simple/src/main/java/com/example/spring/contact/ContactForm.java b/spring-boot/08-spring-security-simple/src/main/java/com/example/spring/contact/ContactForm.java
new file mode 100644
index 0000000..c641edf
--- /dev/null
+++ b/spring-boot/08-spring-security-simple/src/main/java/com/example/spring/contact/ContactForm.java
@@ -0,0 +1,45 @@
+package com.example.spring.contact;
+
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Size;
+
+public class ContactForm {
+
+ @Pattern(regexp = "^[ a-zA-Z]+$", message = "Name should only include English letters")
+ @NotBlank(message = "Name is required")
+ private String name;
+
+ @Email(message = "Must be a valid email")
+ @NotBlank(message = "Email is required")
+ private String email;
+
+ @Size(min = 10, message = "Message must be at least 10 characters long")
+ private String message;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+}
diff --git a/spring-boot/08-spring-security-simple/src/main/resources/application.properties b/spring-boot/08-spring-security-simple/src/main/resources/application.properties
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/spring-boot/08-spring-security-simple/src/main/resources/application.properties
diff --git a/spring-boot/08-spring-security-simple/src/main/resources/config/application-dev.properties b/spring-boot/08-spring-security-simple/src/main/resources/config/application-dev.properties
new file mode 100644
index 0000000..f0f380b
--- /dev/null
+++ b/spring-boot/08-spring-security-simple/src/main/resources/config/application-dev.properties
@@ -0,0 +1,10 @@
+# This file contains settings used during development.
+# If using Maven to run, try the following command:
+# mvn spring-boot:run -Dspring-boot.run.profiles=dev
+
+# Disable caching for static resources
+spring.web.resources.cache.period=0
+spring.thymeleaf.cache=false
+
+# Optional: Tell DevTools to watch changes but never restart the backend server for CSS
+spring.devtools.restart.exclude=static/**,public/**,templates/**
diff --git a/spring-boot/08-spring-security-simple/src/main/resources/static/css/main.css b/spring-boot/08-spring-security-simple/src/main/resources/static/css/main.css
new file mode 100644
index 0000000..edd53ea
--- /dev/null
+++ b/spring-boot/08-spring-security-simple/src/main/resources/static/css/main.css
@@ -0,0 +1,92 @@
+body {
+ font-size: 1.125em;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ line-height: 1.6em;
+ color: rgb(32, 34, 36);;
+ background-color: #FFF;
+ padding: 10px 5px;
+}
+
+a {
+ color: #1475AC;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+ul li {
+ padding-bottom: 0.5em;
+}
+
+header {
+ text-align: left;
+ font-size: 1.2em;
+}
+
+header h1 {
+ margin-top: 0;
+ margin-bottom: 20px;
+}
+
+header a {
+ color: #000000;
+ text-decoration: none;
+}
+
+.main-nav {
+ margin-top: 0;
+ padding: 0;
+}
+
+.main-nav ul {
+ margin: 0;
+ padding : 0;
+ list-style-type: none;
+ background-color: #F6F8F8;
+ border: 1px solid #eee;
+}
+
+.main-nav ul li {
+ margin-left: 0;
+ display: inline;
+ padding: 0 8px;
+ border-left: 1px solid #F9F9FF;
+ border-right: 1px solid #F9F9FF;
+}
+
+.main-nav ul li:hover {
+ background-color: white;
+ border-left: 1px solid #addfff;
+ border-right: 1px solid #addfff;
+}
+
+.main-nav ul li a {
+ color: #555;
+ font-weight: bold;
+}
+
+.main-nav ul li ai:hover {
+ color: #000;
+}
+
+footer {
+ margin-top: 20px;
+ font-size: 85%;
+ border-top: 1px solid #CCC;
+}
+
+.form-field-container {
+ margin-top: 8px;
+ margin-bottom: 8px;
+}
+
+.form-field-container label {
+ display: inline-block;
+ width: 5em;
+}
+
+.form-field-container .validation-error {
+ color: red;
+} \ No newline at end of file
diff --git a/spring-boot/08-spring-security-simple/src/main/resources/templates/contact/form.html b/spring-boot/08-spring-security-simple/src/main/resources/templates/contact/form.html
new file mode 100644
index 0000000..7debe1f
--- /dev/null
+++ b/spring-boot/08-spring-security-simple/src/main/resources/templates/contact/form.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html xmlns:th="http://www.thymeleaf.org" th:replace="~{layout/main :: layout(title='Contact Us', content=~{::main})}">
+
+<body>
+ <main>
+ <form th:action="@{/contact}" th:object="${contactForm}" method="post">
+ <div class="form-field-container">
+ <label>Name</label>
+ <input type="text" th:field="*{name}" placeholder="Your name" />
+ <div class="validation-error" th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></div>
+ </div>
+
+ <div class="form-field-container">
+ <label>Email</label>
+ <input type="email" th:field="*{email}" placeholder="Your email" />
+ <div class="validation-error" th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></div>
+ </div>
+
+ <div class="form-field-container">
+ <label>Message</label>
+ <textarea th:field="*{message}" placeholder="Your message"></textarea>
+ <div class="validation-error" th:if="${#fields.hasErrors('message')}" th:errors="*{message}"></div>
+ </div>
+
+ <button type="submit">Send</button>
+ </form>
+ </main>
+</body>
+
+</html> \ No newline at end of file
diff --git a/spring-boot/08-spring-security-simple/src/main/resources/templates/contact/result.html b/spring-boot/08-spring-security-simple/src/main/resources/templates/contact/result.html
new file mode 100644
index 0000000..d1bda9a
--- /dev/null
+++ b/spring-boot/08-spring-security-simple/src/main/resources/templates/contact/result.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html xmlns:th="http://www.thymeleaf.org" th:replace="~{layout/main :: layout(title='Contact Us', content=~{::main})}">
+
+<body>
+ <main>
+ <p>We received your message.</p>
+
+ <p th:text="'Thank you ' + ${contactForm.name} + '.'" />
+
+ <a th:href="@{/contact}">Try again</a>
+ </main>
+</body>
+
+</html> \ No newline at end of file
diff --git a/spring-boot/08-spring-security-simple/src/main/resources/templates/index.html b/spring-boot/08-spring-security-simple/src/main/resources/templates/index.html
new file mode 100644
index 0000000..b2f59f2
--- /dev/null
+++ b/spring-boot/08-spring-security-simple/src/main/resources/templates/index.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html xmlns:th="http://www.thymeleaf.org" th:replace="~{layout/main :: layout(title='Welcome', content=~{::main})}">
+
+<body>
+ <main>
+ <p>Hello! This is the home page content.</p>
+ <p>Use the navigation links to explore other pages.</p>
+ </main>
+</body>
+
+</html> \ No newline at end of file
diff --git a/spring-boot/08-spring-security-simple/src/main/resources/templates/layout/main.html b/spring-boot/08-spring-security-simple/src/main/resources/templates/layout/main.html
new file mode 100644
index 0000000..815ff3d
--- /dev/null
+++ b/spring-boot/08-spring-security-simple/src/main/resources/templates/layout/main.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html xmlns:th="http://www.thymeleaf.org"
+ xmlns:sec="http://thymeleaf.org/extras/spring-security"
+ th:fragment="layout(title, content)">
+
+<head>
+ <title th:text="|${title} - ABC App|">Base title not shown</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <link rel="stylesheet" th:href="@{/css/main.css}" />
+</head>
+
+<body>
+ <header>
+ <h1>ABC App</h1>
+ </header>
+
+ <nav class="main-nav">
+ <ul>
+ <li><a th:href="@{/}">Home</a></li>
+ <li><a th:href="@{/contact}">Contact Us</a></li>
+ <li><a th:href="@{/logout}" sec:authorize="isAuthenticated()">Logout</a></li>
+ </ul>
+ </nav>
+
+ <h3 th:text="|${title}|">Page content area title</h3>
+
+ <th:block th:replace="${content}" />
+
+ <footer>
+ Copyright &copy; 2026 Example Company. All rights reserved.
+ </footer>
+</body>
+
+</html> \ No newline at end of file