add spring security and token management
This commit is contained in:
parent
597d4062c7
commit
c76c01a174
67
pom.xml
67
pom.xml
@ -17,6 +17,59 @@
|
||||
<java.version>11</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
<version>2.5.4</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security.oauth.boot</groupId>
|
||||
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
|
||||
<version>2.5.2</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>5.3.9.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>5.3.9.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt</artifactId>
|
||||
<version>0.9.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.nimbusds</groupId>
|
||||
<artifactId>nimbus-jose-jwt</artifactId>
|
||||
<version>8.19</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
@ -34,20 +87,16 @@
|
||||
<artifactId>brave</artifactId>
|
||||
<version>5.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity-engine-core</artifactId>
|
||||
<version>2.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.12.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity</artifactId>
|
||||
<version>1.7</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
|
@ -0,0 +1,33 @@
|
||||
package com.iconplus.smartproc.configuration;
|
||||
|
||||
import com.iconplus.smartproc.model.projection.UserRoleView;
|
||||
import com.iconplus.smartproc.repository.RolesRepository;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class CustomUserDetailsService implements UserDetailsService {
|
||||
|
||||
private final RolesRepository rolesRepository;
|
||||
|
||||
public CustomUserDetailsService(RolesRepository rolesRepository) {
|
||||
this.rolesRepository = rolesRepository;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) {
|
||||
List<SimpleGrantedAuthority> authorities = null;
|
||||
Optional<UserRoleView> userRole = rolesRepository.getUserRoleByUserId(username);
|
||||
if (userRole.isPresent()) {
|
||||
authorities=List.of(new SimpleGrantedAuthority(userRole.get().getRole()));
|
||||
}
|
||||
|
||||
return new org.springframework.security.core.userdetails.User(username, username, authorities);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.iconplus.smartproc.configuration;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.iconplus.smartproc.exception.ErrorResponse;
|
||||
import com.iconplus.smartproc.util.Constants;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
@Log4j2
|
||||
public class JwtAuthenticationAccessDenied implements AccessDeniedHandler {
|
||||
|
||||
private static final String DEFAULT_CODE = "30000";
|
||||
private static final String DEFAULT_MESSAGE = "Access denied";
|
||||
|
||||
@Override
|
||||
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException {
|
||||
|
||||
log.error("Access denied, {}", e.getMessage());
|
||||
|
||||
ErrorResponse errorResponse = new ErrorResponse();
|
||||
errorResponse.setCode(DEFAULT_CODE);
|
||||
errorResponse.setTitle(Constants.TITLE_INVALID_NEXT_STEP);
|
||||
errorResponse.setMessage(DEFAULT_MESSAGE);
|
||||
|
||||
httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
|
||||
httpServletResponse.getOutputStream()
|
||||
.println(new ObjectMapper().writeValueAsString(errorResponse));
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package com.iconplus.smartproc.configuration;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.iconplus.smartproc.exception.ErrorResponse;
|
||||
import com.iconplus.smartproc.util.Constants;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
@Component
|
||||
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException authException) throws IOException {
|
||||
|
||||
ErrorResponse errorResponse = new ErrorResponse();
|
||||
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
|
||||
var exception = (Exception) request.getAttribute("exception");
|
||||
|
||||
String message;
|
||||
|
||||
if (exception != null) {
|
||||
|
||||
if (exception.getCause() != null) {
|
||||
message = exception.getCause().toString() + " " + exception.getMessage();
|
||||
} else {
|
||||
message = exception.getMessage();
|
||||
}
|
||||
|
||||
errorResponse.setCode(Constants.ERR_CODE_40051);
|
||||
errorResponse.setTitle(Constants.TITLE_INVALID_NEXT_STEP);
|
||||
errorResponse.setMessage(message);
|
||||
response.getOutputStream()
|
||||
.println(new ObjectMapper().writeValueAsString(errorResponse));
|
||||
} else {
|
||||
errorResponse.setCode(Constants.ERR_CODE_80007);
|
||||
errorResponse.setTitle(Constants.TITLE_INVALID_NEXT_STEP);
|
||||
errorResponse.setMessage("Invalid Access Token");
|
||||
response.getOutputStream()
|
||||
.println(new ObjectMapper().writeValueAsString(errorResponse));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package com.iconplus.smartproc.configuration;
|
||||
|
||||
import com.iconplus.smartproc.exception.BusinessException;
|
||||
import com.iconplus.smartproc.model.request.PostAccessTokenRequest;
|
||||
import com.iconplus.smartproc.service.authentication.PostCheckAccessTokenService;
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
public class JwtRequestFilter extends OncePerRequestFilter {
|
||||
|
||||
private final JwtTokenUtil jwtTokenUtil;
|
||||
private final PostCheckAccessTokenService postCheckAccessTokenService;
|
||||
|
||||
public JwtRequestFilter(JwtTokenUtil jwtTokenUtil,
|
||||
PostCheckAccessTokenService postCheckAccessTokenService) {
|
||||
this.jwtTokenUtil = jwtTokenUtil;
|
||||
this.postCheckAccessTokenService = postCheckAccessTokenService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
throws ServletException, IOException {
|
||||
try {
|
||||
String jwtToken = extractJwtFromRequest(request);
|
||||
if (StringUtils.hasText(jwtToken) && jwtTokenUtil.validateTokenOnly(jwtToken)) {
|
||||
isValidToken(request, jwtToken);
|
||||
UserDetails userDetails = new org.springframework.security.core.userdetails.User(jwtTokenUtil.getUsernameFromToken(jwtToken), "",
|
||||
jwtTokenUtil.getRolesFromToken(jwtToken));
|
||||
|
||||
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
|
||||
userDetails, null, userDetails.getAuthorities());
|
||||
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
|
||||
}
|
||||
} catch(ExpiredJwtException | BadCredentialsException ex)
|
||||
{
|
||||
request.setAttribute("exception", ex);
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private void isValidToken(HttpServletRequest request, String jwtToken) {
|
||||
String requestUrl = request.getRequestURI();
|
||||
String refreshTokenUrl = "/authentication-service/authentication/v1/refresh-token";
|
||||
if (!refreshTokenUrl.equals(requestUrl)) {
|
||||
var isValid = isValidAuthenticateToken(jwtToken);
|
||||
if (!isValid) {
|
||||
throw new BusinessException(HttpStatus.UNAUTHORIZED, "Invalid Access Token");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidAuthenticateToken(String jwtToken) {
|
||||
return postCheckAccessTokenService.execute(PostAccessTokenRequest.builder()
|
||||
.accessToken(jwtToken)
|
||||
.build()).getIsValid();
|
||||
}
|
||||
|
||||
private String extractJwtFromRequest(HttpServletRequest request) {
|
||||
String bearerToken = request.getHeader("Authorization");
|
||||
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
|
||||
return bearerToken.substring(7);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
package com.iconplus.smartproc.configuration;
|
||||
|
||||
import com.iconplus.smartproc.model.token.TokenContent;
|
||||
import io.jsonwebtoken.*;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.security.KeyPair;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Component
|
||||
public class JwtTokenUtil implements Serializable {
|
||||
private static final long serialVersionUID = -2550185165626007488L;
|
||||
|
||||
@Autowired
|
||||
private KeyPair keyPair;
|
||||
|
||||
//retrieve expiration date from jwt token
|
||||
public Date getExpirationDateFromToken(String token) {
|
||||
return getClaimFromToken(token, Claims::getExpiration);
|
||||
}
|
||||
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
|
||||
final Claims claims = getAllClaimsFromToken(token);
|
||||
return claimsResolver.apply(claims);
|
||||
}
|
||||
//for retrieveing any information from token we will need the secret key
|
||||
public Claims getAllClaimsFromToken(String token) {
|
||||
return Jwts.parser().setSigningKey(keyPair.getPublic()).parseClaimsJws(token).getBody();
|
||||
}
|
||||
|
||||
private Boolean isTokenExpired(String token) {
|
||||
final Date expiration = getExpirationDateFromToken(token);
|
||||
return expiration.before(new Date());
|
||||
}
|
||||
|
||||
public String generateToken(String username, TokenContent tokenContent, Integer expirationInMs, String channel, String scopeType) {
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
|
||||
claims.put("authorities", tokenContent.getAccessMenu());
|
||||
claims.put("fullname", tokenContent.getFullname());
|
||||
claims.put("username", tokenContent.getUsername());
|
||||
claims.put("user_id", tokenContent.getUserId());
|
||||
claims.put("role", tokenContent.getRole());
|
||||
|
||||
return doGenerateToken(claims, username, expirationInMs);
|
||||
}
|
||||
|
||||
public String doGenerateToken(Map<String, Object> claims, String subject, Integer expirationInMs) {
|
||||
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
|
||||
.setExpiration(new Date(System.currentTimeMillis() + expirationInMs))
|
||||
.signWith(SignatureAlgorithm.RS256, keyPair.getPrivate()).compact();
|
||||
}
|
||||
|
||||
public Boolean validateToken(String token, UserDetails userDetails) {
|
||||
final String username = getUsernameFromToken(token);
|
||||
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
|
||||
}
|
||||
|
||||
public boolean validateTokenOnly(String authToken) {
|
||||
try {
|
||||
Jwts.parser().setSigningKey(keyPair.getPublic()).parseClaimsJws(authToken);
|
||||
return true;
|
||||
} catch (SignatureException | MalformedJwtException | UnsupportedJwtException | IllegalArgumentException ex) {
|
||||
throw new BadCredentialsException("INVALID_CREDENTIALS", ex);
|
||||
} catch (ExpiredJwtException ex) {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public String getUsernameFromToken(String token) {
|
||||
Claims claims = Jwts.parser().setSigningKey(keyPair.getPublic()).parseClaimsJws(token).getBody();
|
||||
return claims.getSubject();
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("squid:S4834")
|
||||
public List<SimpleGrantedAuthority> getRolesFromToken(String token) {
|
||||
Claims claims = Jwts.parser().setSigningKey(keyPair.getPublic()).parseClaimsJws(token).getBody();
|
||||
List<SimpleGrantedAuthority> authorityList = new ArrayList<>();
|
||||
ArrayList<String> authorities = claims.get("authorities", ArrayList.class);
|
||||
authorities.forEach(c-> authorityList.add(new SimpleGrantedAuthority(c)));
|
||||
return authorityList;
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.iconplus.smartproc.configuration;
|
||||
|
||||
import com.iconplus.smartproc.util.RSAUtil;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.security.KeyPair;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
@Configuration
|
||||
public class KeyConfiguration {
|
||||
|
||||
@Value("${jwt.private-key}")
|
||||
private String privateKey;
|
||||
|
||||
@Value("${jwt.public-key}")
|
||||
private String publicKey;
|
||||
|
||||
@Bean
|
||||
public KeyPair keypairBean() {
|
||||
|
||||
PublicKey pubKey = RSAUtil.getPublicKey(publicKey);
|
||||
PrivateKey privKey = RSAUtil.getPrivateKey(privateKey);
|
||||
|
||||
return new KeyPair(pubKey, privKey);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package com.iconplus.smartproc.configuration;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
|
||||
|
||||
@Autowired
|
||||
private JwtAuthenticationAccessDenied jwtAuthenticationAccessDenied;
|
||||
|
||||
@Autowired
|
||||
private JwtRequestFilter jwtRequestFilter;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity httpSecurity) throws Exception {
|
||||
httpSecurity
|
||||
.sessionManagement()
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
.sessionFixation().none().and()
|
||||
.csrf().disable();
|
||||
httpSecurity.authorizeRequests()
|
||||
.antMatchers("/api*/**").permitAll()
|
||||
.antMatchers("/actuator/health").permitAll()
|
||||
.antMatchers("/swagger*/**").permitAll()
|
||||
.antMatchers("/v2*/**").permitAll()
|
||||
.antMatchers("/token/jwks.json").permitAll()
|
||||
.anyRequest().authenticated().and()
|
||||
.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
|
||||
.accessDeniedHandler(jwtAuthenticationAccessDenied);
|
||||
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
web.ignoring().antMatchers("/v2/api-docs",
|
||||
"/configuration/ui",
|
||||
"/swagger-resources/**",
|
||||
"/configuration/security",
|
||||
"/swagger-ui.html",
|
||||
"/webjars/**");
|
||||
}
|
||||
}
|
@ -45,7 +45,7 @@ public class UsersController {
|
||||
.orElseThrow(() -> new ResourceNotFoundException("Users not exist with id :" + id));
|
||||
|
||||
users.setUsername(usersDetails.getUsername());
|
||||
users.setNama(usersDetails.getNama());
|
||||
users.setFullname(usersDetails.getFullname());
|
||||
users.setEmail(usersDetails.getEmail());
|
||||
users.setPassword(usersDetails.getPassword());
|
||||
// users.setInstansi(usersDetails.getInstansi());
|
||||
|
@ -1,28 +0,0 @@
|
||||
package com.iconplus.smartproc.exception;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class ErrorDetails {
|
||||
private Date timestamp;
|
||||
private String message;
|
||||
private String details;
|
||||
|
||||
public ErrorDetails(Date timestamp, String message, String details) {
|
||||
super();
|
||||
this.timestamp = timestamp;
|
||||
this.message = message;
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
public Date getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public String getDetails() {
|
||||
return details;
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import org.apache.velocity.Template;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
import org.apache.velocity.app.Velocity;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.context.Context;
|
||||
import org.apache.velocity.runtime.resource.loader.StringResourceLoader;
|
||||
import org.apache.velocity.runtime.resource.util.StringResourceRepository;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@ -88,7 +89,7 @@ public class ErrorHelper {
|
||||
.getApplicationAttribute(StringResourceLoader.REPOSITORY_NAME_DEFAULT);
|
||||
resourceRepository.putStringResource(RAW_TEMPLATE, rawNotificationTemplate);
|
||||
|
||||
return new VelocityContext(parameters);
|
||||
return new VelocityContext((Context) parameters);
|
||||
}
|
||||
|
||||
private void addVelocityProperties() {
|
||||
|
@ -0,0 +1,53 @@
|
||||
package com.iconplus.smartproc.helper.service;
|
||||
|
||||
import com.nimbusds.jose.JWSObject;
|
||||
import com.nimbusds.jose.Payload;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import net.minidev.json.JSONObject;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@Log4j2
|
||||
public class TokenUtils {
|
||||
|
||||
private TokenUtils() {
|
||||
|
||||
}
|
||||
|
||||
public static Map<String, String> decodeToken(String jwtToken) {
|
||||
Map<String, String> body = new HashMap<>();
|
||||
|
||||
try {
|
||||
if (jwtToken != null) {
|
||||
jwtToken = jwtToken.replace("Bearer", "");
|
||||
jwtToken = jwtToken.trim();
|
||||
}
|
||||
if (StringUtils.isBlank(jwtToken)) {
|
||||
return body;
|
||||
}
|
||||
JWSObject token = JWSObject.parse(jwtToken);
|
||||
|
||||
Payload tokenPayload = token.getPayload();
|
||||
JSONObject tokenBody = tokenPayload.toJSONObject();
|
||||
|
||||
tokenBody.forEach((key, value) -> {
|
||||
if (Objects.isNull(value)) {
|
||||
value = "";
|
||||
}
|
||||
|
||||
body.put(key, value.toString());
|
||||
});
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to parse JWT Token. Error: {}", e.getMessage());
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
public static Object getValueByParam(String param, String token) {
|
||||
return decodeToken(token).get(param);
|
||||
}
|
||||
}
|
52
src/main/java/com/iconplus/smartproc/model/entity/Menu.java
Normal file
52
src/main/java/com/iconplus/smartproc/model/entity/Menu.java
Normal file
@ -0,0 +1,52 @@
|
||||
package com.iconplus.smartproc.model.entity;
|
||||
|
||||
import com.iconplus.smartproc.helper.base.BaseEntity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.GeneratorType;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Entity
|
||||
@Table(name = "permission")
|
||||
public class Menu extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "subMenu")
|
||||
private String subMenu;
|
||||
|
||||
@Column(name = "menu")
|
||||
private String menu;
|
||||
|
||||
// @Column(name = "can_view")
|
||||
// @Type(type = "org.hibernate.type.NumericBooleanType")
|
||||
// private Boolean canView;
|
||||
//
|
||||
// @Column(name = "can_read")
|
||||
// @Type(type = "org.hibernate.type.NumericBooleanType")
|
||||
// private Boolean canRead;
|
||||
//
|
||||
// @Column(name = "can_create")
|
||||
// @Type(type = "org.hibernate.type.NumericBooleanType")
|
||||
// private Boolean canCreate;
|
||||
//
|
||||
// @Column(name = "can_delete")
|
||||
// @Type(type = "org.hibernate.type.NumericBooleanType")
|
||||
// private Boolean canDelete;
|
||||
|
||||
@Column(name = "deleted")
|
||||
@Type(type = "org.hibernate.type.NumericBooleanType")
|
||||
private Boolean deleted;
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package com.iconplus.smartproc.model.entity;
|
||||
|
||||
import com.iconplus.smartproc.helper.base.BaseEntity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Table(name = "permission")
|
||||
public class Permission extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(generator = "UUID")
|
||||
@GenericGenerator(
|
||||
name = "UUID",
|
||||
strategy = "org.hibernate.id.UUIDGenerator"
|
||||
)
|
||||
@Column(name = "id")
|
||||
private String id;
|
||||
|
||||
@Column(name = "role_id")
|
||||
private Long roleId;
|
||||
|
||||
@Column(name = "role_id")
|
||||
private Long menuId;
|
||||
|
||||
@Column(name = "deleted")
|
||||
@Type(type = "org.hibernate.type.NumericBooleanType")
|
||||
private Boolean deleted;
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package com.iconplus.smartproc.model.entity;
|
||||
|
||||
import com.iconplus.smartproc.helper.base.BaseEntity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Table(name = "token_management")
|
||||
public class TokenManagement extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(generator = "UUID")
|
||||
@GenericGenerator(
|
||||
name = "UUID",
|
||||
strategy = "org.hibernate.id.UUIDGenerator"
|
||||
)
|
||||
@Column(name = "id")
|
||||
private String id;
|
||||
|
||||
@Column(name = "user_id")
|
||||
private String userId;
|
||||
|
||||
@Lob
|
||||
@Column(name = "access_token")
|
||||
private String accessToken;
|
||||
|
||||
@Lob
|
||||
@Column(name = "refresh_token")
|
||||
private String refreshToken;
|
||||
|
||||
@Column(name = "issued_time")
|
||||
private Timestamp issuedTime;
|
||||
|
||||
@Column(name = "expired_time")
|
||||
private Timestamp expiredTime;
|
||||
|
||||
@Column(name = "deleted")
|
||||
@Type(type = "org.hibernate.type.NumericBooleanType")
|
||||
private Boolean deleted;
|
||||
}
|
@ -20,8 +20,8 @@ public class Users extends BaseEntity {
|
||||
@Column(name = "username")
|
||||
private String username;
|
||||
|
||||
@Column(name = "nama")
|
||||
private String nama;
|
||||
@Column(name = "fullname")
|
||||
private String fullname;
|
||||
|
||||
@Column(name = "email")
|
||||
private String email;
|
||||
|
@ -0,0 +1,16 @@
|
||||
package com.iconplus.smartproc.model.projection;
|
||||
|
||||
import java.sql.Clob;
|
||||
|
||||
public interface TokenManagementView {
|
||||
|
||||
String getId();
|
||||
void setId(String id);
|
||||
|
||||
String getUserId();
|
||||
void setUserId(String userId);
|
||||
|
||||
Clob getAccessToken();
|
||||
void setAccessToken(Clob accessToken);
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.iconplus.smartproc.model.projection;
|
||||
|
||||
public interface UserRoleView {
|
||||
|
||||
Long getId();
|
||||
String getUsername();
|
||||
String getPassword();
|
||||
Long getRoleId();
|
||||
String getRole();
|
||||
Boolean getDeleted();
|
||||
|
||||
void setId(Long id);
|
||||
void setUsername(String username);
|
||||
void setPassword(String password);
|
||||
void setRoleId(Long roleId);
|
||||
void setRole(String role);
|
||||
void setDeleted(Boolean deleted);
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.iconplus.smartproc.model.request;
|
||||
|
||||
import com.iconplus.smartproc.helper.base.BaseRequest;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class LoginRequest extends BaseRequest {
|
||||
|
||||
private String email;
|
||||
private String password;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.iconplus.smartproc.model.request;
|
||||
|
||||
import com.iconplus.smartproc.helper.base.BaseRequest;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PostAccessTokenRequest extends BaseRequest {
|
||||
|
||||
private String accessToken;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.iconplus.smartproc.model.response;
|
||||
|
||||
import com.iconplus.smartproc.helper.base.BaseResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class LoginResponse extends BaseResponse {
|
||||
|
||||
private String accessToken;
|
||||
private String validity;
|
||||
private String refreshToken;
|
||||
private String username;
|
||||
private String email;
|
||||
private Long roleId;
|
||||
private String role;
|
||||
Set<String> accessMenu;
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.iconplus.smartproc.model.response;
|
||||
|
||||
import com.iconplus.smartproc.helper.base.BaseResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class PostAccessTokenResponse extends BaseResponse {
|
||||
|
||||
private Boolean isValid;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.iconplus.smartproc.model.token;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
public class TokenContent {
|
||||
private String userId;
|
||||
private String role;
|
||||
private Set<String> accessMenu;
|
||||
private String fullname;
|
||||
private String username;
|
||||
}
|
@ -1,10 +1,26 @@
|
||||
package com.iconplus.smartproc.repository;
|
||||
|
||||
import com.iconplus.smartproc.model.entity.Roles;
|
||||
import com.iconplus.smartproc.model.projection.UserRoleView;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface RolesRepository extends JpaRepository<Roles, Long> {
|
||||
|
||||
@Query(value = "SELECT u.id as id, " +
|
||||
"u.username as username, " +
|
||||
"u.password as password, " +
|
||||
"u.roleId as roleId, " +
|
||||
"r.role as role " +
|
||||
"FROM Users u " +
|
||||
"join Roles r on r.id=u.roleId " +
|
||||
"WHERE u.deleted = false " +
|
||||
"AND r.deleted = false " +
|
||||
"AND u.username = :userName ")
|
||||
Optional<UserRoleView> getUserRoleByUserId(String userName);
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
package com.iconplus.smartproc.repository;
|
||||
|
||||
import com.iconplus.smartproc.model.entity.TokenManagement;
|
||||
import com.iconplus.smartproc.model.projection.TokenManagementView;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface TokenManagementRepository extends JpaRepository<TokenManagement, String> {
|
||||
|
||||
@Query(value = "SELECT access_token as accessToken FROM token_management " +
|
||||
"WHERE user_id = :userId " +
|
||||
"AND deleted = false " +
|
||||
"AND expired_time >= SYSDATE", nativeQuery = true)
|
||||
List<TokenManagementView> findAccessTokenByUserIdAndDeletedFalse(String userId);
|
||||
}
|
@ -4,7 +4,11 @@ import com.iconplus.smartproc.model.entity.Users;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface UsersRepository extends JpaRepository<Users, Long> {
|
||||
|
||||
Optional<Users> findByEmailAndDeletedFalse(String email);
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
package com.iconplus.smartproc.service.authentication;
|
||||
|
||||
import com.iconplus.smartproc.exception.BusinessException;
|
||||
import com.iconplus.smartproc.helper.service.BaseService;
|
||||
import com.iconplus.smartproc.model.request.LoginRequest;
|
||||
import com.iconplus.smartproc.model.response.LoginResponse;
|
||||
import com.iconplus.smartproc.repository.UsersRepository;
|
||||
import com.iconplus.smartproc.util.Constants;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class LoginService implements BaseService<LoginRequest, LoginResponse> {
|
||||
|
||||
|
||||
private final UsersRepository usersRepository;
|
||||
|
||||
public LoginService(UsersRepository userRepository) {
|
||||
this.usersRepository = userRepository;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginResponse execute(LoginRequest input) {
|
||||
|
||||
var user= usersRepository.findByEmailAndDeletedFalse(input.getEmail())
|
||||
.orElseThrow(() -> new BusinessException(HttpStatus.CONFLICT,
|
||||
Constants.ERR_CODE_10003,
|
||||
Constants.ERR_TTL_10003,
|
||||
String.format(Constants.ERR_MSG_10003, input.getEmail())));
|
||||
|
||||
if (!StringUtils.equalsIgnoreCase(input.getPassword(), user.getPassword())) {
|
||||
throw new BusinessException(HttpStatus.CONFLICT,
|
||||
Constants.ERR_CODE_10004,
|
||||
Constants.ERR_TTL_10004,
|
||||
Constants.ERR_MSG_10004);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return LoginResponse.builder()
|
||||
.build();
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package com.iconplus.smartproc.service.authentication;
|
||||
|
||||
import com.iconplus.smartproc.helper.service.BaseService;
|
||||
import com.iconplus.smartproc.helper.service.TokenUtils;
|
||||
import com.iconplus.smartproc.model.projection.TokenManagementView;
|
||||
import com.iconplus.smartproc.model.request.PostAccessTokenRequest;
|
||||
import com.iconplus.smartproc.model.response.PostAccessTokenResponse;
|
||||
import com.iconplus.smartproc.repository.TokenManagementRepository;
|
||||
import com.iconplus.smartproc.util.CommonUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class PostCheckAccessTokenService implements BaseService<PostAccessTokenRequest, PostAccessTokenResponse> {
|
||||
|
||||
private TokenManagementRepository tokenManagementRepository;
|
||||
|
||||
public PostCheckAccessTokenService(TokenManagementRepository tokenManagementRepository) {
|
||||
this.tokenManagementRepository = tokenManagementRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PostAccessTokenResponse execute(PostAccessTokenRequest input) {
|
||||
|
||||
var decodeToken = TokenUtils.decodeToken(input.getAccessToken());
|
||||
String userId = decodeToken.get("user_id");
|
||||
|
||||
List<TokenManagementView> tokenManagementViews = tokenManagementRepository.findAccessTokenByUserIdAndDeletedFalse(userId);
|
||||
if (tokenManagementViews.isEmpty()) {
|
||||
log.error("access token not found in db");
|
||||
return PostAccessTokenResponse.builder()
|
||||
.isValid(false)
|
||||
.build();
|
||||
}
|
||||
|
||||
List<String> userTokenList = tokenManagementViews.stream()
|
||||
.map(c-> CommonUtil.clobToString(c.getAccessToken()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
boolean isMatch = userTokenList.stream().anyMatch(s -> s.equals(input.getAccessToken()));
|
||||
if (isMatch) {
|
||||
return PostAccessTokenResponse.builder()
|
||||
.isValid(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
return PostAccessTokenResponse.builder()
|
||||
.isValid(false)
|
||||
.build();
|
||||
}
|
||||
}
|
25
src/main/java/com/iconplus/smartproc/util/CommonUtil.java
Normal file
25
src/main/java/com/iconplus/smartproc/util/CommonUtil.java
Normal file
@ -0,0 +1,25 @@
|
||||
package com.iconplus.smartproc.util;
|
||||
|
||||
import com.iconplus.smartproc.exception.TechnicalException;
|
||||
|
||||
import java.sql.Clob;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class CommonUtil {
|
||||
private CommonUtil() {
|
||||
}
|
||||
|
||||
public static String clobToString(Clob input) {
|
||||
try {
|
||||
if (input != null) {
|
||||
return input.getSubString(1, (int) input.length());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (SQLException exception) {
|
||||
throw new TechnicalException(Constants.ERR_TTL_40041,
|
||||
Constants.ERR_TTL_40041,
|
||||
Constants.ERR_MSG_40041);
|
||||
}
|
||||
}
|
||||
}
|
@ -12,4 +12,21 @@ public class Constants {
|
||||
public static final String ERR_TTL_10002 = "Data tersedia";
|
||||
public static final String ERR_MSG_10002 = "Jenis Anggaran dengan id : %s sudah tersedia";
|
||||
|
||||
public static final String ERR_CODE_10003 = "10003";
|
||||
public static final String ERR_TTL_10003 = "Data tidak tersedia";
|
||||
public static final String ERR_MSG_10003 = "User dengan email : %s tidak ditemukan";
|
||||
|
||||
public static final String ERR_CODE_10004 = "10004";
|
||||
public static final String ERR_TTL_10004 = "Gagal Authentikasi User";
|
||||
public static final String ERR_MSG_10004 = "Silahkan Periksa kembali Email dan Password Anda";
|
||||
|
||||
public static final String ERR_CODE_40041 = "40041";
|
||||
public static final String ERR_TTL_40041 = "Terjadi Gangguan";
|
||||
public static final String ERR_MSG_40041 = "Masalah Koneksi System";
|
||||
|
||||
public static final String ERR_CODE_40051 = "40051";
|
||||
public static final String ERR_CODE_80007 = "80007";
|
||||
public static final String TITLE_INVALID_NEXT_STEP = "Proses tidak dapat dilanjutkan";
|
||||
|
||||
|
||||
}
|
||||
|
109
src/main/java/com/iconplus/smartproc/util/RSAUtil.java
Normal file
109
src/main/java/com/iconplus/smartproc/util/RSAUtil.java
Normal file
@ -0,0 +1,109 @@
|
||||
package com.iconplus.smartproc.util;
|
||||
|
||||
import com.iconplus.smartproc.exception.TechnicalException;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.security.*;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Base64;
|
||||
|
||||
@Log4j2
|
||||
public class RSAUtil {
|
||||
|
||||
private RSAUtil(){
|
||||
|
||||
}
|
||||
|
||||
public static PrivateKey getPrivateKey(String base64PrivateKey){
|
||||
PrivateKey privateKey = null;
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(base64PrivateKey.getBytes()));
|
||||
try {
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
privateKey = keyFactory.generatePrivate(keySpec);
|
||||
} catch (InvalidKeySpecException e) {
|
||||
log.error("InvalidKeySpecException : "+e.getMessage());
|
||||
throw new TechnicalException("80000", "InvalidKeySpecException : "+e.getMessage());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
log.error("NoSuchAlgorithmException : "+e.getMessage());
|
||||
throw new TechnicalException("80000", "NoSuchAlgorithmException : "+e.getMessage());
|
||||
}
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
public static PublicKey getPublicKey(String base64PublicKey){
|
||||
PublicKey publicKey = null;
|
||||
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes()));
|
||||
try {
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
publicKey = keyFactory.generatePublic(keySpec);
|
||||
} catch (InvalidKeySpecException e) {
|
||||
log.error("InvalidKeySpecException : "+e.getMessage());
|
||||
throw new TechnicalException("80000", "InvalidKeySpecException : "+e.getMessage());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
log.error("NoSuchAlgorithmException : "+e.getMessage());
|
||||
throw new TechnicalException("80000", "NoSuchAlgorithmException : "+e.getMessage());
|
||||
}
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
private static String decryptChipper(byte[] data, PrivateKey privateKey) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
return new String(cipher.doFinal(data));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
log.error("NoSuchAlgorithmException : "+e.getMessage());
|
||||
throw new TechnicalException("80000", "NoSuchAlgorithmException : "+e.getMessage());
|
||||
} catch (NoSuchPaddingException e) {
|
||||
log.error("NoSuchPaddingException : "+e.getMessage());
|
||||
throw new TechnicalException("80000", "NoSuchPaddingException : "+e.getMessage());
|
||||
} catch (InvalidKeyException e) {
|
||||
log.error("InvalidKeyException : "+e.getMessage());
|
||||
throw new TechnicalException("80000", "InvalidKeyException : "+e.getMessage());
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
log.error("IllegalBlockSizeException : "+e.getMessage());
|
||||
throw new TechnicalException("80000", "IllegalBlockSizeException : "+e.getMessage());
|
||||
} catch (BadPaddingException e) {
|
||||
log.error("BadPaddingException : "+e.getMessage());
|
||||
throw new TechnicalException("80000", "BadPaddingException : "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] encryptChipper(byte[] data, PublicKey publicKey) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
return cipher.doFinal(data);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
log.error("NoSuchAlgorithmException : "+e.getMessage());
|
||||
throw new TechnicalException("80000", "NoSuchAlgorithmException : "+e.getMessage());
|
||||
} catch (NoSuchPaddingException e) {
|
||||
log.error("NoSuchPaddingException : "+e.getMessage());
|
||||
throw new TechnicalException("80000", "NoSuchPaddingException : "+e.getMessage());
|
||||
} catch (InvalidKeyException e) {
|
||||
log.error("InvalidKeyException : "+e.getMessage());
|
||||
throw new TechnicalException("80000", "InvalidKeyException : "+e.getMessage());
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
log.error("IllegalBlockSizeException : "+e.getMessage());
|
||||
throw new TechnicalException("80000", "IllegalBlockSizeException : "+e.getMessage());
|
||||
} catch (BadPaddingException e) {
|
||||
log.error("BadPaddingException : "+e.getMessage());
|
||||
throw new TechnicalException("80000", "BadPaddingException : "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static String decrypt(String data, String base64PrivateKey) {
|
||||
return decryptChipper(Base64.getDecoder().decode(data.getBytes()), getPrivateKey(base64PrivateKey));
|
||||
}
|
||||
|
||||
public static String encrypt(String data, String base64PublicKey) {
|
||||
return Base64.getEncoder().encodeToString(encryptChipper(data.getBytes(), getPublicKey(base64PublicKey)));
|
||||
}
|
||||
|
||||
}
|
22
src/main/resources/application-local.yml
Normal file
22
src/main/resources/application-local.yml
Normal file
@ -0,0 +1,22 @@
|
||||
#Configuration for database
|
||||
jwt:
|
||||
public-key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx3MRA7zxvaWKrtmPl2hRJLFiyryvj0ZUlmWw9OZIgqwJUDBTsg5yFX4hCQrANV1yy5ibTqAn2APdNCdhGgp8R2YLWrUR2vVGbmnKXXzEDsFpT6cgo+/a+lWaUq8aYEhzVg8Xjmy9oG1s521LklEz/jKD2xNE4OgY2Y1SgfUH+bexs84ZEyUhcSpCrcZenjCns7Ubp9zsWPrXa/j6kr7ZuFWH7nXN/i+oYF0HFhc+hDaVr2R9Q7s56wAQNE8XfI2Q+h4iRI1hWa5Vva9ha1DnCN9McJDLBHoGy1coIUEoQKkDhCNQmdHlubIJYDoFIyfDTrSQIXw2gzrrC9sOgYU64wIDAQAB
|
||||
private-key: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDHcxEDvPG9pYqu2Y+XaFEksWLKvK+PRlSWZbD05kiCrAlQMFOyDnIVfiEJCsA1XXLLmJtOoCfYA900J2EaCnxHZgtatRHa9UZuacpdfMQOwWlPpyCj79r6VZpSrxpgSHNWDxeObL2gbWznbUuSUTP+MoPbE0Tg6BjZjVKB9Qf5t7GzzhkTJSFxKkKtxl6eMKeztRun3OxY+tdr+PqSvtm4VYfudc3+L6hgXQcWFz6ENpWvZH1DuznrABA0Txd8jZD6HiJEjWFZrlW9r2FrUOcI30xwkMsEegbLVyghQShAqQOEI1CZ0eW5sglgOgUjJ8NOtJAhfDaDOusL2w6BhTrjAgMBAAECggEAL8SPPqXx/8m1/Up96XVCeddCIewu39GoUJzqVL0SgLlTQbFRWkO7bwpWPyQkBKPs6nYSPDJ/WG0UfXkw+FuqiC8YaREUxawYwjj0Do/jJOWNo1YTqy+28l2uKD9nwceYV/QlYCcLA3Exs/upLdHk8eyHR+DFjlgIG5KNQDK/Rj8cLdQGJjAZjHUGzaRq/HhDi+0LVkOoUvzbzle8RSiiZnNrxCt0UV1CambQzvyxXzqLgtGe4s+qItwk/zzkvXDRnRju3+/AyaFaToA2Wnp9gdV2rT4cRGHhj0Dqh0vwrBH4RiPtEfLQjIa9DhTPHfpr6ACGe6GF96fJ889WIEl4gQKBgQDrGgYKGwIhY9j2V7tu6eHmLxYFGzxSPOtfBZPzSLUyQXrcd6wFlb+Fsae2bgBFZJzilIv4lG0wNaGSFjAjteyXMoqVCTIUKJCjzWs+g3qjuA5fu9IAeWEEaXuKSVvkV5tJrnwhmqYdH1jQx5xhpO434W2a4wuEgOnU6SzNjvS/TwKBgQDZLb3Q9KRwlMcyt/rgjeTOf2SD1jvlKD2t+YRuaxlzBs7j99hCEP3GLaTz6/rIptfkutwk10FM/piO5PCyoPXNc2A1Z73ukmsirMRy2G06PfqKBQrV/B9vtIqPW1Agz7KUpXARrHL8Bb6T2ljKl2HU+kC4Pgx2GZQgYnbEvNBGLQKBgQCNf3grFN5PYlzuxxbURofjlmtWX3IKvQechSrqvdPwj2B22L/8DIjc2nPqZIJdQZT6+hTUY+DjpyO7XQdUNuZSieTGlmZBo7iKHdRyJ4fkiZ59F/notyUhFqt4K3bXE7MuwYmMYBuiY399COaiDjYiA9eH5SbFdSFHN5/ziBreGQKBgGZHNG2DyS1745PvMScvq+HT/PJZojt5iBK2v7eAmKujOSwDPMVgWyNJu7VkHOcCLAp8NdDjzs0D2bTx/KkjRJ9NBrIf+UKxkeLymlG7uzUCm0sEtOWxptxkmhyJVGMfbWqzvuOT41LtIaNf4REH2fsDIBekoRm9UhUuSeC9SxjBAoGAP6pdT7HlMsr++XJFqs9+dj7tRsX+a6Coi3T8BFaf2Nl9YxMFFaSBbNOO4QfZWyCUcfbkLrcdEka5VTVt/HwckDKzckxWqH3hMn2+kAKJnHhAvB1M38KAyvdpA54vNgVyID+vL5VbqpHk8wsUbVWZc8F/ERELfuHwzcD0rt6Opnc=
|
||||
expired-time :
|
||||
service-account:
|
||||
access-token: 480
|
||||
refresh-token: 720
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
driver-class-name: org.postgresql.Driver
|
||||
url: jdbc:postgresql://localhost:5432/smartproc
|
||||
username: postgres
|
||||
password: postgre
|
||||
jackson:
|
||||
default-property-inclusion: NON_NULL
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: update
|
||||
database-platform: org.hibernate.dialect.PostgreSQLDialect
|
||||
show-sql: true
|
@ -1,12 +0,0 @@
|
||||
spring.datasource.url=jdbc:postgresql://localhost:5432/smartproc
|
||||
spring.datasource.username=postgres
|
||||
spring.datasource.password=postgre
|
||||
spring.jpa.show-sql=true
|
||||
|
||||
## Hibernate Properties
|
||||
# The SQL dialect makes Hibernate generate better SQL for the chosen database
|
||||
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
|
||||
|
||||
# Hibernate ddl auto (create, create-drop, validate, update)
|
||||
spring.jpa.hibernate.ddl-auto = update
|
||||
server.port=9090
|
7
src/main/resources/application.yml
Normal file
7
src/main/resources/application.yml
Normal file
@ -0,0 +1,7 @@
|
||||
spring:
|
||||
application:
|
||||
name: "smartproc-service"
|
||||
profiles:
|
||||
active: local
|
||||
server:
|
||||
port: 9090
|
5
src/main/resources/bootstrap.properties
Normal file
5
src/main/resources/bootstrap.properties
Normal file
@ -0,0 +1,5 @@
|
||||
spring.application.name=smartproc
|
||||
spring.profiles.active=@spring.profiles.active@
|
||||
management.endpoints.web.exposure.include=*
|
||||
management.endpoint.health.show-details=ALWAYS
|
||||
management.metrics.tags.application=${spring.application.name}
|
Loading…
x
Reference in New Issue
Block a user