Skip to content

Commit 94f88c4

Browse files
committed
Add security and actuator
1 parent bb7ac44 commit 94f88c4

File tree

4 files changed

+179
-4
lines changed

4 files changed

+179
-4
lines changed

spring-boot/spring-boot-codefirst/build.gradle

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
plugins {
2-
id 'org.springframework.boot' version '2.2.6.RELEASE'
2+
id 'org.springframework.boot' version '2.3.0.RELEASE'
33
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
44
id 'java'
55
}
66

77
group = 'io.reflectoring'
88
version = '0.0.1-SNAPSHOT'
9-
sourceCompatibility = '14'
9+
sourceCompatibility = '1.8'
1010

1111
configurations {
1212
compileOnly {
@@ -19,7 +19,9 @@ repositories {
1919
}
2020

2121
dependencies {
22+
implementation 'org.springframework.boot:spring-boot-starter-actuator'
2223
implementation 'org.springframework.boot:spring-boot-starter-web'
24+
implementation 'org.springframework.boot:spring-boot-starter-security'
2325
implementation 'org.springdoc:springdoc-openapi-ui:1.3.3'
2426
compileOnly 'org.projectlombok:lombok'
2527
annotationProcessor 'org.projectlombok:lombok'
Lines changed: 166 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,178 @@
11
package io.reflectoring.codefirst;
22

3+
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
4+
import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn;
5+
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
6+
import io.swagger.v3.oas.annotations.info.Contact;
7+
import io.swagger.v3.oas.annotations.info.Info;
8+
import io.swagger.v3.oas.annotations.info.License;
9+
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
10+
import io.swagger.v3.oas.annotations.security.SecurityScheme;
11+
import io.swagger.v3.oas.annotations.servers.Server;
12+
import io.swagger.v3.oas.annotations.tags.Tag;
13+
import lombok.AllArgsConstructor;
14+
import lombok.Data;
15+
import lombok.NoArgsConstructor;
316
import org.springframework.boot.SpringApplication;
417
import org.springframework.boot.autoconfigure.SpringBootApplication;
18+
import org.springframework.context.annotation.Bean;
19+
import org.springframework.http.HttpStatus;
20+
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
21+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
22+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
23+
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
24+
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
25+
import org.springframework.security.crypto.password.PasswordEncoder;
26+
import org.springframework.web.bind.annotation.*;
27+
28+
import javax.annotation.PostConstruct;
29+
import java.util.List;
30+
import java.util.UUID;
31+
import java.util.stream.Collectors;
32+
import java.util.stream.Stream;
33+
34+
35+
@RequestMapping("/api/todos")
36+
@Tag(name = "Todo API", description = "euismod in pellentesque massa placerat duis ultricies lacus sed turpis")
37+
@SecurityRequirement(name = "api")
38+
interface TodoApi {
39+
40+
@GetMapping
41+
@ResponseStatus(code = HttpStatus.OK)
42+
List<Todo> findAll();
43+
44+
@GetMapping("/{id}")
45+
@ResponseStatus(code = HttpStatus.OK)
46+
Todo findById(@PathVariable String id);
47+
48+
@PostMapping
49+
@ResponseStatus(code = HttpStatus.CREATED)
50+
Todo save(@RequestBody Todo todo);
51+
52+
@PutMapping("/{id}")
53+
@ResponseStatus(code = HttpStatus.OK)
54+
Todo update(@PathVariable String id, @RequestBody Todo todo);
55+
56+
@DeleteMapping("/{id}")
57+
@ResponseStatus(code = HttpStatus.NO_CONTENT)
58+
void delete(@PathVariable String id);
59+
}
60+
61+
@RequestMapping("/unsecured")
62+
@Tag(name = "Unsecured API", description = "aliquet nec ullamcorper sit amet risus nullam eget felis eget")
63+
interface UnsecuredApi {
64+
65+
@GetMapping
66+
@ResponseStatus(code = HttpStatus.OK)
67+
String unsecured();
68+
}
569

670
@SpringBootApplication
771
public class CodeFirstApplication {
8-
972
public static void main(String[] args) {
1073
SpringApplication.run(CodeFirstApplication.class, args);
1174
}
75+
}
76+
77+
@OpenAPIDefinition(
78+
info = @Info(
79+
title = "Code-First Approach (reflectoring.io)",
80+
description = "" +
81+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur et rhoncus quam. Aenean quis augue ac eros pulvinar malesuada. " +
82+
"In sagittis elit egestas tincidunt iaculis. " +
83+
"Donec eu lacus vitae nulla varius consectetur a vel quam. Aliquam erat volutpat. Duis eget ullamcorper tellus",
84+
contact = @Contact(name = "Reflectoring", url = "https://reflectoring.io", email = "[email protected]"),
85+
license = @License(name = "MIT Licence", url = "https://github.com/thombergs/code-examples/blob/master/LICENSE")),
86+
servers = @Server(url = "http://localhost:8080")
87+
)
88+
@SecurityScheme(scheme = "basic", type = SecuritySchemeType.HTTP, name = "api", in = SecuritySchemeIn.HEADER)
89+
class OpenAPIConfiguration {
90+
}
91+
92+
@EnableWebSecurity
93+
class SecurityConfiguration extends WebSecurityConfigurerAdapter {
1294

95+
@Override
96+
protected void configure(HttpSecurity http) throws Exception {
97+
http.authorizeRequests()
98+
.antMatchers("/unsecured", "/swagger-ui/**", "/reflectoring-openapi/**").permitAll()
99+
.anyRequest().authenticated()
100+
.and()
101+
.httpBasic();
102+
}
103+
104+
@Override
105+
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
106+
auth.inMemoryAuthentication()
107+
.withUser("admin")
108+
.password(passwordEncoder().encode("password"))
109+
.authorities("ADMIN");
110+
}
111+
112+
@Bean
113+
public PasswordEncoder passwordEncoder() {
114+
return new BCryptPasswordEncoder();
115+
}
13116
}
117+
118+
@NoArgsConstructor
119+
@AllArgsConstructor
120+
@Data
121+
class Todo {
122+
private String id;
123+
private String text;
124+
}
125+
126+
@RestController
127+
class TodoController implements TodoApi {
128+
129+
private List<Todo> todos;
130+
131+
@Override
132+
public List<Todo> findAll() {
133+
return todos;
134+
}
135+
136+
@Override
137+
public Todo findById(String id) {
138+
return todos.stream().filter(todo -> todo.getId().equals(id)).findFirst().orElseGet(null);
139+
}
140+
141+
@Override
142+
public Todo save(Todo todo) {
143+
todos.add(todo);
144+
return todo;
145+
}
146+
147+
@Override
148+
public Todo update(String id, Todo todo) {
149+
for (Todo t : todos) {
150+
if (t.getId().equals(id)) {
151+
t.setText(todo.getText());
152+
}
153+
}
154+
155+
return todo;
156+
}
157+
158+
@Override
159+
public void delete(String id) {
160+
todos.removeIf(t -> t.getId().equals(id));
161+
}
162+
163+
@PostConstruct
164+
public void onInit() {
165+
todos = Stream.of("Groceries", "Lisa's birthday")
166+
.map(todo -> new Todo(UUID.randomUUID().toString(), todo))
167+
.collect(Collectors.toList());
168+
}
169+
}
170+
171+
@RestController
172+
class Unsecured implements UnsecuredApi {
173+
174+
@Override
175+
public String unsecured() {
176+
return "unsecured";
177+
}
178+
}

spring-boot/spring-boot-codefirst/src/main/resources/application.properties

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
springdoc:
2+
api-docs:
3+
path: /reflectoring-openapi
4+
show-actuator: true
5+
management:
6+
endpoints:
7+
web:
8+
exposure:
9+
include: "*"

0 commit comments

Comments
 (0)