From 83fdf8582cd37b0603dba3f4d0a869453722e292 Mon Sep 17 00:00:00 2001 From: wayne <wayne8692wayne8692@gmail.com> Date: 星期一, 29 十一月 2021 12:03:38 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/master' --- PAMapp/pages/login/index.vue | 47 +++++++---- pamapi/src/main/java/com/pollex/pam/config/SecurityConfiguration.java | 1 pamapi/src/main/java/com/pollex/pam/web/rest/ConsultantLoginValidateResource.java | 62 +++++++++++++++ pamapi/src/doc/登入API/顧問登入驗證碼流程.txt | 29 +++++++ pamapi/src/main/java/com/pollex/pam/service/util/VerifyCodeUtil.java | 68 +++++++++++++++++ 5 files changed, 191 insertions(+), 16 deletions(-) diff --git a/PAMapp/pages/login/index.vue b/PAMapp/pages/login/index.vue index 865dc7f..f1cb6f7 100644 --- a/PAMapp/pages/login/index.vue +++ b/PAMapp/pages/login/index.vue @@ -119,8 +119,9 @@ <el-row type="flex" justify="center" class="pam-login-page__action-bar mt-30"> <el-button type="primary" - v-if="connectDevice === 'MOBILE' && onPhoneVerifyStep === 'INPUT_OTP'" - :disabled="!otpCode || !phoneNumber || !phoneValid" + v-if="connectDevice === 'MOBILE' + && onPhoneVerifyStep === 'INPUT_OTP'" + :disabled="isSubmitBtnDisabled" @click="phoneLogin"> � </el-button> @@ -129,7 +130,7 @@ <el-dialog title="甇∟�雿輻��" :custom-class="'pam-register-dialog'" - :visible.sync="registerDialogVisable" + :visible.sync="registerDialogVisible" :fullscreen="true" :close-on-click-modal="false" :show-close="false" @@ -153,7 +154,8 @@ <el-row class="pt-10"> <div class="mdTxt pam-register-dialog__contract" - @scroll="detectContructReadStatus"> + ref="contract" + @scroll="detectContractReadStatus"> <h3>����犖鞈��鈭��</h3> <p class="mt-10"> �摰�犖鞈��風瘜��������犖鞈���������� @@ -216,15 +218,15 @@ </el-row> <el-row class="pt-30"> <div class="pam-agree-radio"> - <label for="agreeControct" class="pam-radio" + <label for="agreeContract" class="pam-radio" :class="{disabled: !isReadContract}"> <input type="radio" - id="agreeControct" - @click="agreeControct = !agreeControct" + id="agreeContract" + @click="agreeContract = !agreeContract" :disabled="!isReadContract" - value="agreeControct"> - <i :class="agreeControct ?'icon-checkbox-1': 'icon-checkbox'"></i>����蒂蝜潛�� + value="agreeContract"> + <i :class="agreeContract ?'icon-checkbox-1': 'icon-checkbox'"></i>����蒂蝜潛�� </label> </div> </el-row> @@ -232,7 +234,7 @@ <span slot="footer" class="dialog-footer"> <el-button type="primary" - :disabled="!name || !agreeControct || !isReadContract" + :disabled="!name || !agreeContract || !isReadContract" @click="applyAccount" >撱箇�撣唾�� </el-button> @@ -288,7 +290,7 @@ <script lang="ts"> import { namespace } from 'nuxt-property-decorator'; -import { Vue, Component } from 'vue-property-decorator'; +import { Vue, Component, Ref } from 'vue-property-decorator'; import { LoginRequest, loginVerify, OtpInfo, register, RegisterInfo, sendOtp } from '~/assets/ts/api/consultant'; import { Role } from '~/assets/ts/models/enum/Role'; @@ -298,6 +300,7 @@ export default class Login extends Vue { @roleStorage.Mutation storageIdToken!: (token:string) => void; @roleStorage.Mutation storageRole!: (role:string) => void; + @Ref('contract') readonly contract!: any; connectDevice: 'MOBILE' | 'EMAIL' = 'MOBILE'; @@ -309,6 +312,10 @@ otpInterval: any; phoneOtpInfo!: OtpInfo; + get isSubmitBtnDisabled(): boolean { + return !this.otpCode || !this.phoneNumber || !this.phoneValid; + } + email = ''; onEmailVerifyResendStatus: 'APPLY_OTP' | 'CAN_RESEND' = 'APPLY_OTP'; emailResendCounter = 30; @@ -316,18 +323,18 @@ emailOtpInfo!: OtpInfo; name = ''; - agreeControct = false; + agreeContract = false; isReadContract = false; phoneSuccessConfirmVisable = false; emailOtpConfirmVisable = false; - registerDialogVisable = false; + registerDialogVisible = false; registerSuccessConfirmVisable = false; applyAccount_onAction = false; - detectContructReadStatus(event: any): void { + detectContractReadStatus(event?: any): void { const scrollTop = Math.round(event.target.scrollTop); const height = event.target.scrollHeight - event.target.clientHeight; if (Math.floor(scrollTop/10) === (Math.floor(height/10))) { @@ -472,15 +479,22 @@ indexKey: this.phoneOtpInfo.indexKey, otpCode: this.otpCode } + loginVerify(login).then(res => { this.storageIdToken(res.data.id_token); this.storageRole(Role.USER); this.phoneSuccessConfirmVisable = true; }).catch(error => { if (error.response.status === 401) { - this.registerDialogVisable = true; + this.registerDialogVisible = true; + setTimeout(() => { + const isScrollBarNeedless = this.contract.scrollHeight <= this.contract.clientHeight; + if (isScrollBarNeedless) { + this.isReadContract = true; + } + }, 1000); } - }) + }); } destroyed() { @@ -530,6 +544,7 @@ border-radius: 6px; border: 1px solid #707070; padding: 20px; + max-height: 335px; } .pam-radio { diff --git "a/pamapi/src/doc/\347\231\273\345\205\245API/\351\241\247\345\225\217\347\231\273\345\205\245\351\251\227\350\255\211\347\242\274\346\265\201\347\250\213.txt" "b/pamapi/src/doc/\347\231\273\345\205\245API/\351\241\247\345\225\217\347\231\273\345\205\245\351\251\227\350\255\211\347\242\274\346\265\201\347\250\213.txt" new file mode 100644 index 0000000..c132146 --- /dev/null +++ "b/pamapi/src/doc/\347\231\273\345\205\245API/\351\241\247\345\225\217\347\231\273\345\205\245\351\251\227\350\255\211\347\242\274\346\265\201\347\250\213.txt" @@ -0,0 +1,29 @@ +* �������Ⅳ���� +http get : + +http://localhost:8080/api/login/validate/get_img_code + + +response content type: +image/jpeg + + + +* 撠��Ⅳ�敺垢�脰���� + +http get : + +http://localhost:8080/api/login/validate/verify_img_code/{imgCode} + +ex: +http://localhost:8080/api/login/validate/verify_img_code/4Rrcp + + + + +response : + +true (撽����), false(撽�仃���) + + + 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 4349448..6fca6d3 100644 --- a/pamapi/src/main/java/com/pollex/pam/config/SecurityConfiguration.java +++ b/pamapi/src/main/java/com/pollex/pam/config/SecurityConfiguration.java @@ -83,6 +83,7 @@ .antMatchers("/api/activate").permitAll() .antMatchers("/api/testLogin/**").permitAll() .antMatchers("/api/otp/**").permitAll() + .antMatchers("/api/login/validate/**").permitAll() .antMatchers("/api/eService/authenticate").permitAll() .antMatchers("/api/account/reset-password/init").permitAll() .antMatchers("/api/account/reset-password/finish").permitAll() diff --git a/pamapi/src/main/java/com/pollex/pam/service/util/VerifyCodeUtil.java b/pamapi/src/main/java/com/pollex/pam/service/util/VerifyCodeUtil.java new file mode 100644 index 0000000..e42af0b --- /dev/null +++ b/pamapi/src/main/java/com/pollex/pam/service/util/VerifyCodeUtil.java @@ -0,0 +1,68 @@ +package com.pollex.pam.service.util; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.util.Random; + +public final class VerifyCodeUtil { + + + public static String createcode() { + String code = ""; + code = ""; + String randomRange = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";// Randomly generated character + // range (0-9, a-z, A-Z) + + // The number of digits for generating the verification code (here 4 digits) + for (int i = 0; i < 4; i++) { + int index = (int) (Math.random() * 62);// Will produce a [0,62) number, excluding decimals + char randomCode = randomRange.charAt(index); + code = code + randomCode; + } + return code; + } + + // 3. Generate pictures + public static BufferedImage createimage(String code) { + // The first 2 parameters are: width, height. The back is the image type + // Create a BufferedImage object without transparent color, TYPE_INT_ARGB is + // with transparent color + BufferedImage bi = new BufferedImage(130, 50, BufferedImage.TYPE_INT_RGB); + + // 1. Get a canvas + Graphics g = bi.getGraphics(); + // 2. Add background color + g.setColor(Color.WHITE); + g.fillRect(0, 0, 130, 50); + + // 3. Add interference lines + for (int i = 0; i < 10; i++) { + Random r = new Random(); + int red = r.nextInt(256); + int green = r.nextInt(256); + int blue = r.nextInt(256); + Color c = new Color(red, green, blue); + g.setColor(c); + int x1 = r.nextInt(131); + int y1 = r.nextInt(51); + int x2 = r.nextInt(131); + int y2 = r.nextInt(51); + g.drawLine(x1, y1, x2, y2);// Draw a line + // g.drawOval(x1, y1, x2, y2);//Draw a curve + } + + // 3. Add text + g.setColor(Color.BLACK); + g.setFont(new Font(" ", Font.BOLD, 40)); + + // 4. Fill the text into the artboard + g.drawString(code, 15, 40); + + // 5. Close the canvas + g.dispose(); + return bi; + } + +} \ No newline at end of file diff --git a/pamapi/src/main/java/com/pollex/pam/web/rest/ConsultantLoginValidateResource.java b/pamapi/src/main/java/com/pollex/pam/web/rest/ConsultantLoginValidateResource.java new file mode 100644 index 0000000..47b4ffc --- /dev/null +++ b/pamapi/src/main/java/com/pollex/pam/web/rest/ConsultantLoginValidateResource.java @@ -0,0 +1,62 @@ +package com.pollex.pam.web.rest; + +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.pollex.pam.service.util.VerifyCodeUtil; + +@RestController +@RequestMapping("/api/login/validate") +public class ConsultantLoginValidateResource { + + @GetMapping("/get_img_code") + public void getVerifyCodeImg(HttpServletResponse response, HttpServletRequest request) { + try { + String code = VerifyCodeUtil.createcode(); + BufferedImage image = VerifyCodeUtil.createimage(code); + // Return to the client in a stream + response.setContentType("image/jpeg"); + // response.setContentType("image/bmp"); + ByteArrayOutputStream bt = new ByteArrayOutputStream(); + // Convert pictures to byte stream + ImageIO.write(image, "jpeg", bt); + ServletOutputStream outputStream = response.getOutputStream(); + outputStream.write(bt.toByteArray()); + HttpSession session = request.getSession(); + session.setAttribute("img_code", code); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + @GetMapping("/verify_img_code/{imgCode}") + public boolean verifyImgCode(HttpServletResponse response, HttpServletRequest request, + @PathVariable String imgCode) { + HttpSession session = request.getSession(); + String sessionImpCode = (String) session.getAttribute("img_code"); + if (!StringUtils.hasText(sessionImpCode) + || !StringUtils.hasText(imgCode)) { + return false; + } + + if (imgCode.equals(sessionImpCode)) { + return true; + } + + return false; + } +} -- Gitblit v1.8.0