refactoring

This commit is contained in:
ard333
2018-07-22 21:36:08 +07:00
parent 636264098c
commit 74b2cb9acd
19 changed files with 73 additions and 173 deletions

View File

@@ -1 +1,5 @@
# spring-boot-webflux-jjwt
Example Spring Boot and WebFlux (Reactive Web) with Spring Security and JWT for token Authentication and Authorization
### Documantation
You can se my Medium story, [Authentication and Authorization Using JWT on Spring Webflux](https://medium.com/@ard333/29b81f813e78)

View File

@@ -3,7 +3,7 @@
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>id.web.ard</groupId>
<groupId>com.ard333</groupId>
<artifactId>spring-boot-webflux-jjwt</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

View File

@@ -1,4 +1,4 @@
package id.web.ard.springbootwebfluxjjwt;
package com.ard333.springbootwebfluxjjwt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

View File

@@ -1,8 +1,4 @@
/*
* Ardiansyah | http://ard.web.id
*
*/
package id.web.ard.springbootwebfluxjjwt.model;
package com.ard333.springbootwebfluxjjwt.model;
import lombok.AllArgsConstructor;
import lombok.Data;
@@ -11,7 +7,7 @@ import lombok.ToString;
/**
*
* @author ardiansyah
* @author ard333
*/
@Data @NoArgsConstructor @AllArgsConstructor @ToString
public class Message {

View File

@@ -1,26 +1,23 @@
/*
* Ardiansyah | http://ard.web.id
*
*/
package id.web.ard.springbootwebfluxjjwt.model;
package com.ard333.springbootwebfluxjjwt.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import id.web.ard.springbootwebfluxjjwt.security.model.Role;
import com.ard333.springbootwebfluxjjwt.security.model.Role;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
/**
*
* @author ardiansyah
* @author ard333
*/
@ToString @AllArgsConstructor @NoArgsConstructor
public class User implements UserDetails {
@@ -29,20 +26,21 @@ public class User implements UserDetails {
private String password;
@Getter @Setter
private Boolean enabled;
@Getter @Setter
private List<Role> roles;
public User(String username) {
this.username = username;
}
@Override
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
//==============================
@Override
public boolean isAccountNonExpired() {
return false;
@@ -63,15 +61,10 @@ public class User implements UserDetails {
return this.enabled;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.roles.stream().map(authority -> new SimpleGrantedAuthority(authority.name())).collect(Collectors.toList());
}
//==============================
@JsonIgnore
@Override
@@ -84,20 +77,4 @@ public class User implements UserDetails {
this.password = password;
}
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
}

View File

@@ -1,18 +1,13 @@
/*
* Ardiansyah | http://ard.web.id
*
*/
package id.web.ard.springbootwebfluxjjwt.rest;
package com.ard333.springbootwebfluxjjwt.rest;
import id.web.ard.springbootwebfluxjjwt.security.JWTUtil;
import id.web.ard.springbootwebfluxjjwt.security.PBKDF2Encoder;
import id.web.ard.springbootwebfluxjjwt.security.model.AuthRequest;
import id.web.ard.springbootwebfluxjjwt.security.model.AuthResponse;
import id.web.ard.springbootwebfluxjjwt.service.UserService;
import com.ard333.springbootwebfluxjjwt.security.JWTUtil;
import com.ard333.springbootwebfluxjjwt.security.PBKDF2Encoder;
import com.ard333.springbootwebfluxjjwt.security.model.AuthRequest;
import com.ard333.springbootwebfluxjjwt.security.model.AuthResponse;
import com.ard333.springbootwebfluxjjwt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@@ -21,13 +16,13 @@ import reactor.core.publisher.Mono;
/**
*
* @author ardiansyah
* @author ard333
*/
@RestController
public class AuthenticationREST {
@Autowired
private JWTUtil jwtTokenUtil;
private JWTUtil jwtUtil;
@Autowired
private PBKDF2Encoder passwordEncoder;
@@ -39,7 +34,7 @@ public class AuthenticationREST {
public Mono<ResponseEntity<AuthResponse>> auth(@RequestBody AuthRequest ar) {
return userRepository.findByUsername(ar.getUsername()).map((userDetails) -> {
if (passwordEncoder.encode(ar.getPassword()).equals(userDetails.getPassword())) {
return ResponseEntity.ok(new AuthResponse(jwtTokenUtil.generateToken(userDetails)));
return ResponseEntity.ok(new AuthResponse(jwtUtil.generateToken(userDetails)));
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}

View File

@@ -2,9 +2,9 @@
* Ardiansyah | http://ard.web.id
*
*/
package id.web.ard.springbootwebfluxjjwt.rest;
package com.ard333.springbootwebfluxjjwt.rest;
import id.web.ard.springbootwebfluxjjwt.model.Message;
import com.ard333.springbootwebfluxjjwt.model.Message;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;

View File

@@ -1,10 +1,6 @@
/*
* Ardiansyah | http://ard.web.id
*
*/
package id.web.ard.springbootwebfluxjjwt.security;
package com.ard333.springbootwebfluxjjwt.security;
import id.web.ard.springbootwebfluxjjwt.security.model.Role;
import com.ard333.springbootwebfluxjjwt.security.model.Role;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
@@ -16,11 +12,10 @@ import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.security.web.server.context.ServerSecurityContextRepository;
/**
*
* @author ardiansyah
* @author ard333
*/
@Component
public class AuthenticationManager implements ReactiveAuthenticationManager {
@@ -32,29 +27,25 @@ public class AuthenticationManager implements ReactiveAuthenticationManager {
public Mono<Authentication> authenticate(Authentication authentication) {
String authToken = authentication.getCredentials().toString();
String username = null;
String username;
try {
username = jwtUtil.getUsernameFromToken(authToken);
} catch (Exception e) {
username = null;
}
if (username != null) {
if (username != null && jwtUtil.validateToken(authToken)) {
Claims claims = jwtUtil.getAllClaimsFromToken(authToken);
if (jwtUtil.validateToken(authToken)) {
List<String> rolesMap = claims.get("role", List.class);
List<Role> roles = new ArrayList<>();
for (String rolemap : rolesMap) {
roles.add(Role.valueOf(rolemap));
}
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
username,
null,
roles.stream().map(authority -> new SimpleGrantedAuthority(authority.name())).collect(Collectors.toList())
);
return Mono.just(auth);
} else {
return Mono.empty();
List<String> rolesMap = claims.get("role", List.class);
List<Role> roles = new ArrayList<>();
for (String rolemap : rolesMap) {
roles.add(Role.valueOf(rolemap));
}
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
username,
null,
roles.stream().map(authority -> new SimpleGrantedAuthority(authority.name())).collect(Collectors.toList())
);
return Mono.just(auth);
} else {
return Mono.empty();
}

View File

@@ -1,8 +1,4 @@
/*
* Ardiansyah | http://ard.web.id
*
*/
package id.web.ard.springbootwebfluxjjwt.security;
package com.ard333.springbootwebfluxjjwt.security;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.config.CorsRegistry;
@@ -11,7 +7,7 @@ import org.springframework.web.reactive.config.WebFluxConfigurer;
/**
*
* @author ardiansyah
* @author ard333
*/
@Configuration
@EnableWebFlux

View File

@@ -1,10 +1,6 @@
/*
* Ardiansyah | http://ard.web.id
*
*/
package id.web.ard.springbootwebfluxjjwt.security;
package com.ard333.springbootwebfluxjjwt.security;
import id.web.ard.springbootwebfluxjjwt.model.User;
import com.ard333.springbootwebfluxjjwt.model.User;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
@@ -17,7 +13,7 @@ import org.springframework.stereotype.Component;
/**
*
* @author ardiansyah
* @author ard333
*/
@Component
public class JWTUtil implements Serializable {

View File

@@ -1,8 +1,4 @@
/*
* Ardiansyah | http://ard.web.id
*
*/
package id.web.ard.springbootwebfluxjjwt.security;
package com.ard333.springbootwebfluxjjwt.security;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
@@ -15,7 +11,7 @@ import org.springframework.stereotype.Component;
/**
*
* @author ardiansyah
* @author ard333
*/
@Component
public class PBKDF2Encoder implements PasswordEncoder{

View File

@@ -1,8 +1,4 @@
/*
* Ardiansyah | http://ard.web.id
*
*/
package id.web.ard.springbootwebfluxjjwt.security;
package com.ard333.springbootwebfluxjjwt.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
@@ -18,7 +14,7 @@ import reactor.core.publisher.Mono;
/**
*
* @author ardiansyah
* @author ard333
*/
@Component
public class SecurityContextRepository implements ServerSecurityContextRepository{

View File

@@ -1,4 +1,4 @@
package id.web.ard.springbootwebfluxjjwt.security;
package com.ard333.springbootwebfluxjjwt.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@@ -10,7 +10,7 @@ import org.springframework.security.web.server.SecurityWebFilterChain;
/**
*
* @author ardiansyah
* @author ard333
*/
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity

View File

@@ -1,8 +1,4 @@
/*
* Ardiansyah | http://ard.web.id
*
*/
package id.web.ard.springbootwebfluxjjwt.security.model;
package com.ard333.springbootwebfluxjjwt.security.model;
import lombok.AllArgsConstructor;
import lombok.Data;
@@ -11,7 +7,7 @@ import lombok.ToString;
/**
*
* @author ardiansyah
* @author ard333
*/
@Data @NoArgsConstructor @AllArgsConstructor @ToString
public class AuthRequest {

View File

@@ -1,8 +1,4 @@
/*
* Ardiansyah | http://ard.web.id
*
*/
package id.web.ard.springbootwebfluxjjwt.security.model;
package com.ard333.springbootwebfluxjjwt.security.model;
import lombok.AllArgsConstructor;
import lombok.Data;
@@ -11,7 +7,7 @@ import lombok.ToString;
/**
*
* @author ardiansyah
* @author ard333
*/
@Data @NoArgsConstructor @AllArgsConstructor @ToString
public class AuthResponse {

View File

@@ -0,0 +1,9 @@
package com.ard333.springbootwebfluxjjwt.security.model;
/**
*
* @author ard333
*/
public enum Role {
ROLE_USER, ROLE_ADMIN
}

View File

@@ -1,11 +1,7 @@
/*
* Ardiansyah | http://ard.web.id
*
*/
package id.web.ard.springbootwebfluxjjwt.service;
package com.ard333.springbootwebfluxjjwt.service;
import id.web.ard.springbootwebfluxjjwt.model.User;
import id.web.ard.springbootwebfluxjjwt.security.model.Role;
import com.ard333.springbootwebfluxjjwt.model.User;
import com.ard333.springbootwebfluxjjwt.security.model.Role;
import java.util.Arrays;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
@@ -13,7 +9,7 @@ import reactor.core.publisher.Mono;
/**
*
* @author ardiansyah
* @author ard333
*/
@Service
public class UserService {
@@ -49,6 +45,4 @@ public class UserService {
}
}
}

View File

@@ -1,29 +0,0 @@
/*
* Ardiansyah | http://ard.web.id
*
*/
package id.web.ard.springbootwebfluxjjwt.security;
import id.web.ard.springbootwebfluxjjwt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
/**
*
* @author ardiansyah
*/
@Service
public class UserDetailsServiceImpl implements ReactiveUserDetailsService {
@Autowired
private UserService userRepository;
@Override
public Mono<UserDetails> findByUsername(String username) {
return userRepository.findUserDetailsByUsername(username);
}
}

View File

@@ -1,13 +0,0 @@
/*
* Ardiansyah | http://ard.web.id
*
*/
package id.web.ard.springbootwebfluxjjwt.security.model;
/**
*
* @author ardiansyah
*/
public enum Role {
ROLE_USER, ROLE_ADMIN
}