Skip to content

Commit 5faeeca

Browse files
committed
Added security
1 parent 1493139 commit 5faeeca

19 files changed

+591
-24
lines changed

pom.xml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
</properties>
2121

2222
<dependencies>
23+
<dependency>
24+
<groupId>org.springframework.boot</groupId>
25+
<artifactId>spring-boot-starter-security</artifactId>
26+
</dependency>
2327
<dependency>
2428
<groupId>org.springframework.boot</groupId>
2529
<artifactId>spring-boot-starter-webflux</artifactId>
@@ -51,6 +55,23 @@
5155
<groupId>org.projectlombok</groupId>
5256
<artifactId>lombok</artifactId>
5357
</dependency>
58+
<dependency>
59+
<groupId>io.jsonwebtoken</groupId>
60+
<artifactId>jjwt-api</artifactId>
61+
<version>0.10.5</version>
62+
</dependency>
63+
<dependency>
64+
<groupId>io.jsonwebtoken</groupId>
65+
<artifactId>jjwt-impl</artifactId>
66+
<version>0.10.5</version>
67+
<scope>runtime</scope>
68+
</dependency>
69+
<dependency>
70+
<groupId>io.jsonwebtoken</groupId>
71+
<artifactId>jjwt-jackson</artifactId>
72+
<version>0.10.5</version>
73+
<scope>runtime</scope>
74+
</dependency>
5475
</dependencies>
5576

