保誠-保戶業務員媒合平台
wayne
2021-11-22 7dfed155bc4f5a1c7cf5a592e8325dc1ba9243bc
[update] otp登入、認證、顧問EService登入

刪除1個檔案
修改12個檔案
新增17個檔案
修改1個檔案名稱
1065 ■■■■■ 已變更過的檔案
pamapi/pom.xml 39 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/doc/登入API/客戶發EmailOTP.txt 15 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/doc/登入API/客戶發手機OTP.txt 15 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/doc/登入API/客戶認證OTP並登入.txt 17 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/doc/登入API/顧問登入ByEService.txt 18 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/config/ApplicationProperties.java 9 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/config/SecurityConfiguration.java 2 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/enums/ConsultantDetailEnum.java 17 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/enums/CustomerDetailEnum.java 17 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/repository/ConsultantRepository.java 3 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/repository/CustomerRepository.java 5 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/security/SecurityUtils.java 16 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/security/jwt/TokenProvider.java 6 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/security/provider/CustomAuthenticationProvider.java 41 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/security/provider/EServiceAuthenticationProvider.java 123 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/security/provider/OtpAuthenticationProvider.java 80 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/security/token/EServiceAuthenticationToken.java 53 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/security/token/OtpAuthenticationToken.java 47 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/service/ConsultantService.java 4 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/service/LoginService.java 1 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/service/OtpWebService.java 63 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/web/rest/EServiceResource.java 46 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/web/rest/LoginResource.java 71 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/web/rest/OtpResource.java 100 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/web/rest/TestLoginResource.java 89 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/web/rest/vm/EServiceLoginVM.java 2 ●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/web/rest/vm/OtpAccount.java 27 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/web/rest/vm/VerifyOtpVM.java 19 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/resources/config/application-dev.yml 1 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/resources/config/application-sit.yml 1 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/resources/config/application-uat.yml 118 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
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>
pamapi/src/doc/µn¤JAPI/«È¤áµoEmailOTP.txt
¤ñ¹ï·sÀÉ®×
@@ -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": ""
}
pamapi/src/doc/µn¤JAPI/«È¤áµo¤â¾÷OTP.txt
¤ñ¹ï·sÀÉ®×
@@ -0,0 +1,15 @@
http post:
http://localhost:8080/api/otp/byPhone
request body:
{
    "phone":"0912345678"
}
response body:
{
    "indexKey": "5913a8cd",
    "success": true,
    "failCode": "",
    "failReason": ""
}
pamapi/src/doc/µn¤JAPI/«È¤á»{ÃÒOTP¨Ãµn¤J.txt
¤ñ¹ï·sÀÉ®×
@@ -0,0 +1,17 @@
http post:
http://localhost:8080/api/otp/verify
request body:
{
    "account": "wayne@pollex.com.tw",   // å¯å¸¶å…¥æ‰‹æ©Ÿæˆ–email,這裡已email為範例
    "indexKey": "123",  // ç”±otp的api回的index key
    "otpCode": "123" // ç”±æ‰‹æ©Ÿæˆ–信箱收到的認證碼
}
目前dev中客戶帳號可用自己Teams的email信箱做登入 (各個前後端工程師及QA帳號已經開好)。
而indexKey及otpCode在dev是不會做任何驗證,可以直接登入
response body:
{
    "id_token": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ3YXluZUBwb2xsZXguY29tLnR3IiwiYXV0aCI6IlJPTEVfVVNFUiIsImRldGFpbHMiOnsiQ3VzdG9tZXJBY2NvdW50Ijoid2F5bmVAcG9sbGV4LmNvbS50dyIsIkN1c3RvbWVySWQiOiI2IiwiQ3VzdG9tZXJOYW1lIjoiV2F5bmUifSwiZXhwIjoxNjM3NjQ5NzUzfQ.6xqkWG7kQPUHOys8vPdx6ebgH1wgZ4gysFEa1t1jCnKB44VsFZ8PjtUlN2mvroBdGtPwpOynoTHU7HvAQ3_mnQ"
}
pamapi/src/doc/µn¤JAPI/ÅU°Ýµn¤JByEService.txt
¤ñ¹ï·sÀÉ®×
@@ -0,0 +1,18 @@
http post:
http://localhost:8080/api/eService/authenticate
request body:
{
    "username": "D265260662",
    "password": "test123"
}
目前可用顧問可參考Angela的10個顧問測試資料
檔名:PCA-Matching Platform-test-data 1108.xlsx
帳號如Excel上面所填寫,密碼在dev端並未從EService檢核,可以直接登入
response body:
{
    "id_token": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJEMjY1MjYwNjYyIiwiYXV0aCI6IlJPTEVfVVNFUiIsImRldGFpbHMiOnsiQ29uc3VsdGFudEFnZW50Tm8iOiJEMjY1MjYwNjYyIiwiQ29uc3VsdGFudE5hbWUiOiLmnpfmiJDlrIwiLCJDb25zdWx0YW50SWQiOiI1In0sImV4cCI6MTYzNzY0OTQ5NX0.BjLiA-nuJOsUtD6UqyONr3brPXbdhjA_5srFBS2qgcvFhfznSOCZMlHtl4NtphiZ1CAk2jyg79QFlqGvM6Uk1A"
}
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;
    }
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()
pamapi/src/main/java/com/pollex/pam/enums/ConsultantDetailEnum.java
¤ñ¹ï·sÀÉ®×
@@ -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;
    }
}
pamapi/src/main/java/com/pollex/pam/enums/CustomerDetailEnum.java
¤ñ¹ï·sÀÉ®×
@@ -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;
    }
}
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);
}
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);
}
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 ||
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) {
pamapi/src/main/java/com/pollex/pam/security/provider/CustomAuthenticationProvider.java
¤ñ¹ï·sÀÉ®×
@@ -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);
    }
}
pamapi/src/main/java/com/pollex/pam/security/provider/EServiceAuthenticationProvider.java
¤ñ¹ï·sÀÉ®×
@@ -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);
    }
}
pamapi/src/main/java/com/pollex/pam/security/provider/OtpAuthenticationProvider.java
¤ñ¹ï·sÀÉ®×
@@ -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所屬正常現象,需用特殊message告知前端可進行註冊
        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;
    }
}
pamapi/src/main/java/com/pollex/pam/security/token/EServiceAuthenticationToken.java
¤ñ¹ï·sÀÉ®×
@@ -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;
    }
}
pamapi/src/main/java/com/pollex/pam/security/token/OtpAuthenticationToken.java
¤ñ¹ï·sÀÉ®×
@@ -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;
    }
}
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) {
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;
pamapi/src/main/java/com/pollex/pam/service/OtpWebService.java
¤ñ¹ï·sÀÉ®×
@@ -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();
    }
}
pamapi/src/main/java/com/pollex/pam/web/rest/EServiceResource.java
¤ñ¹ï·sÀÉ®×
@@ -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);
    }
}
pamapi/src/main/java/com/pollex/pam/web/rest/LoginResource.java
Àɮפw§R°£
pamapi/src/main/java/com/pollex/pam/web/rest/OtpResource.java
¤ñ¹ï·sÀÉ®×
@@ -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", "", ""});
    }
}
pamapi/src/main/java/com/pollex/pam/web/rest/TestLoginResource.java
¤ñ¹ï·sÀÉ®×
@@ -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);
    }
}
pamapi/src/main/java/com/pollex/pam/web/rest/vm/EServiceLoginVM.java
File was renamed from pamapi/src/main/java/com/pollex/pam/web/rest/vm/EServiceRequestVM.java
@@ -1,6 +1,6 @@
package com.pollex.pam.web.rest.vm;
public class EServiceRequestVM {
public class EServiceLoginVM {
    private String username;
    private String password;
pamapi/src/main/java/com/pollex/pam/web/rest/vm/OtpAccount.java
¤ñ¹ï·sÀÉ®×
@@ -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;
    }
}
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() {
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
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
pamapi/src/main/resources/config/application-uat.yml
¤ñ¹ï·sÀÉ®×
@@ -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