From 7dfed155bc4f5a1c7cf5a592e8325dc1ba9243bc Mon Sep 17 00:00:00 2001 From: wayne <wayne8692wayne8692@gmail.com> Date: 星期一, 22 十一月 2021 15:48:09 +0800 Subject: [PATCH] [update] otp登入、認證、顧問EService登入 --- pamapi/src/main/java/com/pollex/pam/service/OtpWebService.java | 63 +++ pamapi/src/doc/登入API/客戶發手機OTP.txt | 15 pamapi/src/main/resources/config/application-sit.yml | 1 pamapi/src/main/java/com/pollex/pam/security/jwt/TokenProvider.java | 6 pamapi/src/main/java/com/pollex/pam/web/rest/TestLoginResource.java | 89 ++++ pamapi/src/doc/登入API/客戶發EmailOTP.txt | 15 pamapi/src/doc/登入API/顧問登入ByEService.txt | 18 + pamapi/src/main/java/com/pollex/pam/enums/CustomerDetailEnum.java | 17 pamapi/src/main/java/com/pollex/pam/web/rest/OtpResource.java | 100 +++++ pamapi/src/main/java/com/pollex/pam/web/rest/vm/VerifyOtpVM.java | 19 pamapi/src/main/java/com/pollex/pam/config/ApplicationProperties.java | 9 pamapi/pom.xml | 39 ++ pamapi/src/main/java/com/pollex/pam/repository/CustomerRepository.java | 5 pamapi/src/main/resources/config/application-dev.yml | 1 pamapi/src/main/java/com/pollex/pam/web/rest/vm/OtpAccount.java | 27 + pamapi/src/main/java/com/pollex/pam/enums/ConsultantDetailEnum.java | 17 pamapi/src/main/java/com/pollex/pam/web/rest/EServiceResource.java | 46 ++ pamapi/src/main/java/com/pollex/pam/security/SecurityUtils.java | 16 /dev/null | 71 --- pamapi/src/main/java/com/pollex/pam/config/SecurityConfiguration.java | 2 pamapi/src/main/java/com/pollex/pam/web/rest/vm/EServiceLoginVM.java | 2 pamapi/src/main/java/com/pollex/pam/service/LoginService.java | 1 pamapi/src/main/java/com/pollex/pam/service/ConsultantService.java | 4 pamapi/src/main/java/com/pollex/pam/repository/ConsultantRepository.java | 3 pamapi/src/main/resources/config/application-uat.yml | 118 ++++++ pamapi/src/doc/登入API/客戶認證OTP並登入.txt | 17 pamapi/src/main/java/com/pollex/pam/security/provider/EServiceAuthenticationProvider.java | 123 ++++++ pamapi/src/main/java/com/pollex/pam/security/provider/CustomAuthenticationProvider.java | 41 ++ pamapi/src/main/java/com/pollex/pam/security/token/OtpAuthenticationToken.java | 47 ++ pamapi/src/main/java/com/pollex/pam/security/provider/OtpAuthenticationProvider.java | 80 ++++ pamapi/src/main/java/com/pollex/pam/security/token/EServiceAuthenticationToken.java | 53 ++ 31 files changed, 974 insertions(+), 91 deletions(-) diff --git a/pamapi/pom.xml b/pamapi/pom.xml index 1fd6eab..76a25f6 100644 --- a/pamapi/pom.xml +++ b/pamapi/pom.xml @@ -984,6 +984,45 @@ </properties> </profile> <profile> + <id>uat</id> + <dependencies> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-undertow</artifactId> + <scope>provided</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <artifactId>maven-clean-plugin</artifactId> + <configuration> + <filesets> + <fileset> + <directory>target/classes/static/</directory> + </fileset> + </filesets> + </configuration> + </plugin> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>build-info</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + <properties> + <!-- default Spring profiles --> + <spring.profiles.active>uat{profile.api-docs}${profile.tls}${profile.no-liquibase}</spring.profiles.active> + </properties> + </profile> + <profile> <id>prod</id> <dependencies> <dependency> diff --git "a/pamapi/src/doc/\347\231\273\345\205\245API/\345\256\242\346\210\266\347\231\274EmailOTP.txt" "b/pamapi/src/doc/\347\231\273\345\205\245API/\345\256\242\346\210\266\347\231\274EmailOTP.txt" new file mode 100644 index 0000000..d1fba1e --- /dev/null +++ "b/pamapi/src/doc/\347\231\273\345\205\245API/\345\256\242\346\210\266\347\231\274EmailOTP.txt" @@ -0,0 +1,15 @@ +http post: +http://localhost:8080/api/otp/byEmail + +request body: +{ + "email":"test@pollex.com.tw" +} + +response body: +{ + "indexKey": "7830d17b", + "success": true, + "failCode": "", + "failReason": "" +} diff --git "a/pamapi/src/doc/\347\231\273\345\205\245API/\345\256\242\346\210\266\347\231\274\346\211\213\346\251\237OTP.txt" "b/pamapi/src/doc/\347\231\273\345\205\245API/\345\256\242\346\210\266\347\231\274\346\211\213\346\251\237OTP.txt" new file mode 100644 index 0000000..6072e63 --- /dev/null +++ "b/pamapi/src/doc/\347\231\273\345\205\245API/\345\256\242\346\210\266\347\231\274\346\211\213\346\251\237OTP.txt" @@ -0,0 +1,15 @@ +http post: +http://localhost:8080/api/otp/byPhone + +request body: +{ + "phone":"0912345678" +} + +response body: +{ + "indexKey": "5913a8cd", + "success": true, + "failCode": "", + "failReason": "" +} diff --git "a/pamapi/src/doc/\347\231\273\345\205\245API/\345\256\242\346\210\266\350\252\215\350\255\211OTP\344\270\246\347\231\273\345\205\245.txt" "b/pamapi/src/doc/\347\231\273\345\205\245API/\345\256\242\346\210\266\350\252\215\350\255\211OTP\344\270\246\347\231\273\345\205\245.txt" new file mode 100644 index 0000000..124c914 --- /dev/null +++ "b/pamapi/src/doc/\347\231\273\345\205\245API/\345\256\242\346\210\266\350\252\215\350\255\211OTP\344\270\246\347\231\273\345\205\245.txt" @@ -0,0 +1,17 @@ +http post: +http://localhost:8080/api/otp/verify + +request body: +{ + "account": "wayne@pollex.com.tw", // �撣嗅����mail嚗�ㄐ撌涪mail�蝭�� + "indexKey": "123", // �otp��pi���ndex key + "otpCode": "123" // �����縑蝞望�����Ⅳ +} + +���ev銝剖恥�撣唾���撌崎eams��mail靽∠拳��� (�����垢撌亦�葦��A撣唾�歇蝬�末)�� +�ndexKey��tpCode�dev�銝��遙雿���隞亦��� + +response body: +{ + "id_token": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ3YXluZUBwb2xsZXguY29tLnR3IiwiYXV0aCI6IlJPTEVfVVNFUiIsImRldGFpbHMiOnsiQ3VzdG9tZXJBY2NvdW50Ijoid2F5bmVAcG9sbGV4LmNvbS50dyIsIkN1c3RvbWVySWQiOiI2IiwiQ3VzdG9tZXJOYW1lIjoiV2F5bmUifSwiZXhwIjoxNjM3NjQ5NzUzfQ.6xqkWG7kQPUHOys8vPdx6ebgH1wgZ4gysFEa1t1jCnKB44VsFZ8PjtUlN2mvroBdGtPwpOynoTHU7HvAQ3_mnQ" +} diff --git "a/pamapi/src/doc/\347\231\273\345\205\245API/\351\241\247\345\225\217\347\231\273\345\205\245ByEService.txt" "b/pamapi/src/doc/\347\231\273\345\205\245API/\351\241\247\345\225\217\347\231\273\345\205\245ByEService.txt" new file mode 100644 index 0000000..1c0158e --- /dev/null +++ "b/pamapi/src/doc/\347\231\273\345\205\245API/\351\241\247\345\225\217\347\231\273\345\205\245ByEService.txt" @@ -0,0 +1,18 @@ +http post: +http://localhost:8080/api/eService/authenticate + +request body: +{ + "username": "D265260662", + "password": "test123" +} + +����憿批����ngela���10�“��葫閰西��� +瑼��:PCA-Matching Platform-test-data 1108.xlsx + +撣唾��xcel銝��憛怠神嚗�Ⅳ�dev蝡臭蒂�敺Service瑼X嚗隞亦��� + +response body: +{ + "id_token": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJEMjY1MjYwNjYyIiwiYXV0aCI6IlJPTEVfVVNFUiIsImRldGFpbHMiOnsiQ29uc3VsdGFudEFnZW50Tm8iOiJEMjY1MjYwNjYyIiwiQ29uc3VsdGFudE5hbWUiOiLmnpfmiJDlrIwiLCJDb25zdWx0YW50SWQiOiI1In0sImV4cCI6MTYzNzY0OTQ5NX0.BjLiA-nuJOsUtD6UqyONr3brPXbdhjA_5srFBS2qgcvFhfznSOCZMlHtl4NtphiZ1CAk2jyg79QFlqGvM6Uk1A" +} diff --git a/pamapi/src/main/java/com/pollex/pam/config/ApplicationProperties.java b/pamapi/src/main/java/com/pollex/pam/config/ApplicationProperties.java index 6270c33..68ed03f 100644 --- a/pamapi/src/main/java/com/pollex/pam/config/ApplicationProperties.java +++ b/pamapi/src/main/java/com/pollex/pam/config/ApplicationProperties.java @@ -11,11 +11,20 @@ @ConfigurationProperties(prefix = "application", ignoreUnknownFields = false) public class ApplicationProperties { + private boolean mockLogin; private String otpWebServiceUrl; private String otpWebServicePassword; private String otpWebServiceSystemType; private String eServiceLoginUrl; + public boolean isMockLogin() { + return mockLogin; + } + + public void setMockLogin(boolean mockLogin) { + this.mockLogin = mockLogin; + } + public String getOtpWebServiceUrl() { return otpWebServiceUrl; } diff --git a/pamapi/src/main/java/com/pollex/pam/config/SecurityConfiguration.java b/pamapi/src/main/java/com/pollex/pam/config/SecurityConfiguration.java index 5052121..4349448 100644 --- a/pamapi/src/main/java/com/pollex/pam/config/SecurityConfiguration.java +++ b/pamapi/src/main/java/com/pollex/pam/config/SecurityConfiguration.java @@ -82,6 +82,8 @@ .antMatchers("/api/register").permitAll() .antMatchers("/api/activate").permitAll() .antMatchers("/api/testLogin/**").permitAll() + .antMatchers("/api/otp/**").permitAll() + .antMatchers("/api/eService/authenticate").permitAll() .antMatchers("/api/account/reset-password/init").permitAll() .antMatchers("/api/account/reset-password/finish").permitAll() .antMatchers("/api/consultant/recommend").permitAll() diff --git a/pamapi/src/main/java/com/pollex/pam/enums/ConsultantDetailEnum.java b/pamapi/src/main/java/com/pollex/pam/enums/ConsultantDetailEnum.java new file mode 100644 index 0000000..331dd27 --- /dev/null +++ b/pamapi/src/main/java/com/pollex/pam/enums/ConsultantDetailEnum.java @@ -0,0 +1,17 @@ +package com.pollex.pam.enums; + +public enum ConsultantDetailEnum { + ID("ConsultantId"), + NAME("ConsultantName"), + AGENT_NO("ConsultantAgentNo"); + + private final String value; + + ConsultantDetailEnum(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/pamapi/src/main/java/com/pollex/pam/enums/CustomerDetailEnum.java b/pamapi/src/main/java/com/pollex/pam/enums/CustomerDetailEnum.java new file mode 100644 index 0000000..692c87a --- /dev/null +++ b/pamapi/src/main/java/com/pollex/pam/enums/CustomerDetailEnum.java @@ -0,0 +1,17 @@ +package com.pollex.pam.enums; + +public enum CustomerDetailEnum { + ID("CustomerId"), + NAME("CustomerName"), + ACCOUNT("CustomerAccount"); + + private final String value; + + CustomerDetailEnum(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/pamapi/src/main/java/com/pollex/pam/repository/ConsultantRepository.java b/pamapi/src/main/java/com/pollex/pam/repository/ConsultantRepository.java index d373143..af244ab 100644 --- a/pamapi/src/main/java/com/pollex/pam/repository/ConsultantRepository.java +++ b/pamapi/src/main/java/com/pollex/pam/repository/ConsultantRepository.java @@ -10,8 +10,7 @@ @Repository public interface ConsultantRepository extends JpaRepository<Consultant, Long>, JpaSpecificationExecutor<Consultant> { - Optional<Consultant> findFirstByAgentNo(String agentNo); + Optional<Consultant> findOneByAgentNo(String agentNo); List<Consultant> findAllByRecommendIsTrue(); List<Consultant> findAllByAgentNoIn(List<String> agentNoList); - } diff --git a/pamapi/src/main/java/com/pollex/pam/repository/CustomerRepository.java b/pamapi/src/main/java/com/pollex/pam/repository/CustomerRepository.java index c4b87cf..eb84506 100644 --- a/pamapi/src/main/java/com/pollex/pam/repository/CustomerRepository.java +++ b/pamapi/src/main/java/com/pollex/pam/repository/CustomerRepository.java @@ -5,7 +5,10 @@ import com.pollex.pam.domain.Customer; +import java.util.List; +import java.util.Optional; + @Repository public interface CustomerRepository extends JpaRepository<Customer, Long>{ - + Optional<Customer> findOneByEmailEqualsOrPhoneEquals(String email, String phone); } diff --git a/pamapi/src/main/java/com/pollex/pam/security/SecurityUtils.java b/pamapi/src/main/java/com/pollex/pam/security/SecurityUtils.java index ef4095a..5e6c77b 100644 --- a/pamapi/src/main/java/com/pollex/pam/security/SecurityUtils.java +++ b/pamapi/src/main/java/com/pollex/pam/security/SecurityUtils.java @@ -5,6 +5,8 @@ import java.util.Optional; import java.util.stream.Stream; +import com.pollex.pam.enums.ConsultantDetailEnum; +import com.pollex.pam.enums.CustomerDetailEnum; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContext; @@ -99,18 +101,18 @@ private static Stream<String> getAuthorities(Authentication authentication) { return authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority); } - + public static String getAgentNo() { - return getCurrentUserLogin().orElseGet(null); + Map<String, String> userDetails = getCurrentUserDetails(); + return userDetails.get(ConsultantDetailEnum.AGENT_NO.getValue()); } - + // todo , should get id from user details public static Long getCustomerId() { -// Map<String, String> userDetails = getCurrentUserDetails(); -// return Long.parseLong(userDetails.get("id")); - return Long.parseLong("2"); + Map<String, String> userDetails = getCurrentUserDetails(); + return Long.parseLong(userDetails.get(CustomerDetailEnum.ID.getValue())); } - + public static Map<String, String> getCurrentUserDetails() { SecurityContext securityContext = SecurityContextHolder.getContext(); if(securityContext.getAuthentication()==null || diff --git a/pamapi/src/main/java/com/pollex/pam/security/jwt/TokenProvider.java b/pamapi/src/main/java/com/pollex/pam/security/jwt/TokenProvider.java index d17fca0..1986286 100644 --- a/pamapi/src/main/java/com/pollex/pam/security/jwt/TokenProvider.java +++ b/pamapi/src/main/java/com/pollex/pam/security/jwt/TokenProvider.java @@ -24,6 +24,7 @@ private final Logger log = LoggerFactory.getLogger(TokenProvider.class); private static final String AUTHORITIES_KEY = "auth"; + private static final String AUTHORITIES_DETAILS = "details"; private final Key key; @@ -69,6 +70,7 @@ .builder() .setSubject(authentication.getName()) .claim(AUTHORITIES_KEY, authorities) + .claim(AUTHORITIES_DETAILS, authentication.getDetails()) .signWith(key, SignatureAlgorithm.HS512) .setExpiration(validity) .compact(); @@ -84,8 +86,10 @@ .collect(Collectors.toList()); User principal = new User(claims.getSubject(), "", authorities); + UsernamePasswordAuthenticationToken authInfo = new UsernamePasswordAuthenticationToken(principal, token, authorities); + authInfo.setDetails(claims.get(AUTHORITIES_DETAILS)); - return new UsernamePasswordAuthenticationToken(principal, token, authorities); + return authInfo; } public boolean validateToken(String authToken) { diff --git a/pamapi/src/main/java/com/pollex/pam/security/provider/CustomAuthenticationProvider.java b/pamapi/src/main/java/com/pollex/pam/security/provider/CustomAuthenticationProvider.java new file mode 100644 index 0000000..079a473 --- /dev/null +++ b/pamapi/src/main/java/com/pollex/pam/security/provider/CustomAuthenticationProvider.java @@ -0,0 +1,41 @@ +package com.pollex.pam.security.provider; + +import com.pollex.pam.config.ApplicationProperties; +import com.pollex.pam.security.token.EServiceAuthenticationToken; +import com.pollex.pam.security.token.OtpAuthenticationToken; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.stereotype.Component; + + +@Component +public class CustomAuthenticationProvider implements AuthenticationProvider { + + @Autowired + EServiceAuthenticationProvider eServiceAuthenticationProvider; + + @Autowired + OtpAuthenticationProvider otpAuthenticationProvider; + + @Autowired + ApplicationProperties applicationProperty; + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + if(authentication instanceof OtpAuthenticationToken) { + return otpAuthenticationProvider.authenticate((OtpAuthenticationToken) authentication); + } + else if(authentication instanceof EServiceAuthenticationToken) { + return eServiceAuthenticationProvider.authenticate((EServiceAuthenticationToken) authentication); + } + return null; + } + + @Override + public boolean supports(Class<?> authentication) { + return AbstractAuthenticationToken.class.isAssignableFrom(authentication); + } +} diff --git a/pamapi/src/main/java/com/pollex/pam/security/provider/EServiceAuthenticationProvider.java b/pamapi/src/main/java/com/pollex/pam/security/provider/EServiceAuthenticationProvider.java new file mode 100644 index 0000000..28a2a19 --- /dev/null +++ b/pamapi/src/main/java/com/pollex/pam/security/provider/EServiceAuthenticationProvider.java @@ -0,0 +1,123 @@ +package com.pollex.pam.security.provider; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.pollex.pam.config.ApplicationProperties; +import com.pollex.pam.domain.Consultant; +import com.pollex.pam.enums.ConsultantDetailEnum; +import com.pollex.pam.enums.CustomerDetailEnum; +import com.pollex.pam.repository.ConsultantRepository; +import com.pollex.pam.security.token.EServiceAuthenticationToken; +import com.pollex.pam.service.dto.EServiceRequest; +import com.pollex.pam.service.dto.EServiceResponse; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.ssl.SSLContexts; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.*; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import javax.net.ssl.SSLContext; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class EServiceAuthenticationProvider { + + private static final String E_SERVICE_LOGIN_SUCCESS_CODE = "0"; + + @Autowired + ApplicationProperties applicationProperty; + + @Autowired + ConsultantRepository consultantRepository; + + public Authentication authenticate(EServiceAuthenticationToken authenticationToken) throws AuthenticationException { + String account = authenticationToken.getPrincipal(); + String credentials = authenticationToken.getCredentials(); + + if(applicationProperty.isMockLogin()){ + return getConsultantToken(account, credentials); + } + + try { + ResponseEntity<EServiceResponse> responseEntity = loginByEService(account, credentials); + if(HttpStatus.OK.equals(responseEntity.getStatusCode())) { + EServiceResponse eServiceResponse = responseEntity.getBody(); + + if(E_SERVICE_LOGIN_SUCCESS_CODE.equals(eServiceResponse.getCode())){ + return getConsultantToken(account, credentials); + } + } + + throw new AuthenticationCredentialsNotFoundException(""); + } catch (Exception e) { + throw new AuthenticationCredentialsNotFoundException(""); + } + } + + private UsernamePasswordAuthenticationToken getConsultantToken(String account, String credential) { + Consultant consultant = consultantRepository.findOneByAgentNo(account).orElseThrow(() -> new UsernameNotFoundException("consultant is not in db, consultant agentNo = " + account)); + + List<GrantedAuthority> grantedAuths = Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")); + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(account, credential, grantedAuths); + + Map<String, String> details = new HashMap<>(); + details.put(ConsultantDetailEnum.ID.getValue(), consultant.getId().toString()); + details.put(ConsultantDetailEnum.NAME.getValue(), consultant.getName()); + details.put(ConsultantDetailEnum.AGENT_NO.getValue(), account); + authenticationToken.setDetails(details); + + return authenticationToken; + } + + private ResponseEntity<EServiceResponse> loginByEService(String account, String paxxword) throws Exception{ + EServiceRequest dto = new EServiceRequest(); + dto.setFunc("ValidateUserLogin"); + dto.setId(account); + dto.setPin(paxxword); + dto.setPwd(paxxword); + dto.setSys("epos"); + + String dtoJson = new ObjectMapper().writeValueAsString(dto); + + RestTemplate restTemplate = getTrustAllRestTemplate(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity<String> entity = new HttpEntity<>(dtoJson, headers); + return restTemplate.exchange(applicationProperty.geteServiceLoginUrl(), HttpMethod.POST, entity, EServiceResponse.class); + } + + private RestTemplate getTrustAllRestTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { + SSLContext sslContext = SSLContexts.custom() + .loadTrustMaterial(null, (X509Certificate[] x509Certs, String s) -> true) + .build(); + SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier()); + CloseableHttpClient httpClient = HttpClients.custom() + .setSSLSocketFactory(csf) + .build(); + HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); + requestFactory.setHttpClient(httpClient); + requestFactory.setConnectTimeout(300000); + requestFactory.setReadTimeout(300000); + return new RestTemplate(requestFactory); + } +} diff --git a/pamapi/src/main/java/com/pollex/pam/security/provider/OtpAuthenticationProvider.java b/pamapi/src/main/java/com/pollex/pam/security/provider/OtpAuthenticationProvider.java new file mode 100644 index 0000000..6fadbba --- /dev/null +++ b/pamapi/src/main/java/com/pollex/pam/security/provider/OtpAuthenticationProvider.java @@ -0,0 +1,80 @@ +package com.pollex.pam.security.provider; + +import com.pollex.pam.config.ApplicationProperties; +import com.pollex.pam.domain.Customer; +import com.pollex.pam.enums.CustomerDetailEnum; +import com.pollex.pam.repository.CustomerRepository; +import com.pollex.pam.security.token.OtpAuthenticationToken; +import com.pollex.pam.service.OtpWebService; +import com.pollex.pam.service.dto.OtpResponseDTO; +import com.pollex.pam.web.rest.vm.OtpAccount; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class OtpAuthenticationProvider { + + private static final Logger log = LoggerFactory.getLogger(OtpAuthenticationProvider.class); + + @Autowired + ApplicationProperties applicationProperty; + + @Autowired + OtpWebService otpWebService; + + @Autowired + CustomerRepository customerRepository; + + public Authentication authenticate(OtpAuthenticationToken otpAuthenticationToken) throws AuthenticationException { + OtpAccount otpAccount = otpAuthenticationToken.getPrincipal(); + String account = otpAccount.getAccount(); + String indexKey = otpAccount.getIndexKey(); + String otpCode = otpAuthenticationToken.getCredentials(); + + if(applicationProperty.isMockLogin()){ + return getCustomerToken(account, otpCode); + } + + try { + OtpResponseDTO otpResponseDTO = otpWebService.verifyOTP(indexKey, otpCode); + if(otpResponseDTO.isSuccess()) { + return getCustomerToken(account, otpCode); + } + } catch (Exception e) { + log.error("Exception: ", e); + throw new AuthenticationCredentialsNotFoundException(""); + } + + throw new AuthenticationCredentialsNotFoundException(""); + } + + private UsernamePasswordAuthenticationToken getCustomerToken(String account, String otpCode) { + // todo �摮�DB��撅祆迤撣貊鞊∴����畾essage����垢��脰�酉��� + Customer customer = customerRepository.findOneByEmailEqualsOrPhoneEquals(account, account).orElseThrow(() -> new UsernameNotFoundException("this customer is not in db, account = " + account)); + + List<GrantedAuthority> grantedAuths = Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")); + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(account, otpCode, grantedAuths); + + Map<String, String> details = new HashMap<>(); + details.put(CustomerDetailEnum.ID.getValue(), customer.getId().toString()); + details.put(CustomerDetailEnum.NAME.getValue(), customer.getName()); + details.put(CustomerDetailEnum.ACCOUNT.getValue(), account); + authenticationToken.setDetails(details); + + return authenticationToken; + } +} diff --git a/pamapi/src/main/java/com/pollex/pam/security/token/EServiceAuthenticationToken.java b/pamapi/src/main/java/com/pollex/pam/security/token/EServiceAuthenticationToken.java new file mode 100644 index 0000000..6bc8410 --- /dev/null +++ b/pamapi/src/main/java/com/pollex/pam/security/token/EServiceAuthenticationToken.java @@ -0,0 +1,53 @@ +package com.pollex.pam.security.token; + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.SpringSecurityCoreVersion; +import org.springframework.util.Assert; + +import java.util.Collection; + +public class EServiceAuthenticationToken extends AbstractAuthenticationToken { + + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + + private final String principle; + private String credentials; + + public EServiceAuthenticationToken(String principle, String credentials) { + super(null); + this.principle = principle; + this.credentials = credentials; + setAuthenticated(false); + } + + public EServiceAuthenticationToken(String principle, String credentials, Collection<? extends GrantedAuthority> authorities) { + super(authorities); + this.principle = principle; + this.credentials = credentials; + setAuthenticated(true); + } + + @Override + public String getCredentials() { + return credentials; + } + + @Override + public String getPrincipal() { + return principle; + } + + @Override + public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { + Assert.isTrue(!isAuthenticated, + "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); + super.setAuthenticated(false); + } + + @Override + public void eraseCredentials() { + super.eraseCredentials(); + this.credentials = null; + } +} diff --git a/pamapi/src/main/java/com/pollex/pam/security/token/OtpAuthenticationToken.java b/pamapi/src/main/java/com/pollex/pam/security/token/OtpAuthenticationToken.java new file mode 100644 index 0000000..9652e9c --- /dev/null +++ b/pamapi/src/main/java/com/pollex/pam/security/token/OtpAuthenticationToken.java @@ -0,0 +1,47 @@ +package com.pollex.pam.security.token; + +import com.pollex.pam.web.rest.vm.OtpAccount; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.SpringSecurityCoreVersion; +import org.springframework.util.Assert; + +import java.util.Collection; + +public class OtpAuthenticationToken extends AbstractAuthenticationToken { + + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + + private final OtpAccount principle; + private String credentials; + + public OtpAuthenticationToken(OtpAccount principle, String credentials) { + super(null); + this.principle = principle; + this.credentials = credentials; + setAuthenticated(false); + } + + @Override + public String getCredentials() { + return this.credentials; + } + + @Override + public OtpAccount getPrincipal() { + return this.principle; + } + + @Override + public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { + Assert.isTrue(!isAuthenticated, + "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); + super.setAuthenticated(false); + } + + @Override + public void eraseCredentials() { + super.eraseCredentials(); + this.credentials = null; + } +} diff --git a/pamapi/src/main/java/com/pollex/pam/service/ConsultantService.java b/pamapi/src/main/java/com/pollex/pam/service/ConsultantService.java index 3dbcbd9..af9c247 100644 --- a/pamapi/src/main/java/com/pollex/pam/service/ConsultantService.java +++ b/pamapi/src/main/java/com/pollex/pam/service/ConsultantService.java @@ -73,7 +73,7 @@ } public ConsultantDetailDTO getConsultantDetail(String agentNo) { - Consultant consultant = consultantRepository.findFirstByAgentNo(agentNo).orElseThrow(ConsultantNotFoundException::new); + Consultant consultant = consultantRepository.findOneByAgentNo(agentNo).orElseThrow(ConsultantNotFoundException::new); return consultantMapper.toDetailDto(consultant); } @@ -108,7 +108,7 @@ public void removeConsultantFromCustomList(String agentNo) { Long customId = SecurityUtils.getCustomerId(); - Consultant consultant = consultantRepository.findFirstByAgentNo(agentNo).orElseThrow(ConsultantNotFoundException::new); + Consultant consultant = consultantRepository.findOneByAgentNo(agentNo).orElseThrow(ConsultantNotFoundException::new); CustomerFavoriteConsultant target = customerFavoriteConsultantRepository.findOneByCustomerIdAndConsultant(customId, consultant).orElse(null); if(target != null) { diff --git a/pamapi/src/main/java/com/pollex/pam/service/LoginService.java b/pamapi/src/main/java/com/pollex/pam/service/LoginService.java index 3c50045..0cd4b29 100644 --- a/pamapi/src/main/java/com/pollex/pam/service/LoginService.java +++ b/pamapi/src/main/java/com/pollex/pam/service/LoginService.java @@ -25,7 +25,6 @@ import com.pollex.pam.config.ApplicationProperties; import com.pollex.pam.service.dto.EServiceRequest; import com.pollex.pam.service.dto.EServiceResponse; -import com.pollex.pam.web.rest.vm.EServiceRequestVM; import com.pollex.pam.web.rest.vm.OtpEmailLoginVM; import com.pollex.pam.web.rest.vm.OtpSMSLoginVM; import com.pollex.pam.web.rest.vm.VerifyOtpVM; diff --git a/pamapi/src/main/java/com/pollex/pam/service/OtpWebService.java b/pamapi/src/main/java/com/pollex/pam/service/OtpWebService.java new file mode 100644 index 0000000..35c9a63 --- /dev/null +++ b/pamapi/src/main/java/com/pollex/pam/service/OtpWebService.java @@ -0,0 +1,63 @@ +package com.pollex.pam.service; + +import com.pollex.pam.config.ApplicationProperties; +import com.pollex.pam.service.dto.OtpResponseDTO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import tw.com.softleader.otp.ws.OtpWebServiceLocator; +import tw.com.softleader.otp.ws.OtpWebServicePortBindingStub; + +import javax.xml.rpc.ServiceException; +import java.rmi.RemoteException; + +@Service +public class OtpWebService { + + private static final Logger log = LoggerFactory.getLogger(OtpWebService.class); + + @Autowired + ApplicationProperties applicationProperty; + + public OtpResponseDTO sendByPhone(String phone) throws ServiceException, RemoteException { + OtpWebServicePortBindingStub stub = getOtpWebServicePortBindingStub(); + log.info("call OtpService snedOtpBySMS, "); + + String[] result = + stub.sendOtpBySMS(applicationProperty.getOtpWebServicePassword(), applicationProperty.getOtpWebServiceSystemType(), phone); + + return new OtpResponseDTO(result); + } + + public OtpResponseDTO sendByEmail(String email) throws ServiceException, RemoteException { + OtpWebServicePortBindingStub stub = getOtpWebServicePortBindingStub(); + + String[] result = + stub.sendOtpByEmail(applicationProperty.getOtpWebServicePassword(), applicationProperty.getOtpWebServiceSystemType(), email); + + final OtpResponseDTO otpResponseDTO = new OtpResponseDTO(result); + if(otpResponseDTO.isSuccess()) { + return otpResponseDTO; + } + else { + throw new RuntimeException("error code = " + otpResponseDTO.getFailCode() + ", error reason = " + otpResponseDTO.getFailReason()); + } + } + + public OtpResponseDTO verifyOTP(String indexKey, String otpCode) throws ServiceException, RemoteException { + OtpWebServicePortBindingStub stub = getOtpWebServicePortBindingStub(); + + String[] result = + stub.verifyOtp(applicationProperty.getOtpWebServicePassword(), applicationProperty.getOtpWebServiceSystemType(), indexKey, otpCode); + + return new OtpResponseDTO(result); + } + + private OtpWebServicePortBindingStub getOtpWebServicePortBindingStub() throws ServiceException { + OtpWebServiceLocator locator = new OtpWebServiceLocator(); + locator.setOtpWebServicePortEndpointAddress(applicationProperty.getOtpWebServiceUrl()); + + return (OtpWebServicePortBindingStub) locator.getOtpWebServicePort(); + } +} diff --git a/pamapi/src/main/java/com/pollex/pam/web/rest/EServiceResource.java b/pamapi/src/main/java/com/pollex/pam/web/rest/EServiceResource.java new file mode 100644 index 0000000..1ee9eed --- /dev/null +++ b/pamapi/src/main/java/com/pollex/pam/web/rest/EServiceResource.java @@ -0,0 +1,46 @@ +package com.pollex.pam.web.rest; + +import com.pollex.pam.security.jwt.JWTFilter; +import com.pollex.pam.security.jwt.TokenProvider; +import com.pollex.pam.security.token.EServiceAuthenticationToken; +import com.pollex.pam.web.rest.vm.EServiceLoginVM; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/eService") +public class EServiceResource { + + @Autowired + AuthenticationManagerBuilder authenticationManagerBuilder; + + @Autowired + TokenProvider tokenProvider; + + @PostMapping("/authenticate") + public ResponseEntity<UserJWTController.JWTToken> authorize(@RequestBody EServiceLoginVM eServiceLoginVM) { + // todo 撽�Ⅳ隤�� + + + EServiceAuthenticationToken authenticationToken = new EServiceAuthenticationToken( + eServiceLoginVM.getUsername(), + eServiceLoginVM.getPassword() + ); + + Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + String jwt = tokenProvider.createToken(authentication, false); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer" + jwt); + return new ResponseEntity<>(new UserJWTController.JWTToken(jwt), httpHeaders, HttpStatus.OK); + } +} diff --git a/pamapi/src/main/java/com/pollex/pam/web/rest/LoginResource.java b/pamapi/src/main/java/com/pollex/pam/web/rest/LoginResource.java deleted file mode 100644 index 3734775..0000000 --- a/pamapi/src/main/java/com/pollex/pam/web/rest/LoginResource.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.pollex.pam.web.rest; - -import com.pollex.pam.config.ApplicationProperties; -import com.pollex.pam.service.LoginService; -import com.pollex.pam.service.dto.OtpResponseDTO; -import com.pollex.pam.web.rest.vm.EServiceRequestVM; -import com.pollex.pam.service.dto.EServiceResponse; -import com.pollex.pam.web.rest.vm.OtpEmailLoginVM; -import com.pollex.pam.web.rest.vm.OtpSMSLoginVM; -import com.pollex.pam.web.rest.vm.VerifyOtpVM; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import tw.com.softleader.otp.ws.OtpWebServiceLocator; -import tw.com.softleader.otp.ws.OtpWebServicePortBindingStub; - -import javax.xml.rpc.ServiceException; -import java.rmi.RemoteException; - -@RestController -@RequestMapping("/api/testLogin") -public class LoginResource { - - private final static Logger log = LoggerFactory.getLogger(LoginResource.class); - - private final LoginService loginService; - private final ApplicationProperties applicationProperty; - - public LoginResource(LoginService loginService, ApplicationProperties applicationProperty) { - this.loginService = loginService; - this.applicationProperty = applicationProperty; - } - - @GetMapping("/bySMS") - public ResponseEntity<OtpResponseDTO> sendOtpBySMS(@RequestParam("phone") String phone) throws ServiceException, RemoteException { - OtpWebServiceLocator locator = new OtpWebServiceLocator(); - locator.setOtpWebServicePortEndpointAddress(applicationProperty.getOtpWebServiceUrl()); - - OtpWebServicePortBindingStub otpWebServicePort = (OtpWebServicePortBindingStub) locator.getOtpWebServicePort(); - String[] result = - otpWebServicePort.sendOtpBySMS(applicationProperty.getOtpWebServicePassword(), applicationProperty.getOtpWebServiceSystemType(), phone); - - return new ResponseEntity<>(new OtpResponseDTO(result), HttpStatus.OK); - } - - @GetMapping("/byEmail") - public ResponseEntity<OtpResponseDTO> sendOtpByEmail(@RequestParam("email") String email) throws RemoteException, ServiceException { - OtpWebServiceLocator locator = new OtpWebServiceLocator(); - locator.setOtpWebServicePortEndpointAddress(applicationProperty.getOtpWebServiceUrl()); - - OtpWebServicePortBindingStub otpWebServicePort = (OtpWebServicePortBindingStub) locator.getOtpWebServicePort(); - String[] result = - otpWebServicePort.sendOtpByEmail(applicationProperty.getOtpWebServicePassword(), applicationProperty.getOtpWebServiceSystemType(), email); - - return new ResponseEntity<>(new OtpResponseDTO(result), HttpStatus.OK); - } - - // todo: �ㄐ蝘餃�隤����rovider - @PostMapping("/verifyOtp") - public void verifyOtp(@RequestBody VerifyOtpVM verifyOtpParam) { - OtpWebServiceLocator locator = new OtpWebServiceLocator(); - } - - // todo: �ㄐ蝘餃�隤����rovider - @GetMapping("/byEService") - public ResponseEntity<EServiceResponse> loginByEService(@RequestParam("account") String account, @RequestParam("password") String password) throws Exception { - return loginService.loginByEService(account, password); - } -} diff --git a/pamapi/src/main/java/com/pollex/pam/web/rest/OtpResource.java b/pamapi/src/main/java/com/pollex/pam/web/rest/OtpResource.java new file mode 100644 index 0000000..bb55739 --- /dev/null +++ b/pamapi/src/main/java/com/pollex/pam/web/rest/OtpResource.java @@ -0,0 +1,100 @@ +package com.pollex.pam.web.rest; + +import com.pollex.pam.config.ApplicationProperties; +import com.pollex.pam.security.jwt.JWTFilter; +import com.pollex.pam.security.jwt.TokenProvider; +import com.pollex.pam.security.token.OtpAuthenticationToken; +import com.pollex.pam.service.OtpWebService; +import com.pollex.pam.service.dto.OtpResponseDTO; +import com.pollex.pam.web.rest.vm.OtpAccount; +import com.pollex.pam.web.rest.vm.OtpEmailLoginVM; +import com.pollex.pam.web.rest.vm.OtpSMSLoginVM; +import com.pollex.pam.web.rest.vm.VerifyOtpVM; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.bind.annotation.*; + +import javax.xml.rpc.ServiceException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.rmi.RemoteException; +import java.util.Arrays; +import java.util.Random; +import java.util.UUID; + +import static java.nio.charset.StandardCharsets.UTF_8; + +@RestController +@RequestMapping("/api/otp") +public class OtpResource { + + private final static Logger log = LoggerFactory.getLogger(OtpResource.class); + + @Autowired + ApplicationProperties applicationProperty; + + @Autowired + OtpWebService otpWebService; + + @Autowired + AuthenticationManagerBuilder authenticationManagerBuilder; + + @Autowired + TokenProvider tokenProvider; + + @PostMapping("/byPhone") + public ResponseEntity<Object> sendOtpByPhone(@RequestBody OtpSMSLoginVM login) { + try { + if(applicationProperty.isMockLogin()) { + return new ResponseEntity<>(getMockOtpResponse(), HttpStatus.OK); + } + + OtpResponseDTO otpResponseDTO = otpWebService.sendByPhone(login.getPhone()); + return new ResponseEntity<>(otpResponseDTO, HttpStatus.OK); + } catch (ServiceException | RemoteException e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("connecting otp web service error"); + } + } + + @PostMapping("/byEmail") + public ResponseEntity<Object> sendOtpByEmail(@RequestBody OtpEmailLoginVM login) { + try { + if(applicationProperty.isMockLogin()) { + return new ResponseEntity<>(getMockOtpResponse(), HttpStatus.OK); + } + + OtpResponseDTO otpResponseDTO = otpWebService.sendByEmail(login.getEmail()); + return new ResponseEntity<>(otpResponseDTO, HttpStatus.OK); + } catch (ServiceException | RemoteException e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("connecting otp web service error"); + } + } + + @PostMapping("/verify") + public ResponseEntity<UserJWTController.JWTToken> verifyOtp(@RequestBody VerifyOtpVM verifyOtpParam) { + OtpAccount otpAccount = new OtpAccount(verifyOtpParam.getAccount(), verifyOtpParam.getIndexKey()); + OtpAuthenticationToken authenticationToken = new OtpAuthenticationToken( + otpAccount, + verifyOtpParam.getOtpCode() + ); + + Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + String jwt = tokenProvider.createToken(authentication, false); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer" + jwt); + return new ResponseEntity<>(new UserJWTController.JWTToken(jwt), httpHeaders, HttpStatus.OK); + } + + private OtpResponseDTO getMockOtpResponse() { + String indexKey = UUID.randomUUID().toString().substring(0, 8); + return new OtpResponseDTO(new String[]{indexKey, "0", "", ""}); + } +} diff --git a/pamapi/src/main/java/com/pollex/pam/web/rest/TestLoginResource.java b/pamapi/src/main/java/com/pollex/pam/web/rest/TestLoginResource.java new file mode 100644 index 0000000..07691a3 --- /dev/null +++ b/pamapi/src/main/java/com/pollex/pam/web/rest/TestLoginResource.java @@ -0,0 +1,89 @@ +package com.pollex.pam.web.rest; + +import com.pollex.pam.config.ApplicationProperties; +import com.pollex.pam.security.jwt.JWTFilter; +import com.pollex.pam.security.jwt.TokenProvider; +import com.pollex.pam.security.token.EServiceAuthenticationToken; +import com.pollex.pam.security.token.OtpAuthenticationToken; +import com.pollex.pam.service.LoginService; +import com.pollex.pam.service.OtpWebService; +import com.pollex.pam.service.dto.OtpResponseDTO; +import com.pollex.pam.web.rest.vm.OtpAccount; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.bind.annotation.*; + +import javax.xml.rpc.ServiceException; +import java.rmi.RemoteException; + +@RestController +@RequestMapping("/api/testLogin") +public class TestLoginResource { + + private final static Logger log = LoggerFactory.getLogger(TestLoginResource.class); + + @Autowired + LoginService loginService; + + @Autowired + ApplicationProperties applicationProperty; + + @Autowired + OtpWebService otpWebService; + + @Autowired + AuthenticationManagerBuilder authenticationManagerBuilder; + + @Autowired + TokenProvider tokenProvider; + + @GetMapping("/bySMS") + public ResponseEntity<OtpResponseDTO> sendOtpBySMS(@RequestParam("phone") String phone) throws ServiceException, RemoteException { + otpWebService.sendByPhone(phone); + return new ResponseEntity<>(HttpStatus.OK); + } + + @GetMapping("/byEmail") + public ResponseEntity<OtpResponseDTO> sendOtpByEmail(@RequestParam("email") String email) throws RemoteException, ServiceException { + otpWebService.sendByEmail(email); + return new ResponseEntity<>(HttpStatus.OK); + } + + @GetMapping("/verifyOtp") + public ResponseEntity<UserJWTController.JWTToken> verifyOtp(@RequestParam("account") String account, @RequestParam("indexKey") String indexKey, @RequestParam("otpCode") String otpCode) throws ServiceException, RemoteException { + OtpAccount otpAccount = new OtpAccount(account, indexKey); + OtpAuthenticationToken authenticationToken = new OtpAuthenticationToken( + otpAccount, + otpCode + ); + + Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + String jwt = tokenProvider.createToken(authentication, false); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer" + jwt); + return new ResponseEntity<>(new UserJWTController.JWTToken(jwt), httpHeaders, HttpStatus.OK); + } + + @GetMapping("/byEService") + public ResponseEntity<UserJWTController.JWTToken> loginByEService(@RequestParam("account") String account, @RequestParam("password") String password) throws Exception { + EServiceAuthenticationToken authenticationToken = new EServiceAuthenticationToken( + account, + password + ); + + Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + String jwt = tokenProvider.createToken(authentication, false); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer" + jwt); + return new ResponseEntity<>(new UserJWTController.JWTToken(jwt), httpHeaders, HttpStatus.OK); + } +} diff --git a/pamapi/src/main/java/com/pollex/pam/web/rest/vm/EServiceRequestVM.java b/pamapi/src/main/java/com/pollex/pam/web/rest/vm/EServiceLoginVM.java similarity index 92% rename from pamapi/src/main/java/com/pollex/pam/web/rest/vm/EServiceRequestVM.java rename to pamapi/src/main/java/com/pollex/pam/web/rest/vm/EServiceLoginVM.java index 91e3b50..2cebe8e 100644 --- a/pamapi/src/main/java/com/pollex/pam/web/rest/vm/EServiceRequestVM.java +++ b/pamapi/src/main/java/com/pollex/pam/web/rest/vm/EServiceLoginVM.java @@ -1,6 +1,6 @@ package com.pollex.pam.web.rest.vm; -public class EServiceRequestVM { +public class EServiceLoginVM { private String username; private String password; diff --git a/pamapi/src/main/java/com/pollex/pam/web/rest/vm/OtpAccount.java b/pamapi/src/main/java/com/pollex/pam/web/rest/vm/OtpAccount.java new file mode 100644 index 0000000..4ee1a74 --- /dev/null +++ b/pamapi/src/main/java/com/pollex/pam/web/rest/vm/OtpAccount.java @@ -0,0 +1,27 @@ +package com.pollex.pam.web.rest.vm; + +public class OtpAccount { + private String account; + private String indexKey; + + public OtpAccount(String account, String indexKey) { + this.account = account; + this.indexKey = indexKey; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getIndexKey() { + return indexKey; + } + + public void setIndexKey(String indexKey) { + this.indexKey = indexKey; + } +} diff --git a/pamapi/src/main/java/com/pollex/pam/web/rest/vm/VerifyOtpVM.java b/pamapi/src/main/java/com/pollex/pam/web/rest/vm/VerifyOtpVM.java index 0f40cd6..8465eee 100644 --- a/pamapi/src/main/java/com/pollex/pam/web/rest/vm/VerifyOtpVM.java +++ b/pamapi/src/main/java/com/pollex/pam/web/rest/vm/VerifyOtpVM.java @@ -1,15 +1,24 @@ package com.pollex.pam.web.rest.vm; public class VerifyOtpVM { - private String identityCode; + private String account; + private String indexKey; private String otpCode; - public String getIdentityCode() { - return identityCode; + public String getAccount() { + return account; } - public void setIdentityCode(String identityCode) { - this.identityCode = identityCode; + public void setAccount(String account) { + this.account = account; + } + + public String getIndexKey() { + return indexKey; + } + + public void setIndexKey(String indexKey) { + this.indexKey = indexKey; } public String getOtpCode() { diff --git a/pamapi/src/main/resources/config/application-dev.yml b/pamapi/src/main/resources/config/application-dev.yml index 890f872..450ab2a 100644 --- a/pamapi/src/main/resources/config/application-dev.yml +++ b/pamapi/src/main/resources/config/application-dev.yml @@ -111,6 +111,7 @@ # =================================================================== application: + mock-login: true otp-web-service-url: https://vtwlifeopensyssit.pru.intranet.asia:443/pcalife-otp/ws/otpWebService otp-web-service-password: es20!%Pass otp-web-service-system-type: epos diff --git a/pamapi/src/main/resources/config/application-sit.yml b/pamapi/src/main/resources/config/application-sit.yml index bd1e2ab..93ca69e 100644 --- a/pamapi/src/main/resources/config/application-sit.yml +++ b/pamapi/src/main/resources/config/application-sit.yml @@ -111,6 +111,7 @@ # =================================================================== application: + mock-login: false otp-web-service-url: https://vtwlifeopensyssit.pru.intranet.asia:443/pcalife-otp/ws/otpWebService otp-web-service-password: es20!%Pass otp-web-service-system-type: epos diff --git a/pamapi/src/main/resources/config/application-uat.yml b/pamapi/src/main/resources/config/application-uat.yml new file mode 100644 index 0000000..e5ddb97 --- /dev/null +++ b/pamapi/src/main/resources/config/application-uat.yml @@ -0,0 +1,118 @@ +# =================================================================== +# Spring Boot configuration for the "sit" profile. +# +# This configuration overrides the application.yml file. +# +# More information on profiles: https://www.jhipster.tech/profiles/ +# More information on configuration properties: https://www.jhipster.tech/common-application-properties/ +# =================================================================== + +# =================================================================== +# Standard Spring Boot properties. +# Full reference is available at: +# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html +# =================================================================== + +logging: + level: + ROOT: DEBUG + tech.jhipster: DEBUG + org.hibernate.SQL: DEBUG + com.pollex.pam: DEBUG + +spring: + devtools: + restart: + enabled: true + additional-exclude: static/** + livereload: + enabled: false # we use Webpack dev server + BrowserSync for livereload + jackson: + serialization: + indent-output: true + datasource: + type: com.zaxxer.hikari.HikariDataSource + url: jdbc:postgresql://VTWLIFELDPOS01:5006/omo?currentSchema=omo + username: omo_svc + password: omo_svc-100784c + hikari: + poolName: Hikari + auto-commit: false + jpa: + database-platform: tech.jhipster.domain.util.FixedPostgreSQL10Dialect + liquibase: + # Remove 'faker' if you do not want the sample data to be loaded automatically + contexts: uat, faker + mail: + host: localhost + port: 25 + username: + password: + messages: + cache-duration: PT1S # 1 second, see the ISO 8601 standard + thymeleaf: + cache: false + sleuth: + sampler: + probability: 1 # report 100% of traces + zipkin: # Use the "zipkin" Maven profile to have the Spring Cloud Zipkin dependencies + base-url: http://localhost:9411 + enabled: false + locator: + discovery: + enabled: true + +server: + port: 8080 + +# =================================================================== +# JHipster specific properties +# +# Full reference is available at: https://www.jhipster.tech/common-application-properties/ +# =================================================================== + +jhipster: + cache: # Cache configuration + ehcache: # Ehcache configuration + time-to-live-seconds: 3600 # By default objects stay 1 hour in the cache + max-entries: 100 # Number of objects in each cache entry + # cors: + # # Allow Ionic for JHipster by default (* no longer allowed in Spring Boot 2.4+) + # allowed-origins: 'http://localhost:8100,https://localhost:8100,http://localhost:9000,https://localhost:9000' + # allowed-methods: '*' + # allowed-headers: '*' + # exposed-headers: 'Authorization,Link,X-Total-Count,X-${jhipster.clientApp.name}-alert,X-${jhipster.clientApp.name}-error,X-${jhipster.clientApp.name}-params' + # allow-credentials: true + # max-age: 1800 + security: + authentication: + jwt: + # This token must be encoded using Base64 and be at least 256 bits long (you can type `openssl rand -base64 64` on your command line to generate a 512 bits one) + base64-secret: MjI3YWRiMzg1ZTY3ZmZkZDgxZmI5Yjc5YjVkOTIzMzc4MmI2OWM3NWVkZjFiOTNmNjg0YWFjZWQ4YzhlOTUzYzk3MGUzMzM5Y2U5MDdkZTMyN2Q0N2E0M2ZmM2FhYzkyNDY4MjBkYTY5OGM4YmIzMmYxODJhNWFkMmVhNmVhNTM= + # Token is valid 24 hours + token-validity-in-seconds: 86400 + token-validity-in-seconds-for-remember-me: 2592000 + mail: # specific JHipster mail property, for standard properties see MailProperties + base-url: http://127.0.0.1:8080 + logging: + use-json-format: false # By default, logs are not in Json format + logstash: # Forward logs to logstash over a socket, used by LoggingConfiguration + enabled: false + host: localhost + port: 5000 + queue-size: 512 +# =================================================================== +# Application specific properties +# Add your own application properties here, see the ApplicationProperties class +# to have type-safe configuration, like in the JHipsterProperties above +# +# More documentation is available at: +# https://www.jhipster.tech/common-application-properties/ +# =================================================================== + +application: + mock-login: false + otp-web-service-url: https://vtwlifeopensyssit.pru.intranet.asia:443/pcalife-otp/ws/otpWebService + otp-web-service-password: es20!%Pass + otp-web-service-system-type: epos + e-service-login-url: https://ssotwsit.eservice.pcalife.com.tw/sso/acctValidate -- Gitblit v1.8.0