5677
<dependencyManagement>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package net.java.forest.controller;
2+
3+
4+
import net.java.forest.model.Userdata;
5+
import net.java.forest.security.JWTUtil;
6+
import net.java.forest.security.PBKDF2Encoder;
7+
import net.java.forest.security.model.AuthRequest;
8+
import net.java.forest.security.model.AuthResponse;
9+
import net.java.forest.service.UserService;
10+
import org.springframework.beans.factory.annotation.Autowired;
11+
import org.springframework.http.HttpStatus;
12+
import org.springframework.http.ResponseEntity;
13+
import org.springframework.validation.annotation.Validated;
14+
import org.springframework.web.bind.annotation.RequestBody;
15+
import org.springframework.web.bind.annotation.RequestMapping;
16+
import org.springframework.web.bind.annotation.RequestMethod;
17+
import org.springframework.web.bind.annotation.RestController;
18+
import org.springframework.web.reactive.function.server.ServerRequest;
19+
import org.springframework.web.reactive.function.server.ServerResponse;
20+
import reactor.core.publisher.Mono;
21+
22+
import java.awt.print.Book;
23+
import java.net.URI;
24+
25+
@RestController
26+
@Validated
27+
public class AuthenticationREST {
28+
29+
@Autowired
30+
private JWTUtil jwtUtil;
31+
32+
@Autowired
33+
private PBKDF2Encoder passwordEncoder;
34+
35+
@Autowired
36+
private UserService userService;
37+
38+
@RequestMapping(value = "/login", method = RequestMethod.POST)
39+
public Mono<ResponseEntity<?>> login(@RequestBody AuthRequest ar) {
40+
return userService.findByUsername(ar.getUsername()).map((userDetails) -> {
41+
if (ar.getPassword().equals(userDetails.getPassword())) {
42+
//if (passwordEncoder.encode(ar.getPassword()).equals(userDetails.getPassword())) {
43+
return ResponseEntity.ok(new AuthResponse(jwtUtil.generateToken(userDetails)));
44+
} else {
45+
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
46+
}
47+
}).defaultIfEmpty(ResponseEntity.status(HttpStatus.UNAUTHORIZED).build());
48+
}
49+
50+
/*@RequestMapping(value = "/signup", method = RequestMethod.POST)
51+
public Mono<ServerResponse> signUp(ServerRequest request) {
52+
53+
54+
}*/
55+
56+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package net.java.forest.controller;
2+
3+
import net.java.forest.model.Message;
4+
import org.springframework.http.ResponseEntity;
5+
import org.springframework.security.access.prepost.PreAuthorize;
6+
import org.springframework.web.bind.annotation.RequestMapping;
7+
import org.springframework.web.bind.annotation.RequestMethod;
8+
import org.springframework.web.bind.annotation.RestController;
9+
import reactor.core.publisher.Mono;
10+
11+
import java.security.Principal;
12+
13+
14+
@RestController
15+
public class ResourceREST {
16+
17+
@RequestMapping(value = "/user", method = RequestMethod.GET)
18+
public Mono<ResponseEntity<?>> publicUser(Principal principal) {
19+
return Mono.just(ResponseEntity.ok(new Message(principal.toString())));
20+
}
21+
22+
@RequestMapping(value = "/resource/user", method = RequestMethod.GET)
23+
@PreAuthorize("hasRole('USER')")
24+
public Mono<ResponseEntity<?>> user(Principal principal) {
25+
return Mono.just(ResponseEntity.ok(new Message(principal.toString())));
26+
}
27+
28+
@RequestMapping(value = "/resource/admin", method = RequestMethod.GET)
29+
@PreAuthorize("hasRole('ADMIN')")
30+
public Mono<ResponseEntity<?>> admin() {
31+
return Mono.just(ResponseEntity.ok(new Message("Content for admin")));
32+
}
33+
34+
@RequestMapping(value = "/resource/user-or-admin", method = RequestMethod.GET)
35+
@PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
36+
public Mono<ResponseEntity<?>> userOrAdmin() {
37+
return Mono.just(ResponseEntity.ok(new Message("Content for user or admin")));
38+
}
39+
}

src/main/java/net/java/forest/controller/UserController.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import reactor.core.publisher.Flux;
1010
import reactor.core.publisher.Mono;
1111

12+
import java.util.Arrays;
13+
1214
@RestController
1315
public class UserController {
1416
@Autowired
@@ -21,6 +23,6 @@ public Flux<Userdata> getallUser(){
2123

2224
@RequestMapping(value = "/adduser", method = RequestMethod.GET)
2325
public Mono<Userdata> addUser(){
24-
return userService.addUpdateUser(new Userdata(null, "Mahade","hassan", "12345", "mahade.hasan68@gmail.com","Bd, Khustia"));
26+
return userService.addUpdateUser(new Userdata(null, "Mahade","hassan", "12345", "mahade.hasan68@gmail.com","Bd, Khustia", Arrays.asList("USER")));
2527
}
2628
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package net.java.forest.model;
2+
3+
public class Message {
4+
private String content;
5+
6+
public Message(String content) {
7+
this.content = content;
8+
}
9+
10+
public String getContent() {
11+
return content;
12+
}
13+
14+
public void setContent(String content) {
15+
this.content = content;
16+
}
17+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package net.java.forest.model;
2+
3+
public enum Role {
4+
ROLE_USER, ROLE_ADMIN
5+
}

src/main/java/net/java/forest/model/Userdata.java

Lines changed: 87 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
package net.java.forest.model;
22

3+
import com.fasterxml.jackson.annotation.JsonIgnore;
4+
import com.fasterxml.jackson.annotation.JsonProperty;
5+
36
import org.hibernate.validator.constraints.UniqueElements;
47
import org.springframework.data.annotation.Id;
8+
import org.springframework.security.core.GrantedAuthority;
9+
import org.springframework.security.core.authority.SimpleGrantedAuthority;
10+
import org.springframework.security.core.userdetails.UserDetails;
511

612
import javax.validation.constraints.Email;
713
import javax.validation.constraints.NotBlank;
14+
import java.util.Collection;
15+
import java.util.List;
16+
import java.util.stream.Collectors;
817

9-
public class Userdata {
18+
public class Userdata implements UserDetails {
1019
@Id
1120
private Long id;
1221
@NotBlank(message = "Firstname should not be empty")
@@ -19,14 +28,53 @@ public class Userdata {
1928
@UniqueElements(message = "Should be unique")
2029
private String email;
2130
private String address;
31+
@NotBlank(message = "Roles should not be empty")
32+
private List<String> roles;
33+
private Boolean enabled;
2234

23-
public Userdata(Long id, String firstName, String lastName, String password, String email, String address) {
35+
public Userdata(Long id, String firstName, String lastName, String password, String email, String address, List<String> roles ) {
2436
this.id = id;
2537
this.firstName = firstName;
2638
this.lastName = lastName;
2739
this.password = password;
2840
this.email = email;
2941
this.address = address;
42+
this.roles = roles;
43+
this.enabled = true;
44+
}
45+
46+
public Userdata(String email, String password, boolean enabled, List<String> asList) {
47+
this.enabled = enabled;
48+
this.email = email;
49+
this.password = password;
50+
this.roles = asList;
51+
}
52+
53+
public Userdata() {
54+
}
55+
56+
public Boolean getEnabled() {
57+
return enabled;
58+
}
59+
60+
public void setEnabled(Boolean enabled) {
61+
this.enabled = enabled;
62+
}
63+
64+
public String getAddress() {
65+
return address;
66+
}
67+
68+
public void setAddress(String address) {
69+
this.address = address;
70+
}
71+
72+
public List<String> getRoles() {
73+
return roles;
74+
}
75+
76+
public void setRoles(List<String> roles) {
77+
this.roles = roles;
3078
}
3179

3280
public Long getId() {
@@ -53,10 +101,45 @@ public void setLastName(String lastName) {
53101
this.lastName = lastName;
54102
}
55103

104+
105+
@Override
106+
public Collection<? extends GrantedAuthority> getAuthorities() {
107+
108+
return this.roles.stream().map(authority -> new SimpleGrantedAuthority(authority)).collect(Collectors.toList());
109+
}
110+
111+
@JsonIgnore
112+
@Override
56113
public String getPassword() {
57114
return password;
58115
}
59116

117+
@Override
118+
public String getUsername() {
119+
return this.email;
120+
}
121+
122+
@Override
123+
public boolean isAccountNonExpired() {
124+
return false;
125+
}
126+
127+
@Override
128+
public boolean isAccountNonLocked() {
129+
return false;
130+
}
131+
132+
@Override
133+
public boolean isCredentialsNonExpired() {
134+
return false;
135+
}
136+
137+
@Override
138+
public boolean isEnabled() {
139+
return false;
140+
}
141+
142+
@JsonProperty
60143
public void setPassword(String password) {
61144
this.password = password;
62145
}
@@ -69,23 +152,16 @@ public void setEmail(String email) {
69152
this.email = email;
70153
}
71154

72-
public String getAdddress() {
73-
return address;
74-
}
75-
76-
public void setAdddress(String adddress) {
77-
this.address = adddress;
78-
}
79-
80155
@Override
81156
public String toString() {
82-
return "User{" +
157+
return "Userdata{" +
83158
"id=" + id +
84159
", firstName='" + firstName + '\'' +
85160
", lastName='" + lastName + '\'' +
86161
", password='" + password + '\'' +
87162
", email='" + email + '\'' +
88163
", address='" + address + '\'' +
164+
", roles=" + roles +
89165
'}';
90166
}
91167
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package net.java.forest.repository;
22

33
import net.java.forest.model.Userdata;
4+
import org.springframework.data.r2dbc.repository.query.Query;
45
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
56
import org.springframework.stereotype.Repository;
7+
import reactor.core.publisher.Mono;
68

79
@Repository
810
public interface UserRepository extends ReactiveCrudRepository<Userdata, Long> {
9-
/*@Query("Select * from user where user.email=")
10-
Mono<User> findByEmail(String email);*/
11+
@Query("select * from userdata where email = :email")
12+
Mono<Userdata> findByEmail(String email);
1113
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package net.java.forest.security;
2+
3+
import io.jsonwebtoken.Claims;
4+
import net.java.forest.model.Role;
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.security.authentication.ReactiveAuthenticationManager;
7+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
8+
import org.springframework.security.core.Authentication;
9+
import org.springframework.security.core.authority.SimpleGrantedAuthority;
10+
import org.springframework.stereotype.Component;
11+
import reactor.core.publisher.Mono;
12+
import java.util.ArrayList;
13+
import java.util.List;
14+
import java.util.stream.Collectors;
15+
16+
@Component
17+
public class AuthenticationManager implements ReactiveAuthenticationManager {
18+
19+
@Autowired
20+
private JWTUtil jwtUtil;
21+
22+
@Override
23+
@SuppressWarnings("unchecked")
24+
public Mono<Authentication> authenticate(Authentication authentication) {
25+
String authToken = authentication.getCredentials().toString();
26+
27+
String username;
28+
try {
29+
username = jwtUtil.getUsernameFromToken(authToken);
30+
} catch (Exception e) {
31+
username = null;
32+
}
33+
if (username != null && jwtUtil.validateToken(authToken)) {
34+
Claims claims = jwtUtil.getAllClaimsFromToken(authToken);
35+
List<String> rolesMap = claims.get("role", List.class);
36+
List<Role> roles = new ArrayList<>();
37+
for (String rolemap : rolesMap) {
38+
roles.add(Role.valueOf(rolemap));
39+
}
40+
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
41+
username,
42+
null,
43+
roles.stream().map(authority -> new SimpleGrantedAuthority(authority.name())).collect(Collectors.toList())
44+
);
45+
return Mono.just(auth);
46+
} else {
47+
return Mono.empty();
48+
}
49+
}
50+
}

0 commit comments

Comments
 (0)