保誠-保戶業務員媒合平台
Tomas
2021-11-23 c2d8465faade429e8b8f677864b0bc2da763e71c
Merge branch 'master' of ssh://192.168.0.10:29418/pcalife/PAM
刪除2個檔案
修改6個檔案
新增3個檔案
277 ■■■■■ 已變更過的檔案
pamapi/src/doc/登入API/客戶發EmailOTP.txt 15 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/doc/登入API/客戶發OTP.txt 16 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/doc/登入API/客戶發手機OTP.txt 15 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/enums/OtpLoginTypeEnum.java 6 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/security/provider/EServiceAuthenticationProvider.java 16 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/service/OtpWebService.java 17 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/web/rest/OtpResource.java 38 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/web/rest/TestLoginResource.java 107 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/web/rest/vm/OtpLoginVM.java 24 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/resources/config/application-sit.yml 2 ●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/resources/logback-spring.xml 21 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/doc/µn¤JAPI/«È¤áµoEmailOTP.txt
Àɮפw§R°£
pamapi/src/doc/µn¤JAPI/«È¤áµoOTP.txt
¤ñ¹ï·sÀÉ®×
@@ -0,0 +1,16 @@
http post:
http://localhost:8080/api/otp/sendOtp
request body:
{
    "loginType":"SMS",          // "SMS":Otp發送手機,"EMAIL":Otp發email
    "account": "0912345678",    // è‹¥loginTypeå¡«SMS則該欄帶入手機、EMAIL則帶入郵件信箱
}
response body:
{
    "indexKey": "7c8c38a2",     // ç”¨æ–¼å¸¶å…¥otp認證時
    "success": true,            // Otp是否有成功發送
    "failCode": "",
    "failReason": ""
}
pamapi/src/doc/µn¤JAPI/«È¤áµo¤â¾÷OTP.txt
Àɮפw§R°£
pamapi/src/main/java/com/pollex/pam/enums/OtpLoginTypeEnum.java
¤ñ¹ï·sÀÉ®×
@@ -0,0 +1,6 @@
package com.pollex.pam.enums;
public enum OtpLoginTypeEnum {
    SMS,
    EMAIL
}
pamapi/src/main/java/com/pollex/pam/security/provider/EServiceAuthenticationProvider.java
@@ -17,6 +17,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
@@ -32,10 +34,7 @@
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;
import java.util.*;
@Component
public class EServiceAuthenticationProvider {
@@ -98,6 +97,7 @@
        String dtoJson = new ObjectMapper().writeValueAsString(dto);
        RestTemplate restTemplate = getTrustAllRestTemplate();
        settingMessageConvertesToSpecifyType(restTemplate, MediaType.ALL);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
@@ -120,4 +120,12 @@
        requestFactory.setReadTimeout(300000);
        return new RestTemplate(requestFactory);
    }
    private void settingMessageConvertesToSpecifyType(RestTemplate restTemplate, MediaType mediaType) {
        List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setSupportedMediaTypes(Collections.singletonList(mediaType));
        messageConverters.add(converter);
        restTemplate.setMessageConverters(messageConverters);
    }
}
pamapi/src/main/java/com/pollex/pam/service/OtpWebService.java
@@ -22,7 +22,8 @@
    public OtpResponseDTO sendByPhone(String phone) throws ServiceException, RemoteException {
        OtpWebServicePortBindingStub stub = getOtpWebServicePortBindingStub();
        log.info("call OtpService snedOtpBySMS, ");
        log.info("call OtpService sendOtpBySMS, url = {}, systemType = {}, service password = {}, phone = {}",
            applicationProperty.getOtpWebServiceUrl(), applicationProperty.getOtpWebServiceSystemType(), applicationProperty.getOtpWebServicePassword(), phone);
        String[] result =
            stub.sendOtpBySMS(applicationProperty.getOtpWebServicePassword(), applicationProperty.getOtpWebServiceSystemType(), phone);
@@ -32,21 +33,19 @@
    public OtpResponseDTO sendByEmail(String email) throws ServiceException, RemoteException {
        OtpWebServicePortBindingStub stub = getOtpWebServicePortBindingStub();
        log.info("call OtpService sendByEmail, url = {}, systemType = {}, service password = {}, email = {}",
            applicationProperty.getOtpWebServiceUrl(), applicationProperty.getOtpWebServiceSystemType(), applicationProperty.getOtpWebServicePassword(), email);
        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());
        }
        return new OtpResponseDTO(result);
    }
    public OtpResponseDTO verifyOTP(String indexKey, String otpCode) throws ServiceException, RemoteException {
        OtpWebServicePortBindingStub stub = getOtpWebServicePortBindingStub();
        log.info("call OtpService verifyOTP, url = {}, systemType = {}, service password = {}, indexKey = {}, otpCode = {}",
            applicationProperty.getOtpWebServiceUrl(), applicationProperty.getOtpWebServiceSystemType(), applicationProperty.getOtpWebServicePassword(), indexKey, otpCode);
        String[] result =
            stub.verifyOtp(applicationProperty.getOtpWebServicePassword(), applicationProperty.getOtpWebServiceSystemType(), indexKey, otpCode);
@@ -54,7 +53,7 @@
        return new OtpResponseDTO(result);
    }
    private OtpWebServicePortBindingStub getOtpWebServicePortBindingStub() throws ServiceException {
    public OtpWebServicePortBindingStub getOtpWebServicePortBindingStub() throws ServiceException {
        OtpWebServiceLocator locator = new OtpWebServiceLocator();
        locator.setOtpWebServicePortEndpointAddress(applicationProperty.getOtpWebServiceUrl());
pamapi/src/main/java/com/pollex/pam/web/rest/OtpResource.java
@@ -1,15 +1,13 @@
package com.pollex.pam.web.rest;
import com.pollex.pam.config.ApplicationProperties;
import com.pollex.pam.enums.OtpLoginTypeEnum;
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 com.pollex.pam.web.rest.vm.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -22,14 +20,8 @@
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")
@@ -49,29 +41,21 @@
    @Autowired
    TokenProvider tokenProvider;
    @PostMapping("/byPhone")
    public ResponseEntity<Object> sendOtpByPhone(@RequestBody OtpSMSLoginVM login) {
    @PostMapping("/sendOtp")
    public ResponseEntity<Object> sendOtp(@RequestBody OtpLoginVM login) {
        try {
            if(applicationProperty.isMockLogin()) {
                return new ResponseEntity<>(getMockOtpResponse(), HttpStatus.OK);
                return new ResponseEntity<>(getMockSendOtpResponse(), 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");
            if(login.getLoginType() == OtpLoginTypeEnum.SMS) {
                return new ResponseEntity<>(otpWebService.sendByPhone(login.getAccount()), HttpStatus.OK);
        }
            else if(login.getLoginType() == OtpLoginTypeEnum.EMAIL) {
                return new ResponseEntity<>(otpWebService.sendByEmail(login.getAccount()), HttpStatus.OK);
    }
    @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);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("can not support this login type, loginType = " + login.getLoginType().name());
        } catch (ServiceException | RemoteException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("connecting otp web service error");
        }
@@ -93,7 +77,7 @@
        return new ResponseEntity<>(new UserJWTController.JWTToken(jwt), httpHeaders, HttpStatus.OK);
    }
    private OtpResponseDTO getMockOtpResponse() {
    private OtpResponseDTO getMockSendOtpResponse() {
        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
@@ -1,5 +1,6 @@
package com.pollex.pam.web.rest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pollex.pam.config.ApplicationProperties;
import com.pollex.pam.security.jwt.JWTFilter;
import com.pollex.pam.security.jwt.TokenProvider;
@@ -7,22 +8,43 @@
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.EServiceRequest;
import com.pollex.pam.service.dto.EServiceResponse;
import com.pollex.pam.service.dto.OtpResponseDTO;
import com.pollex.pam.web.rest.vm.OtpAccount;
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.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.http.*;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
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 org.springframework.web.client.RestTemplate;
import tw.com.softleader.otp.ws.OtpWebServicePortBindingStub;
import javax.net.ssl.SSLContext;
import javax.xml.rpc.ServiceException;
import java.rmi.RemoteException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
// todo,僅為初期接login方便使用而用get的方式登入,目前已拆出OtpResource與EServiceResource,主要是用這兩個做登入
@Deprecated
@RestController
@RequestMapping("/api/testLogin")
public class TestLoginResource {
@@ -46,44 +68,69 @@
    @GetMapping("/bySMS")
    public ResponseEntity<OtpResponseDTO> sendOtpBySMS(@RequestParam("phone") String phone) throws ServiceException, RemoteException {
        otpWebService.sendByPhone(phone);
        return new ResponseEntity<>(HttpStatus.OK);
        final OtpResponseDTO otpResponseDTO = otpWebService.sendByPhone(phone);
        return new ResponseEntity<>(otpResponseDTO, HttpStatus.OK);
    }
    @GetMapping("/byEmail")
    public ResponseEntity<OtpResponseDTO> sendOtpByEmail(@RequestParam("email") String email) throws RemoteException, ServiceException {
        otpWebService.sendByEmail(email);
        return new ResponseEntity<>(HttpStatus.OK);
        final OtpResponseDTO otpResponseDTO = otpWebService.sendByEmail(email);
        return new ResponseEntity<>(otpResponseDTO, 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
        );
    public ResponseEntity<OtpResponseDTO> verifyOtp(@RequestParam("account") String account, @RequestParam("indexKey") String indexKey, @RequestParam("otpCode") String otpCode) throws ServiceException, RemoteException {
        OtpWebServicePortBindingStub stub = otpWebService.getOtpWebServicePortBindingStub();
        log.info("call OtpService verifyOTP, systemType = {}, service password = {}, indexKey = {}, paxxword = {}",
            applicationProperty.getOtpWebServiceSystemType(), applicationProperty.getOtpWebServicePassword(), indexKey, 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);
        String[] result =
            stub.verifyOtp(applicationProperty.getOtpWebServicePassword(), applicationProperty.getOtpWebServiceSystemType(), indexKey, otpCode);
        return new ResponseEntity<>(new OtpResponseDTO(result), 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
        );
    public ResponseEntity<EServiceResponse> loginByEService(@RequestParam("account") String account, @RequestParam("password") String password) throws Exception {
        EServiceRequest dto = new EServiceRequest();
        dto.setFunc("ValidateUserLogin");
        dto.setId(account);
        dto.setPin(password);
        dto.setPwd(password);
        dto.setSys("epos");
        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);
        String dtoJson = new ObjectMapper().writeValueAsString(dto);
        RestTemplate restTemplate = getTrustAllRestTemplate();
        settingMessageConvertesToSpecifyType(restTemplate, MediaType.ALL);
        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 void settingMessageConvertesToSpecifyType(RestTemplate restTemplate, MediaType mediaType) {
        List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setSupportedMediaTypes(Collections.singletonList(mediaType));
        messageConverters.add(converter);
        restTemplate.setMessageConverters(messageConverters);
    }
    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/web/rest/vm/OtpLoginVM.java
¤ñ¹ï·sÀÉ®×
@@ -0,0 +1,24 @@
package com.pollex.pam.web.rest.vm;
import com.pollex.pam.enums.OtpLoginTypeEnum;
public class OtpLoginVM {
    private OtpLoginTypeEnum loginType;
    private String account;
    public OtpLoginTypeEnum getLoginType() {
        return loginType;
    }
    public void setLoginType(OtpLoginTypeEnum loginType) {
        this.loginType = loginType;
    }
    public String getAccount() {
        return account;
    }
    public void setAccount(String account) {
        this.account = account;
    }
}
pamapi/src/main/resources/config/application-sit.yml
@@ -115,4 +115,4 @@
  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
  e-service-login-url: https://eserviceuat.pcalife.com.tw/sso/chatbotValidate
pamapi/src/main/resources/logback-spring.xml
@@ -4,6 +4,27 @@
<configuration scan="true">
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    <property name="logback.dir" value="/appublic/applications/pamapi"/>
    <springProfile name="sit,uat,prod">
        <appender name="logToFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <File>${logback.dir}/pamapi_server.log</File>
            <rollingPolicy  class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <FileNamePattern>${logback.dir}/log.%d{yyyy-MM-dd}.zip</FileNamePattern>
                <maxHistory>180</maxHistory>
                <totalSizeCap>2GB</totalSizeCap>
            </rollingPolicy>
            <encoder>
                <charset>UTF-8</charset>
                <pattern>%d [%thread] %-5level %logger{36} %line - %msg%n</pattern>
            </encoder>
        </appender>
        <root level="DEBUG">
            <appender-ref ref="logToFile" />
        </root>
    </springProfile>
<!-- The FILE and ASYNC appenders are here as examples for a production configuration -->
<!--
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">