implement authentication and authorization
This commit is contained in:
12
pom.xml
12
pom.xml
@@ -14,7 +14,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.2.RELEASE</version>
|
||||
<version>2.0.0.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
@@ -33,6 +33,16 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt</artifactId>
|
||||
<version>0.7.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Ardiansyah | http://ard.web.id
|
||||
*
|
||||
*/
|
||||
package id.web.ard.springbootwebfluxjjwt.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ardiansyah
|
||||
*/
|
||||
@Data @NoArgsConstructor @AllArgsConstructor @ToString
|
||||
public class Message {
|
||||
|
||||
private String content;
|
||||
|
||||
}
|
||||
103
src/main/java/id/web/ard/springbootwebfluxjjwt/entity/User.java
Normal file
103
src/main/java/id/web/ard/springbootwebfluxjjwt/entity/User.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Ardiansyah | http://ard.web.id
|
||||
*
|
||||
*/
|
||||
package id.web.ard.springbootwebfluxjjwt.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import id.web.ard.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.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ardiansyah
|
||||
*/
|
||||
@ToString @AllArgsConstructor @NoArgsConstructor
|
||||
public class User implements UserDetails {
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
private Boolean enabled;
|
||||
|
||||
private List<Role> roles;
|
||||
|
||||
public User(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
//==============================
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
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
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
@JsonProperty
|
||||
public void setPassword(String password) {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Ardiansyah | http://ard.web.id
|
||||
*
|
||||
*/
|
||||
package id.web.ard.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 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;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ardiansyah
|
||||
*/
|
||||
@RestController
|
||||
public class AuthenticationREST {
|
||||
|
||||
@Autowired
|
||||
private JWTUtil jwtTokenUtil;
|
||||
|
||||
@Autowired
|
||||
private PBKDF2Encoder passwordEncoder;
|
||||
|
||||
@Autowired
|
||||
private UserService userRepository;
|
||||
|
||||
@RequestMapping(value = "auth", method = RequestMethod.POST)
|
||||
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)));
|
||||
} else {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Ardiansyah | http://ard.web.id
|
||||
*
|
||||
*/
|
||||
package id.web.ard.springbootwebfluxjjwt.rest;
|
||||
|
||||
import id.web.ard.springbootwebfluxjjwt.entity.Message;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ardiansyah
|
||||
*/
|
||||
@RestController
|
||||
public class ResourceREST {
|
||||
|
||||
@RequestMapping(value = "resource/user", method = RequestMethod.GET)
|
||||
@PreAuthorize("hasRole('USER')")
|
||||
public Mono<ResponseEntity<?>> user() {
|
||||
return Mono.just(ResponseEntity.ok(new Message("Content for user")));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "resource/admin", method = RequestMethod.GET)
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
public Mono<ResponseEntity<?>> admin() {
|
||||
return Mono.just(ResponseEntity.ok(new Message("Content for admin")));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "resource/user-or-admin", method = RequestMethod.GET)
|
||||
@PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
|
||||
public Mono<ResponseEntity<?>> userOrAdmin() {
|
||||
return Mono.just(ResponseEntity.ok(new Message("Content for user or admin")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Ardiansyah | http://ard.web.id
|
||||
*
|
||||
*/
|
||||
package id.web.ard.springbootwebfluxjjwt.security;
|
||||
|
||||
import id.web.ard.springbootwebfluxjjwt.security.model.Role;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.stereotype.Component;
|
||||
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
|
||||
*/
|
||||
@Component
|
||||
public class AuthenticationManager implements ReactiveAuthenticationManager {
|
||||
|
||||
@Autowired
|
||||
private JWTUtil jwtUtil;
|
||||
|
||||
@Override
|
||||
public Mono<Authentication> authenticate(Authentication authentication) {
|
||||
String authToken = authentication.getCredentials().toString();
|
||||
|
||||
String username = null;
|
||||
try {
|
||||
username = jwtUtil.getUsernameFromToken(authToken);
|
||||
} catch (Exception e) {
|
||||
username = null;
|
||||
}
|
||||
if (username != null) {
|
||||
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();
|
||||
}
|
||||
} else {
|
||||
return Mono.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Ardiansyah | http://ard.web.id
|
||||
*
|
||||
*/
|
||||
package id.web.ard.springbootwebfluxjjwt.security;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ardiansyah
|
||||
*/
|
||||
@Component
|
||||
public class CORSFilter implements WebFilter{
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange swe, WebFilterChain wfc) {
|
||||
|
||||
//CORS
|
||||
swe.getResponse().getHeaders().add("Access-Control-Allow-Origin", "*");
|
||||
if (swe.getRequest().getHeaders().get("Access-Control-Request-Method") != null && "OPTIONS".equalsIgnoreCase(swe.getRequest().getMethod().toString())) {
|
||||
swe.getResponse().getHeaders().add("Access-Control-Allow-Headers", "Authorization");
|
||||
swe.getResponse().getHeaders().add("Access-Control-Allow-Headers", "Content-Type");
|
||||
swe.getResponse().getHeaders().add("Access-Control-Max-Age", "1");
|
||||
swe.getResponse().getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
|
||||
}
|
||||
|
||||
return wfc.filter(swe);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Ardiansyah | http://ard.web.id
|
||||
*
|
||||
*/
|
||||
package id.web.ard.springbootwebfluxjjwt.security;
|
||||
|
||||
import id.web.ard.springbootwebfluxjjwt.entity.User;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ardiansyah
|
||||
*/
|
||||
@Component
|
||||
public class JWTUtil implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Value("${springbootwebfluxjjwt.jjwt.secret}")
|
||||
private String secret;
|
||||
|
||||
@Value("${springbootwebfluxjjwt.jjwt.expiration}")
|
||||
private String expirationTime;
|
||||
|
||||
public Claims getAllClaimsFromToken(String token) {
|
||||
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
|
||||
}
|
||||
|
||||
public String getUsernameFromToken(String token) {
|
||||
return getAllClaimsFromToken(token).getSubject();
|
||||
}
|
||||
|
||||
public Date getExpirationDateFromToken(String token) {
|
||||
return getAllClaimsFromToken(token).getExpiration();
|
||||
}
|
||||
|
||||
private Boolean isTokenExpired(String token) {
|
||||
final Date expiration = getExpirationDateFromToken(token);
|
||||
return expiration.before(new Date());
|
||||
}
|
||||
|
||||
public String generateToken(User user) {
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
claims.put("role", user.getRoles());
|
||||
claims.put("enable", user.getEnabled());
|
||||
return doGenerateToken(claims, user.getUsername());
|
||||
}
|
||||
|
||||
private String doGenerateToken(Map<String, Object> claims, String username) {
|
||||
Long expirationTimeLong = Long.parseLong(expirationTime); //in second
|
||||
|
||||
final Date createdDate = new Date();
|
||||
final Date expirationDate = new Date(createdDate.getTime() + expirationTimeLong * 1000);
|
||||
return Jwts.builder()
|
||||
.setClaims(claims)
|
||||
.setSubject(username)
|
||||
.setIssuedAt(createdDate)
|
||||
.setExpiration(expirationDate)
|
||||
.signWith(SignatureAlgorithm.HS512, secret)
|
||||
.compact();
|
||||
}
|
||||
|
||||
public Boolean validateToken(String token) {
|
||||
return !isTokenExpired(token);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Ardiansyah | http://ard.web.id
|
||||
*
|
||||
*/
|
||||
package id.web.ard.springbootwebfluxjjwt.security;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Base64;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ardiansyah
|
||||
*/
|
||||
@Component
|
||||
public class PBKDF2Encoder implements PasswordEncoder{
|
||||
|
||||
@Value("${springbootwebfluxjjwt.password.secret}")
|
||||
private String secret;
|
||||
|
||||
/**
|
||||
* More info (https://www.owasp.org/index.php/Hashing_Java)
|
||||
* @param cs password
|
||||
* @return encoded password
|
||||
*/
|
||||
@Override
|
||||
public String encode(CharSequence cs) {
|
||||
try {
|
||||
byte[] result = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512")
|
||||
.generateSecret(new PBEKeySpec(cs.toString().toCharArray(), secret.getBytes(), 33, 256))
|
||||
.getEncoded();
|
||||
return Base64.getEncoder().encodeToString(result);
|
||||
} catch (NoSuchAlgorithmException | InvalidKeySpecException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(CharSequence cs, String string) {
|
||||
return encode(cs).equals(string);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Ardiansyah | http://ard.web.id
|
||||
*
|
||||
*/
|
||||
package id.web.ard.springbootwebfluxjjwt.security;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextImpl;
|
||||
import org.springframework.security.web.server.context.ServerSecurityContextRepository;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ardiansyah
|
||||
*/
|
||||
@Component
|
||||
public class SecurityContextRepository implements ServerSecurityContextRepository{
|
||||
|
||||
@Autowired
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
@Override
|
||||
public Mono<Void> save(ServerWebExchange swe, SecurityContext sc) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<SecurityContext> load(ServerWebExchange swe) {
|
||||
ServerHttpRequest request = swe.getRequest();
|
||||
String authHeader = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
|
||||
|
||||
if (authHeader != null && authHeader.startsWith("Bearer ")) {
|
||||
String authToken = authHeader.substring(7);
|
||||
Authentication auth = new UsernamePasswordAuthenticationToken(authToken, authToken);
|
||||
return this.authenticationManager.authenticate(auth).map((authentication) -> {
|
||||
return new SecurityContextImpl(authentication);
|
||||
});
|
||||
} else {
|
||||
return Mono.empty();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package id.web.ard.springbootwebfluxjjwt.security;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
||||
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
import org.springframework.security.web.server.SecurityWebFilterChain;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ardiansyah
|
||||
*/
|
||||
@EnableWebFluxSecurity
|
||||
@EnableReactiveMethodSecurity
|
||||
public class WebSecurityConfig {
|
||||
|
||||
@Autowired
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
@Autowired
|
||||
private SecurityContextRepository securityContextRepository;
|
||||
|
||||
@Bean
|
||||
public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) {
|
||||
return http.csrf().disable()
|
||||
.formLogin().disable()
|
||||
.httpBasic().disable()
|
||||
.authenticationManager(authenticationManager)
|
||||
.securityContextRepository(securityContextRepository)
|
||||
//.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.HTTP_BASIC)
|
||||
.authorizeExchange()
|
||||
.pathMatchers("/auth").permitAll()
|
||||
.anyExchange().authenticated()
|
||||
.and().build();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Ardiansyah | http://ard.web.id
|
||||
*
|
||||
*/
|
||||
package id.web.ard.springbootwebfluxjjwt.security.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ardiansyah
|
||||
*/
|
||||
@Data @NoArgsConstructor @AllArgsConstructor @ToString
|
||||
public class AuthRequest {
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Ardiansyah | http://ard.web.id
|
||||
*
|
||||
*/
|
||||
package id.web.ard.springbootwebfluxjjwt.security.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ardiansyah
|
||||
*/
|
||||
@Data @NoArgsConstructor @AllArgsConstructor @ToString
|
||||
public class AuthResponse {
|
||||
|
||||
private String token;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Ardiansyah | http://ard.web.id
|
||||
*
|
||||
*/
|
||||
package id.web.ard.springbootwebfluxjjwt.security.model;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ardiansyah
|
||||
*/
|
||||
public enum Role {
|
||||
ROLE_USER, ROLE_ADMIN
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Ardiansyah | http://ard.web.id
|
||||
*
|
||||
*/
|
||||
package id.web.ard.springbootwebfluxjjwt.service;
|
||||
|
||||
import id.web.ard.springbootwebfluxjjwt.entity.User;
|
||||
import id.web.ard.springbootwebfluxjjwt.security.model.Role;
|
||||
import java.util.Arrays;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ardiansyah
|
||||
*/
|
||||
@Service
|
||||
public class UserService {
|
||||
|
||||
// this is just an example, you can load the user from the database from the repository
|
||||
|
||||
//username:passwowrd -> user:user
|
||||
private final String userUsername = "user";// password: user
|
||||
private final User user = new User(userUsername, "cBrlgyL2GI2GINuLUUwgojITuIufFycpLG4490dhGtY=", true, Arrays.asList(Role.ROLE_USER));
|
||||
|
||||
//username:passwowrd -> admin:admin
|
||||
private final String adminUsername = "admin";// password: admin
|
||||
private final User admin = new User(adminUsername, "dQNjUIMorJb8Ubj2+wVGYp6eAeYkdekqAcnYp+aRq5w=", true, Arrays.asList(Role.ROLE_ADMIN));
|
||||
|
||||
|
||||
public Mono<UserDetails> findUserDetailsByUsername(String username) {
|
||||
if (username.equals(userUsername)) {
|
||||
return Mono.just(user);
|
||||
} else if (username.equals(adminUsername)) {
|
||||
return Mono.just(admin);
|
||||
} else {
|
||||
return Mono.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public Mono<User> findByUsername(String username) {
|
||||
if (username.equals(userUsername)) {
|
||||
return Mono.just(user);
|
||||
} else if (username.equals(adminUsername)) {
|
||||
return Mono.just(admin);
|
||||
} else {
|
||||
return Mono.empty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
springbootwebfluxjjwt.password.secret=mysecret
|
||||
springbootwebfluxjjwt.jjwt.secret=mysecret
|
||||
springbootwebfluxjjwt.jjwt.expiration=28800
|
||||
Reference in New Issue
Block a user