Skip to content

Commit 8c4660d

Browse files
committed
ApplicationUserPermission and ApplicationUserRole have been defined.
1 parent 7166e1f commit 8c4660d

File tree

5 files changed

+188
-30
lines changed

5 files changed

+188
-30
lines changed

day-10/api/Security.md

Lines changed: 137 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# 1. Basic Authentication
2+
23
## 1.1. Dependency
34

45
Öncelikle projeye yeni bir bağımlılık eklenir.
@@ -9,19 +10,20 @@
910
<artifactId>spring-boot-starter-security</artifactId>
1011
</dependency>
1112
```
12-
Yukarıdkai bağımlılık ifadesiyle artık API güvenliği ilk adım atılır. Konsol ortamında verilen **generated security password** ve **user** kullanıcı adı ile oturum açılabilir.
1313

14-
* Logout olma şansı yoktur.
15-
* Kullanıcı adı ve şifresine müdahale edilemez.
14+
Yukarıdkai bağımlılık ifadesiyle artık API güvenliği ilk adım atılır. Konsol ortamında verilen **generated security password** ve **user** kullanıcı adı ile oturum açılabilir.
15+
16+
- Logout olma şansı yoktur.
17+
- Kullanıcı adı ve şifresine müdahale edilemez.
1618

1719
## 1.2. Application Security Config
1820

1921
**security/config** gibi bir isimle yeni bir klasör projeye dahil edilir.
2022

2123
Gelen Request yapılarını hangi kurallara göre cevap verileceğini belirlemek üzere **ApplicationSecurityConfig** sınıfı kullanılır.
22-
Bu sınıf **WebSecurityConfigurerAdapter** sınıfından kalıtılır.
24+
Bu sınıf **WebSecurityConfigurerAdapter** sınıfından kalıtılır.
2325

24-
**config** metodu (HttpSecurity imzalı olanı) **Override** edilir.
26+
**config** metodu (HttpSecurity imzalı olanı) **Override** edilir.
2527

2628
```java
2729
@Configuration
@@ -35,8 +37,9 @@ public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {
3537
}
3638
```
3739

38-
## 1.3. Authentication Nasıl Yapılır?
39-
Bu metot üzerinde authentication işleminin nasıl yapılması gerektiği tanımlanır. Basic Authentication ile API güvenliğini sağlayalım.
40+
## 1.3. Authentication Nasıl Yapılır?
41+
42+
Bu metot üzerinde authentication işleminin nasıl yapılması gerektiği tanımlanır. Basic Authentication ile API güvenliğini sağlayalım.
4043

4144
```java
4245
@Configuration
@@ -54,30 +57,29 @@ public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {
5457
}
5558
```
5659

57-
Bu işlem sonucunda herhangi bir kaynak üzerinden GET, POST, PUT ve DELETE işlemlerinin yapılması tavsiye edilir.
58-
User ve password bilgisi girilmeden hiçbir http isteği yanıtlanmaz iken; user ve password bilgisi bir Authorization header ifadesiyle gönderildiğinde yalnızca GET isteklerinin yanıtlandığı ancak POST, PUT ve DELETE gibi işlemlerin ise yanıtlanmadığı (Forbidden) yani yasaklandığı görülür.
60+
Bu işlem sonucunda herhangi bir kaynak üzerinden GET, POST, PUT ve DELETE işlemlerinin yapılması tavsiye edilir.
61+
User ve password bilgisi girilmeden hiçbir http isteği yanıtlanmaz iken; user ve password bilgisi bir Authorization header ifadesiyle gönderildiğinde yalnızca GET isteklerinin yanıtlandığı ancak POST, PUT ve DELETE gibi işlemlerin ise yanıtlanmadığı (Forbidden) yani yasaklandığı görülür.
5962

6063
![Basic Authentication](http://www.zafercomert.com/medya/java/springSecurity-BasicAuth.svg)
6164

62-
63-
# 2. UserDetailsService
65+
# 2. UserDetailsService
6466

6567
## 2.1. UserDetailsService
6668

67-
**UserDetailService** üzerinden kullanıcı tanımları gerçekleştirebilir. Bu noktada kullanıcı bilgilerini tutmak üzere **InMemoryUserDetailsManager** kullanıyoruz.
69+
**UserDetailService** üzerinden kullanıcı tanımları gerçekleştirebilir. Bu noktada kullanıcı bilgilerini tutmak üzere **InMemoryUserDetailsManager** kullanıyoruz.
6870

69-
Ancak **UserDetailService** implemente eden daha farklı sınıflar da vardır. Detaylar için resmi dokümantasyon incelenebilir [Interface UserDetailsService](https://docs.spring.io/spring-security/site/docs/3.2.8.RELEASE/apidocs/org/springframework/security/core/userdetails/UserDetailsService.html).
71+
Ancak **UserDetailService** implemente eden daha farklı sınıflar da vardır. Detaylar için resmi dokümantasyon incelenebilir [Interface UserDetailsService](https://docs.spring.io/spring-security/site/docs/3.2.8.RELEASE/apidocs/org/springframework/security/core/userdetails/UserDetailsService.html).
7072

71-
**UserDetailService** interface yapısını implemente eden sınıflar:
73+
**UserDetailService** interface yapısını implemente eden sınıflar:
7274

73-
* CachingUserDetailsService,
74-
* InMemoryDaoImpl,
75-
* *InMemoryUserDetailsManager*,
76-
* JdbcDaoImpl,
77-
* JdbcUserDetailsManager,
78-
* LdapUserDetailsManager,
79-
* LdapUserDetailsService,
80-
* UserDetailsServiceWrapper
75+
- CachingUserDetailsService,
76+
- InMemoryDaoImpl,
77+
- _InMemoryUserDetailsManager_,
78+
- JdbcDaoImpl,
79+
- JdbcUserDetailsManager,
80+
- LdapUserDetailsManager,
81+
- LdapUserDetailsService,
82+
- UserDetailsServiceWrapper
8183

8284
```java
8385
@Override
@@ -103,11 +105,12 @@ protected UserDetailsService userDetailsService() {
103105
.build();
104106

105107
return new InMemoryUserDetailsManager(admin, editor, user);
106-
}
108+
}
107109
```
110+
108111
> UserDetailsService de bir konfigürasyon ifadesidir. Bu nedenle @Bean annotation yapısı mutlaka bu metodun üzerine eklenmelidir.
109112
110-
Uygulamanın bu haliyle yukarıda verilen kullanıcı adı ve şifreler ile artık API test edilebilir durumdadur.
113+
Uygulamanın bu haliyle yukarıda verilen kullanıcı adı ve şifreler ile artık API test edilebilir durumdadur.
111114

112115
## 2.2 PasswordEncoder
113116

@@ -122,7 +125,7 @@ public class PasswordConfig {
122125
}
123126
```
124127

