add spring security and token management
This commit is contained in:
		| @@ -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))); | ||||
|     } | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user