125-
Injection unutulmamalıdır:
128+
Injection unutulmamalıdır:
126129

127130
```java
128131
private final PasswordEncoder passwordEncoder;
@@ -148,3 +151,112 @@ private final PasswordEncoder passwordEncoder;
148151
.httpBasic();
149152
}
150153
```
154+
155+
## 3. Roles and Permissions
156+
157+
## 3.1. Google Guava
158+
159+
Öncelikle projemize Google Guava bağımlılığını ekleyeceğiz [Google Guava](https://github.com/google/guava).
160+
161+
> Guava, yeni koleksiyon türleri (çoklu harita ve çoklu küme gibi), değişmez koleksiyonlar, bir grafik kitaplığı ve eşzamanlılık için yardımcı programları içeren Google'ın temel Java kitaplıkları kümesidir.
162+
> pom.xml dosyasına aşağıdaki bağımlılık eklenir.
163+
164+
```xml
165+
<dependency>
166+
<groupId>com.google.guava</groupId>
167+
<artifactId>guava</artifactId>
168+
<version>28.1-jre</version>
169+
</dependency>
170+
```
171+
172+
## 3.2. ApplicationUserRole
173+
174+
ApplicationUserRole içerisinde uygulamadaki rol tanımlarını gerçekleştirmeye çalışıyoruz. Bu kapsamda Admin, Editor ve User rollerinin tanımını enum formatında gerçekleştiriyoruz.
175+
176+
```java
177+
public enum ApplicationUserRole {
178+
ADMIN(Sets.newHashSet(BOOK_READ, BOOK_WRITE, BOOK_PUT, BOOK_DELETE)),
179+
EDITOR(Sets.newHashSet(BOOK_READ, BOOK_WRITE, BOOK_PUT)),
180+
USER(Sets.newHashSet(BOOK_READ));
181+
182+
private final Set<ApplicationUserPermission> permissions;
183+
184+
ApplicationUserRole(Set<ApplicationUserPermission> permissions) {
185+
this.permissions = permissions;
186+
}
187+
188+
public Set<ApplicationUserPermission> getPermissions() {
189+
return permissions;
190+
}
191+
}
192+
```
193+
194+
> #### Bir role çok sayıda Permission tanımı içerebilir.
195+
196+
## 3.3 ApplicationUserPermission
197+
198+
**ApplicationUserPermission** da bir **enum** yapısıdır ve kaynaklara ait yazma ya da okuma gibi işlevlerin tanımlanmasını sağlar. Burada tanımlanan izin ifadeleri istenilen Rollere atanabilir.
199+
200+
```java
201+
public enum ApplicationUserPermission {
202+
BOOK_GET("book:get"),
203+
BOOK_DELETE("book:delete"),
204+
BOOK_PUT("book:put"),
205+
BOOK_POST("book:post");
206+
207+
private final String permission;
208+
209+
ApplicationUserPermission(String permission) {
210+
this.permission = permission;
211+
}
212+
213+
public String getPermission() {
214+
return permission;
215+
}
216+
}
217+
```
218+
219+
```java
220+
import java.util.Set;
221+
222+
import com.google.common.collect.Sets;
223+
import static com.bookstore.api.security.ApplicationUserPermission.*;
224+
225+
public enum ApplicationUserRole {
226+
ADMIN(Sets.newHashSet(BOOK_GET, BOOK_POST, BOOK_PUT, BOOK_DELETE)),
227+
EDITOR(Sets.newHashSet(BOOK_GET, BOOK_POST, BOOK_PUT)),
228+
USER(Sets.newHashSet(BOOK_GET));
229+
230+
private final Set<ApplicationUserPermission> permissions;
231+
232+
ApplicationUserRole(Set<ApplicationUserPermission> permissions) {
233+
this.permissions = permissions;
234+
}
235+
236+
public Set<ApplicationUserPermission> getPermissions() {
237+
return permissions;
238+
}
239+
}
240+
241+
```
242+
243+
## 3.4. ApplicationSecurityConfig Güncellemesi
244+
245+
Artık rol tanımları bir enum yapısı içerisinde tanımlandığından String ifadeleri konfigürasyon dosyamızdan çıkartabiliriz.
246+
247+
```java
248+
249+
import static com.bookstore.api.security.ApplicationUserRole.*;
250+
251+
@Override
252+
protected void configure(HttpSecurity http) throws Exception {
253+
http
254+
.authorizeRequests()
255+
.antMatchers("/", "/index", "/css/*", "js/**").permitAll()
256+
.antMatchers("/api/**").hasAnyRole(ADMIN.name(), EDITOR.name())
257+
.anyRequest()
258+
.authenticated()
259+
.and()
260+
.httpBasic();
261+
}
262+
```

day-10/api/pom.xml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
2+
<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">
43
<modelVersion>4.0.0</modelVersion>
54
<parent>
65
<groupId>org.springframework.boot</groupId>
76
<artifactId>spring-boot-starter-parent</artifactId>
87
<version>2.7.1</version>
9-
<relativePath/> <!-- lookup parent from repository -->
8+
<relativePath /> <!-- lookup parent from repository -->
109
</parent>
1110
<groupId>com.bookstore</groupId>
1211
<artifactId>api</artifactId>
@@ -18,6 +17,12 @@
1817
</properties>
1918
<dependencies>
2019

20+
<dependency>
21+
<groupId>com.google.guava</groupId>
22+
<artifactId>guava</artifactId>
23+
<version>28.1-jre</version>
24+
</dependency>
25+
2126
<dependency>
2227
<groupId>org.springframework.boot</groupId>
2328
<artifactId>spring-boot-starter-security</artifactId>
@@ -91,4 +96,4 @@
9196
</plugins>
9297
</build>
9398

94-
</project>
99+
</project>

day-10/api/src/main/java/com/bookstore/api/config/ApplicationSecurityConfig.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.springframework.security.core.userdetails.UserDetailsService;
1111
import org.springframework.security.crypto.password.PasswordEncoder;
1212
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
13+
import static com.bookstore.api.security.ApplicationUserRole.*;
1314

1415
import lombok.RequiredArgsConstructor;
1516

@@ -25,7 +26,7 @@ protected void configure(HttpSecurity http) throws Exception {
2526
http
2627
.authorizeRequests()
2728
.antMatchers("/", "/index", "/css/*", "js/**").permitAll()
28-
.antMatchers("/api/**").hasAnyRole("ADMIN", "EDITOR")
29+
.antMatchers("/api/**").hasAnyRole(ADMIN.name(), EDITOR.name())
2930
.anyRequest()
3031
.authenticated()
3132
.and()
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.bookstore.api.security;
2+
3+
public enum ApplicationUserPermission {
4+
BOOK_GET("book:get"),
5+
BOOK_DELETE("book:delete"),
6+
BOOK_PUT("book:put"),
7+
BOOK_POST("book:post");
8+
9+
private final String permission;
10+
11+
ApplicationUserPermission(String permission) {
12+
this.permission = permission;
13+
}
14+
15+
public String getPermission() {
16+
return permission;
17+
}
18+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.bookstore.api.security;
2+
3+
import java.util.Set;
4+
5+
import com.google.common.collect.Sets;
6+
import static com.bookstore.api.security.ApplicationUserPermission.*;
7+
8+
public enum ApplicationUserRole {
9+
ADMIN(Sets.newHashSet(BOOK_GET, BOOK_POST, BOOK_PUT, BOOK_DELETE)),
10+
EDITOR(Sets.newHashSet(BOOK_GET, BOOK_POST, BOOK_PUT)),
11+
USER(Sets.newHashSet(BOOK_GET));
12+
13+
private final Set<ApplicationUserPermission> permissions;
14+
15+
ApplicationUserRole(Set<ApplicationUserPermission> permissions) {
16+
this.permissions = permissions;
17+
}
18+
19+
public Set<ApplicationUserPermission> getPermissions() {
20+
return permissions;
21+
}
22+
}

0 commit comments

Comments
 (0)