From da6191fafa9aa07a1f4f56487d23fbc703a935b9 Mon Sep 17 00:00:00 2001 From: zhubaomin <zhubaomin> Date: 星期三, 11 九月 2024 11:41:47 +0800 Subject: [PATCH] 2024-09-11 朱宝民 新加获取图片验证码接口,完善单点登录接口 --- pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/captcha/CaptchaCtrl.java | 129 +++++++++ pipIrr-platform/pipIrr-global/pom.xml | 7 pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/config/KaptchaConfig.java | 128 +++++++++ pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/config/KaptchaMathTwoTextCreator.java | 26 + pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/captcha/dto/CaptchaDomain.java | 99 +++++++ pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/captcha/CaptchaSV.java | 104 +++++++ pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoBa/BaCaptcha.java | 56 ++++ pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/util/CaptchaUtil.java | 67 ++++ pipIrr-platform/pipIrr-global/src/main/resources/mapper/BaCaptchaMapper.xml | 96 ++++++ pipIrr-platform/pipIrr-web/pipIrr-web-sso/src/main/java/com/dy/sso/busi/LoginVo.java | 10 pipIrr-platform/pipIrr-web/pipIrr-web-sso/src/main/java/com/dy/sso/busi/SsoCtrl.java | 37 ++ pipIrr-platform/pipIrr-web/pipIrr-web-sso/src/main/java/com/dy/sso/busi/SsoSv.java | 14 pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/config/KaptchaMathOneTextCreator.java | 25 + pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoBa/BaCaptchaMapper.java | 36 ++ 14 files changed, 829 insertions(+), 5 deletions(-) diff --git a/pipIrr-platform/pipIrr-global/pom.xml b/pipIrr-platform/pipIrr-global/pom.xml index a494f6e..d18263c 100644 --- a/pipIrr-platform/pipIrr-global/pom.xml +++ b/pipIrr-platform/pipIrr-global/pom.xml @@ -158,6 +158,13 @@ <artifactId>commons-codec</artifactId> <version>1.15</version> </dependency> + + <!-- 鍥剧墖楠岃瘉鐮� --> + <dependency> + <groupId>com.github.penggle</groupId> + <artifactId>kaptcha</artifactId> + <version>2.3.2</version> + </dependency> </dependencies> <build> diff --git a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/config/KaptchaConfig.java b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/config/KaptchaConfig.java new file mode 100644 index 0000000..9c2182a --- /dev/null +++ b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/config/KaptchaConfig.java @@ -0,0 +1,128 @@ +package com.dy.pipIrrGlobal.config; + +import com.google.code.kaptcha.impl.DefaultKaptcha; +import com.google.code.kaptcha.util.Config; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Properties; + +/** + * @author ZhuBaoMin + * @date 2024-09-10 11:17 + * @LastEditTime 2024-09-10 11:17 + * @Description Google楠岃瘉鐮侀厤缃被锛岄厤缃笁绉嶇被鍨嬬殑楠岃瘉鐮佺敓鎴愬櫒锛氱畝鍗曟枃鏈獙璇佺爜銆佷竴浣嶆暟鍔犲噺涔橀櫎楠岃瘉鐮併�佷袱浣嶆暟鍔犲噺涔橀櫎楠岃瘉鐮� + */ + +@Configuration +public class KaptchaConfig { + private static KaptchaConfig instance; + + /** + * 楠岃瘉鐮侀厤缃粯璁ら厤缃� + * @return + */ + @Bean(name = "captchaProducer") + public DefaultKaptcha getKaptchaBean() { + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + Properties properties = new Properties(); + // 鏄惁鏈夎竟妗嗐�傞粯璁rue锛屽彲閫夛細yes锛宯o + properties.setProperty("kaptcha.border", "yes"); + //璁剧疆鍥剧墖杈规棰滆壊 + properties.setProperty("kaptcha.border.color", "green"); + // 楠岃瘉鐮佹枃鏈瓧绗﹂鑹层�傞粯璁olor.BLACK + properties.setProperty("kaptcha.textproducer.font.color", "black"); + // 鏂囧瓧闂撮殧 + properties.put("kaptcha.textproducer.char.space", "10"); + // 楠岃瘉鐮佸浘鐗囧搴︺�傞粯璁�200 + properties.setProperty("kaptcha.image.width", "160"); + // 楠岃瘉鐮佸浘鐗囬珮搴︺�傞粯璁�50 + properties.setProperty("Kkaptcha.image.height", "60"); + // 楠岃瘉鐮佹枃鏈瓧绗﹀ぇ灏忋�傞粯璁�40 + properties.setProperty("kaptcha.textproducer.font.size", "38"); + // KAPTCHA_SESSION_KEY + properties.setProperty("Kkaptcha.session.key", "kaptchaCode"); + // 楠岃瘉鐮佹枃鏈瓧绗﹂暱搴︺�傞粯璁�5 + properties.setProperty("kaptcha.textproducer.char.length", "4"); + // 楠岃瘉鐮佹枃鏈瓧浣撴牱寮忋�傞粯璁わ細new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) + properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier"); + // 骞叉壈瀹炵幇绫� + properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise"); + // 鍥剧墖鏍峰紡銆� + // 姘寸汗锛歝om.google.code.kaptcha.impl.WaterRipple + // 楸肩溂锛歝om.google.code.kaptcha.impl.FishEyeGimpy + // 闃村奖锛歝om.google.code.kaptcha.impl.ShadowGimpy + properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.WaterRipple"); + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } + + /** + * 楠岃瘉鐮佹暟瀛﹂绫婚厤缃紙涓�浣嶆暟鍔犲噺涔橀櫎锛� + * @return 閰嶇疆淇℃伅 + */ + @Bean(name = "captchaProducerMathOne") + public DefaultKaptcha getKaptchaBeanMathOne() { + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + Properties properties = commonConfig("com.dy.pipIrrGlobal.config.KaptchaMathOneTextCreator"); + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } + + /** + * 楠岃瘉鐮佹暟瀛﹂绫婚厤缃紙涓や綅鏁扮殑鍔犲噺涔橀櫎锛� + * @return 閰嶇疆淇℃伅 + */ + @Bean(name = "captchaProducerMathTwo") + public DefaultKaptcha getKaptchaBeanMathTwo() { + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + Properties properties = commonConfig("com.dy.pipIrrGlobal.config.KaptchaMathTwoTextCreator"); + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } + + /** + * 绠楀紡杩愮畻閰嶇疆鐨勫叕鍏遍厤缃被 + * @param textImpl 楠岃瘉鐮佹枃鏈敓鎴愬櫒 + * @return 閰嶇疆绫� + */ + protected static Properties commonConfig(String textImpl) { + Properties properties = new Properties(); + // 鏄惁鏈夎竟妗嗐�傞粯璁や负true锛屽彲璁剧疆锛歽es锛宯o + properties.setProperty("kaptcha.border", "yes"); + // 杈规棰滆壊銆傞粯璁わ細Color.BLACK + properties.setProperty("kaptcha.border.color", "105,179,90"); + // 楠岃瘉鐮佹枃鏈瓧绗﹂鑹层�傞粯璁わ細Color.BLACK + properties.setProperty("kaptcha.textproducer.font.color", "blue"); + // 楠岃瘉鐮佸浘鐗囧搴︺�傞粯璁わ細200 + properties.setProperty("kaptcha.image.width", "160"); + // 楠岃瘉鐮佸浘鐗囬珮搴︺�傞粯璁わ細50 + properties.setProperty("kaptcha.image.height", "60"); + // 楠岃瘉鐮佹枃鏈瓧绗﹀ぇ灏忋�傞粯璁わ細40 + properties.setProperty("kaptcha.textproducer.font.size", "35"); + // KAPTCHA_SESSION_KEY + properties.setProperty("kaptcha.session.key", "kaptchaCodeMath"); + // 楠岃瘉鐮佹枃鏈敓鎴愬櫒 + properties.setProperty("kaptcha.textproducer.impl", textImpl); + // 楠岃瘉鐮佹枃鏈瓧绗﹂棿璺濄�傞粯璁わ細2 + properties.setProperty("kaptcha.textproducer.char.space", "6"); + // 楠岃瘉鐮佹枃鏈瓧绗﹂暱搴︺�傞粯璁わ細5 + properties.setProperty("kaptcha.textproducer.char.length", "6"); + // 楠岃瘉鐮佹枃鏈瓧浣撴牱寮忋�傞粯璁わ細new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) + properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier"); + // 楠岃瘉鐮佸櫔鐐归鑹层�傞粯璁わ細Color.BLACK + properties.setProperty("kaptcha.noise.color", "white"); + // 骞叉壈瀹炵幇绫� + properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise"); + // 鍥剧墖鏍峰紡銆� + // 姘寸汗锛歝om.google.code.kaptcha.impl.WaterRipple + // 楸肩溂锛歝om.google.code.kaptcha.impl.FishEyeGimpy + // 闃村奖锛歝om.google.code.kaptcha.impl.ShadowGimpy + properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.WaterRipple"); + // 杩斿洖鐢熸垚鐨勯厤缃被 + return properties; + } +} diff --git a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/config/KaptchaMathOneTextCreator.java b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/config/KaptchaMathOneTextCreator.java new file mode 100644 index 0000000..f3040b7 --- /dev/null +++ b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/config/KaptchaMathOneTextCreator.java @@ -0,0 +1,25 @@ +package com.dy.pipIrrGlobal.config; + +import com.dy.pipIrrGlobal.util.CaptchaUtil; +import com.google.code.kaptcha.text.impl.DefaultTextCreator; + +import java.security.SecureRandom; +import java.util.Map; +import java.util.Random; + +/** + * @author ZhuBaoMin + * @date 2024-09-10 10:38 + * @LastEditTime 2024-09-10 10:38 + * @Description 楠岃瘉鐮侀殢鏈烘枃鏈敓鎴愬櫒锛氫竴浣嶆暟鐨勫姞鍑忎箻闄� + */ + +public class KaptchaMathOneTextCreator extends DefaultTextCreator { + @Override + public String getText() { + Random random = new SecureRandom(); + // 鐢熸垚涓や釜闅忔満鏁帮紝闅忔満鏁拌寖鍥达細[0,10)锛屽苟杩斿洖缁撴灉 + Map<String, String> result = CaptchaUtil.mathTextCreator(random.nextInt(10), random.nextInt(10)); + return result.get("resultString"); + } +} diff --git a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/config/KaptchaMathTwoTextCreator.java b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/config/KaptchaMathTwoTextCreator.java new file mode 100644 index 0000000..ada8d22 --- /dev/null +++ b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/config/KaptchaMathTwoTextCreator.java @@ -0,0 +1,26 @@ +package com.dy.pipIrrGlobal.config; + +import com.dy.pipIrrGlobal.util.CaptchaUtil; +import com.google.code.kaptcha.text.impl.DefaultTextCreator; + +import java.security.SecureRandom; +import java.util.Map; +import java.util.Random; + +/** + * @author ZhuBaoMin + * @date 2024-09-10 10:39 + * @LastEditTime 2024-09-10 10:39 + * @Description 楠岃瘉鐮侀殢鏈烘枃鏈敓鎴愬櫒锛氫袱浣嶆暟鐨勫姞鍑忎箻闄� + */ + +public class KaptchaMathTwoTextCreator extends DefaultTextCreator { + @Override + public String getText() { + Random random = new SecureRandom(); + // 淇濆瓨璁$畻缁撴灉 + Map<String, String> result = CaptchaUtil.mathTextCreator(random.nextInt(100), random.nextInt(100)); + // 鐢熸垚涓や釜闅忔満鏁帮紝闅忔満鏁拌寖鍥达細[0,100)锛屽苟杩斿洖缁撴灉 + return result.get("resultString"); + } +} diff --git a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoBa/BaCaptchaMapper.java b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoBa/BaCaptchaMapper.java new file mode 100644 index 0000000..4c610e3 --- /dev/null +++ b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoBa/BaCaptchaMapper.java @@ -0,0 +1,36 @@ +package com.dy.pipIrrGlobal.daoBa; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.dy.pipIrrGlobal.pojoBa.BaCaptcha; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Map; + +/** + * @author ZhuBaoMin + * @date 2024-09-11 10:58 + * @LastEditTime 2024-09-11 10:58 + * @Description + */ + +@Mapper +public interface BaCaptchaMapper extends BaseMapper { + int deleteByPrimaryKey(Long id); + + int insert(BaCaptcha record); + + int insertSelective(BaCaptcha record); + + BaCaptcha selectByPrimaryKey(Long id); + + int updateByPrimaryKeySelective(BaCaptcha record); + + int updateByPrimaryKey(BaCaptcha record); + + /** + * 渚濇嵁楠岃瘉鐮乼oken鑾峰彇楠岃瘉瀛楃 + * @param token + * @return + */ + Map getCodeByToken(String token); +} \ No newline at end of file diff --git a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoBa/BaCaptcha.java b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoBa/BaCaptcha.java new file mode 100644 index 0000000..28e83d8 --- /dev/null +++ b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoBa/BaCaptcha.java @@ -0,0 +1,56 @@ +package com.dy.pipIrrGlobal.pojoBa; + +/** + * @author ZhuBaoMin + * @date 2024-09-11 10:58 + * @LastEditTime 2024-09-11 10:58 + * @Description + */ + +import com.alibaba.fastjson2.annotation.JSONField; +import com.alibaba.fastjson2.writer.ObjectWriterImplToString; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.dy.common.po.BaseEntity; +import jakarta.validation.constraints.NotBlank; +import lombok.*; + +/** + * 鍥惧舰楠岃瘉璁板綍琛� + */ + +@TableName(value = "ba_captcha", autoResultMap = true) +@Data +@Builder +@ToString +@NoArgsConstructor +@AllArgsConstructor +public class BaCaptcha implements BaseEntity { + public static final long serialVersionUID = 202409111103001L; + + /** + * 涓婚敭 + */ + @JSONField(serializeUsing = ObjectWriterImplToString.class) + @TableId(type = IdType.INPUT) + private Long id; + + /** + * 楠岃瘉鐮乼oken + */ + @NotBlank(message = "楠岃瘉鐮乼oken涓嶈兘涓虹┖") + private String token; + + /** + * 楠岃瘉瀛楃 + */ + @NotBlank(message = "楠岃瘉瀛楃涓嶈兘涓虹┖") + private String code; + + /** + * 杩囨湡鏃堕棿 + */ + @JSONField(serializeUsing = ObjectWriterImplToString.class) + private Long expiration; +} \ No newline at end of file diff --git a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/util/CaptchaUtil.java b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/util/CaptchaUtil.java new file mode 100644 index 0000000..5f7bfd8 --- /dev/null +++ b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/util/CaptchaUtil.java @@ -0,0 +1,67 @@ +package com.dy.pipIrrGlobal.util; + +import java.security.SecureRandom; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +/** + * @author ZhuBaoMin + * @date 2024-09-10 10:32 + * @LastEditTime 2024-09-10 10:32 + * @Description 鑷畾涔夐獙璇佺爜宸ュ叿绫� + */ + +public class CaptchaUtil { + /** + * 鐢熸垚鏁板鏂囨湰绠楀紡锛屼緥濡�1+1=锛� + * @param a 鏁板瓧 + * @param b 鏁板瓧 + * @return 瀛楃 + */ + public static Map<String, String> mathTextCreator(int a, int b) { + Random random = new SecureRandom(); + // 鐢熸垚闅忔満鎿嶄綔锛屾搷浣滆寖鍥达細[0,4)锛屽垎鍒〃绀猴細 + - * / + int op = random.nextInt(4); + // 瀹氫箟璁$畻鐨勭粨鏋� + Integer result = 0; + // 瀹氫箟鏋勫缓鐨勭畻寮忓瓧绗︿覆 + StringBuilder resultString = new StringBuilder(); + // 杩愮畻绗︼細- + if (1 == op) { + if (a >= b) { + result = a - b; + resultString.append(a).append("-").append(b).append("=?@").append(result); + } else { + result = b - a; + resultString.append(b).append("-").append(a).append("=?@").append(result); + } + } + // 杩愮畻绗︼細* + else if (2 == op) { + result = a * b; + resultString.append(a).append("*").append(b).append("=?@").append(result); + } + // 杩愮畻绗︼細/ + else if (3 == op) { + if (a != 0 && b % a == 0) { + result = b / a; + resultString.append(b).append("/").append(a).append("=?@").append(result); + } else if (b != 0 && a % b == 0) { + result = a / b; + resultString.append(a).append("/").append(b).append("=?@").append(result); + } else { + return mathTextCreator(a, b); + } + } + // 杩愮畻绗︼細+ + else { + result = b + a; + resultString.append(a).append("+").append(b).append("=?@").append(result); + } + Map<String, String> ret = new HashMap<String, String>(); + ret.put("resultCode", result.toString()); + ret.put("resultString", resultString.toString()); + return ret; + } +} diff --git a/pipIrr-platform/pipIrr-global/src/main/resources/mapper/BaCaptchaMapper.xml b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/BaCaptchaMapper.xml new file mode 100644 index 0000000..f0aeaeb --- /dev/null +++ b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/BaCaptchaMapper.xml @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.dy.pipIrrGlobal.daoBa.BaCaptchaMapper"> + <resultMap id="BaseResultMap" type="com.dy.pipIrrGlobal.pojoBa.BaCaptcha"> + <!--@mbg.generated--> + <!--@Table ba_captcha--> + <id column="id" jdbcType="BIGINT" property="id" /> + <result column="token" jdbcType="VARCHAR" property="token" /> + <result column="code" jdbcType="VARCHAR" property="code" /> + <result column="expiration" jdbcType="BIGINT" property="expiration" /> + </resultMap> + <sql id="Base_Column_List"> + <!--@mbg.generated--> + id, token, code, expiration + </sql> + <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> + <!--@mbg.generated--> + select + <include refid="Base_Column_List" /> + from ba_captcha + where id = #{id,jdbcType=BIGINT} + </select> + <delete id="deleteByPrimaryKey" parameterType="java.lang.Long"> + <!--@mbg.generated--> + delete from ba_captcha + where id = #{id,jdbcType=BIGINT} + </delete> + <insert id="insert" parameterType="com.dy.pipIrrGlobal.pojoBa.BaCaptcha"> + <!--@mbg.generated--> + insert into ba_captcha (id, token, code, + expiration) + values (#{id,jdbcType=BIGINT}, #{token,jdbcType=VARCHAR}, #{code,jdbcType=VARCHAR}, + #{expiration,jdbcType=BIGINT}) + </insert> + <insert id="insertSelective" parameterType="com.dy.pipIrrGlobal.pojoBa.BaCaptcha"> + <!--@mbg.generated--> + insert into ba_captcha + <trim prefix="(" suffix=")" suffixOverrides=","> + <if test="id != null"> + id, + </if> + <if test="token != null"> + token, + </if> + <if test="code != null"> + code, + </if> + <if test="expiration != null"> + expiration, + </if> + </trim> + <trim prefix="values (" suffix=")" suffixOverrides=","> + <if test="id != null"> + #{id,jdbcType=BIGINT}, + </if> + <if test="token != null"> + #{token,jdbcType=VARCHAR}, + </if> + <if test="code != null"> + #{code,jdbcType=VARCHAR}, + </if> + <if test="expiration != null"> + #{expiration,jdbcType=BIGINT}, + </if> + </trim> + </insert> + <update id="updateByPrimaryKeySelective" parameterType="com.dy.pipIrrGlobal.pojoBa.BaCaptcha"> + <!--@mbg.generated--> + update ba_captcha + <set> + <if test="token != null"> + token = #{token,jdbcType=VARCHAR}, + </if> + <if test="code != null"> + code = #{code,jdbcType=VARCHAR}, + </if> + <if test="expiration != null"> + expiration = #{expiration,jdbcType=BIGINT}, + </if> + </set> + where id = #{id,jdbcType=BIGINT} + </update> + <update id="updateByPrimaryKey" parameterType="com.dy.pipIrrGlobal.pojoBa.BaCaptcha"> + <!--@mbg.generated--> + update ba_captcha + set token = #{token,jdbcType=VARCHAR}, + code = #{code,jdbcType=VARCHAR}, + expiration = #{expiration,jdbcType=BIGINT} + where id = #{id,jdbcType=BIGINT} + </update> + + <!--渚濇嵁楠岃瘉鐮乼oken鑾峰彇楠岃瘉瀛楃--> + <select id="getCodeByToken" resultType="java.util.Map"> + SELECT code, expiration FROM ba_captcha WHERE token = #{token} + </select> +</mapper> \ No newline at end of file diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sso/src/main/java/com/dy/sso/busi/LoginVo.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sso/src/main/java/com/dy/sso/busi/LoginVo.java index cf1501b..57ff5e4 100644 --- a/pipIrr-platform/pipIrr-web/pipIrr-web-sso/src/main/java/com/dy/sso/busi/LoginVo.java +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sso/src/main/java/com/dy/sso/busi/LoginVo.java @@ -33,5 +33,15 @@ @NotEmpty(message = "缁勭粐鍗曚綅涓嶈兘涓虹┖") //涓嶈兘涓虹┖涔熶笉鑳戒负null @Length(message = "缁勭粐鍗曚綅鏍囩蹇呴』澶т簬{min}浣�", min = 2) public String orgTag ; + + /** + * 鍥惧舰楠岃瘉鐮乼oken锛屽嵆session鐨刱ey + */ + private String token; + + /** + * 鍥惧舰楠岃瘉鐮佺粨鏋� + */ + private String code; } diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sso/src/main/java/com/dy/sso/busi/SsoCtrl.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sso/src/main/java/com/dy/sso/busi/SsoCtrl.java index 46fc4db..1bbfa52 100644 --- a/pipIrr-platform/pipIrr-web/pipIrr-web-sso/src/main/java/com/dy/sso/busi/SsoCtrl.java +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sso/src/main/java/com/dy/sso/busi/SsoCtrl.java @@ -25,9 +25,7 @@ import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; -import java.util.List; -import java.util.Objects; -import java.util.UUID; +import java.util.*; /** * 娉ㄨВTag 鍦ˋPI涓樉绀猴細 Tag 娉ㄨВ, 缁欐暣涓帴鍙h捣浜嗕釜鍚嶅瓧涓庢弿杩�" @@ -45,6 +43,7 @@ //鍦ㄥ睘鎬т笂娉ㄨВ@Autowired鏃讹紝浼氳鍛� Field injection is not recommended锛堜笉鍐嶆帹鑽愪娇鐢ㄥ瓧娈垫敞鍏ワ級 private SsoSv sv ; + //private KaptchaConfig kaptchaConfig; //@Autowired //private CacheManager cacheManager ; @@ -53,6 +52,10 @@ this.sv = sv ; } + //@Autowired + //public void setKaptchaConfig(KaptchaConfig kaptchaConfig) { + // this.kaptchaConfig = kaptchaConfig; + //} /** * 瀹㈡埛绔姹傚緱鍒版墍鏈夌粍缁囨満鏋� @@ -98,7 +101,7 @@ ) }) @PostMapping(path = "loginJson", consumes = MediaType.APPLICATION_JSON_VALUE) - public BaseResponse<UserVo> loginJson(@RequestBody @Parameter(description = "鐧诲綍json鏁版嵁", required = true) @Valid LoginVo vo, @Parameter(hidden = true) BindingResult bindingResult) { + public BaseResponse<UserVo> loginJson(HttpServletRequest request, @RequestBody @Parameter(description = "鐧诲綍json鏁版嵁", required = true) @Valid LoginVo vo, @Parameter(hidden = true) BindingResult bindingResult) { if(bindingResult != null && bindingResult.hasErrors()){ return BaseResponseUtils.buildErrorMsg(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage()); } @@ -113,6 +116,32 @@ //鎶婄粍缁囧崟浣嶆爣绛句綔涓烘暟鎹簮鍚嶇О DataSourceContext.set(vo.orgTag); + String token = Optional.ofNullable(vo.getToken()).orElse(""); + String code = Optional.ofNullable(vo.getCode()).orElse(""); + + + + + + if(token.length() > 0 && code.length() > 0) { + // 浠巗ession涓幏鍙栭獙璇佺爜 + //HttpSession session = (HttpSession) request.getSession(); + //String localCode = session.getAttribute(token).toString(); + + Map map = sv.getCodeByToken(token); + Long expiration = Long.parseLong(map.get("expiration").toString()); + Long currentTimestamp = System.currentTimeMillis(); + if(currentTimestamp > expiration) { + return BaseResponseUtils.buildErrorMsg("楠岃瘉鐮佸凡瓒呮椂"); + } + + // 浠庢暟鎹簱鑾峰彇楠岃瘉鐮� + String localCode = map.get("code").toString(); + if(!code.equals(localCode)) { + return BaseResponseUtils.buildErrorMsg("楠岃瘉鐮侀敊璇�"); + } + } + //寰楀埌鎵�鏈夌敤鎴疯处鍙� List<String> phones = sv.getPhones(); if(!phones.contains(vo.phone)){ diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sso/src/main/java/com/dy/sso/busi/SsoSv.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sso/src/main/java/com/dy/sso/busi/SsoSv.java index fbd0ceb..bed8576 100644 --- a/pipIrr-platform/pipIrr-web/pipIrr-web-sso/src/main/java/com/dy/sso/busi/SsoSv.java +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sso/src/main/java/com/dy/sso/busi/SsoSv.java @@ -1,6 +1,7 @@ package com.dy.sso.busi; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.dy.pipIrrGlobal.daoBa.BaCaptchaMapper; import com.dy.pipIrrGlobal.daoBa.BaUserMapper; import com.dy.pipIrrGlobal.pojoBa.BaUser; import lombok.extern.slf4j.Slf4j; @@ -11,11 +12,11 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.Map; @Slf4j @Service public class SsoSv { - private BaUserMapper baUserMapper; @Autowired @@ -23,6 +24,8 @@ this.baUserMapper = baUserMapper ; } + @Autowired + private BaCaptchaMapper baCaptchaMapper; /** * 闇�瑕丅aUserMapper.xml @@ -76,4 +79,13 @@ public List<String> getPhones(){ return baUserMapper.getPhones() ; } + + /** + * 渚濇嵁楠岃瘉鐮乼oken鑾峰彇楠岃瘉瀛楃 + * @param token + * @return + */ + public Map getCodeByToken(String token) { + return baCaptchaMapper.getCodeByToken(token); + } } diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/captcha/CaptchaCtrl.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/captcha/CaptchaCtrl.java new file mode 100644 index 0000000..933b981 --- /dev/null +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/captcha/CaptchaCtrl.java @@ -0,0 +1,129 @@ +package com.dy.pipIrrWechat.captcha; + +import com.dy.pipIrrGlobal.pojoBa.BaCaptcha; +import com.dy.pipIrrWechat.captcha.dto.CaptchaDomain; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.imageio.ImageIO; +import java.io.IOException; +import java.util.Calendar; + +/** + * @author ZhuBaoMin + * @date 2024-09-10 11:40 + * @LastEditTime 2024-09-10 11:40 + * @Description 鍥剧墖楠岃瘉鐮� + */ + +@Slf4j +@RestController +@RequestMapping(path="captcha") +public class CaptchaCtrl { + @Autowired + private CaptchaSV captchaSV; + + /** + * 鑾峰彇楠岃瘉鐮� + * @param type锛屽浘鐗囩被鍨嬶細char-鏂囨湰锛宮ath-涓�浣嶆暟绠楀紡锛宮ath2-涓や綅鏁扮畻寮� + * @return + */ + @GetMapping("/get") + @ResponseBody + public CaptchaDomain getCaptcha(HttpServletRequest request, @RequestParam(value = "type", required = false, defaultValue = "char") String type) { + // 鐢熸垚楠岃瘉鐮佸疄浣� + CaptchaDomain captchaDomain = captchaSV.createGoogleCaptcha(type); + if (null != captchaDomain) { + + // 楠岃瘉鐮佷繚瀛樿嚦redis + // redisUtils.set(captchaDomain.getToken(), captchaDomain.getCode(), 300L); + + // 楠岃瘉鐮佷繚瀛樿嚦session + //HttpSession session = (HttpSession) request.getSession(); + //session.setAttribute(captchaDomain.getToken(), captchaDomain.getCode()); + + /** + * 楠岃瘉淇濆瓨鍒版暟鎹簱 + * 鑾峰彇褰撳墠鏃堕棿鎴冲苟寤跺悗3鍒嗛挓 + */ + Long timestamp = System.currentTimeMillis(); + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(timestamp); + calendar.add(Calendar.SECOND, 180); + + BaCaptcha baCaptcha = new BaCaptcha(); + baCaptcha.setToken(captchaDomain.getToken()); + baCaptcha.setCode(captchaDomain.getCode()); + baCaptcha.setExpiration(calendar.getTimeInMillis()); + Long rec = captchaSV.addCaptcha(baCaptcha); + System.out.println("token: " + captchaDomain.getToken() + "; code: " + captchaDomain.getCode()); + + // 鏃犵敤淇℃伅璁剧┖ + captchaDomain.setText(null); + captchaDomain.setCode(null); + // 杩斿洖鍓嶇淇℃伅 + return captchaDomain; + } else { + return null; + } + } + + /** + * 鐩存帴杈撳嚭鍥剧墖 + * @param type锛屽浘鐗囩被鍨嬶細char-鏂囨湰锛宮ath-涓�浣嶆暟绠楀紡锛宮ath2-涓や綅鏁扮畻寮� + */ + @GetMapping("/get/image") + public void getCaptchaImage(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "type", required = false, defaultValue = "char") String type) { + CaptchaDomain captchaDomain = null; + + // 鐢熸垚璋锋瓕楠岃瘉鐮佸疄浣� + captchaDomain = captchaSV.createGoogleCaptcha(type); + + // 楠岃瘉鐮佷繚瀛樿嚦redis + // redisUtils.set(captchaDomain.getToken(), captchaDomain.getCode(), 300L); + + // 楠岃瘉鐮佷繚瀛樿嚦session + //HttpSession session = (HttpSession) request.getSession(); + //session.setAttribute(captchaDomain.getToken(), captchaDomain.getCode()); + + /** + * 楠岃瘉淇濆瓨鍒版暟鎹簱 + * 鑾峰彇褰撳墠鏃堕棿鎴冲苟寤跺悗3鍒嗛挓 + */ + Long timestamp = System.currentTimeMillis(); + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(timestamp); + calendar.add(Calendar.SECOND, 180); + + BaCaptcha baCaptcha = new BaCaptcha(); + baCaptcha.setToken(captchaDomain.getToken()); + baCaptcha.setCode(captchaDomain.getCode()); + baCaptcha.setExpiration(calendar.getTimeInMillis()); + Long rec = captchaSV.addCaptcha(baCaptcha); + System.out.println("token: " + captchaDomain.getToken() + "; code: " + captchaDomain.getCode()); + + // 浠ユ枃浠舵祦鐨勫舰寮忥紝杈撳嚭楠岃瘉鐮佸浘鐗� + ServletOutputStream out = null; + try { + response.setContentType("image/jpeg"); + out = response.getOutputStream(); + ImageIO.write(captchaDomain.getImage(), "jpg", out); + out.flush(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (out != null) { + out.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + +} diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/captcha/CaptchaSV.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/captcha/CaptchaSV.java new file mode 100644 index 0000000..f802662 --- /dev/null +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/captcha/CaptchaSV.java @@ -0,0 +1,104 @@ +package com.dy.pipIrrWechat.captcha; + +import com.dy.pipIrrGlobal.daoBa.BaCaptchaMapper; +import com.dy.pipIrrGlobal.pojoBa.BaCaptcha; +import com.dy.pipIrrWechat.captcha.dto.CaptchaDomain; +import com.google.code.kaptcha.Producer; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.imageio.ImageIO; +import java.io.ByteArrayOutputStream; +import java.util.Base64; +import java.util.UUID; + +/** + * @author ZhuBaoMin + * @date 2024-09-10 11:40 + * @LastEditTime 2024-09-10 11:40 + * @Description + */ + +@Slf4j +@Service +public class CaptchaSV { + @Autowired + private BaCaptchaMapper baCaptchaMapper; + + @Resource(name = "captchaProducer") + private Producer captchaProducer; + + @Resource(name = "captchaProducerMathOne") + private Producer captchaProducerMathOne; + + @Resource(name = "captchaProducerMathTwo") + private Producer captchaProducerMathTwo; + + private static final String TYPE_CHAR = "char"; + private static final String TYPE_MATH_ONE = "math"; + private static final String TYPE_MATH_TWO = "math2"; + + /** + * Kaptcha鐢熸垚楠岃瘉鐮佸疄浣� + * @param type锛宑har - 瀛楃(缂虹渷) | math - 涓�浣嶆暟绠楀紡 | math2 - 涓や綅鏁扮畻寮� + * @return + */ + public CaptchaDomain createGoogleCaptcha(String type) { + // 瀹氫箟楠岃瘉鐮佸疄浣� + CaptchaDomain captchaDomain = new CaptchaDomain(); + // 涓�浣嶆暟鍔犲噺涔橀櫎 + if (TYPE_MATH_ONE.equals(type)) { + // 鐢熸垚鏂囨湰 + String producerText = captchaProducerMathOne.createText(); + // 璁剧疆楠岃瘉鐮佸瓧绗� + captchaDomain.setText(producerText.substring(0, producerText.indexOf("@"))); + // 璁剧疆楠岃瘉鐮佺瓟妗堢爜 + captchaDomain.setCode(producerText.substring(producerText.indexOf("@") + 1)); + // 璁剧疆楠岃瘉鐮佸浘鐗� + captchaDomain.setImage(captchaProducerMathOne.createImage(captchaDomain.getText())); + } + // 涓や綅鏁板姞鍑忎箻闄� + else if (TYPE_MATH_TWO.equals(type)) { + String producerText = captchaProducerMathTwo.createText(); + captchaDomain.setText(producerText.substring(0, producerText.indexOf("@"))); + captchaDomain.setCode(producerText.substring(producerText.indexOf("@") + 1)); + captchaDomain.setImage(captchaProducerMathTwo.createImage(captchaDomain.getText())); + } + // 缂虹渷鎯呭喌锛氬瓧绗� + else { + captchaDomain.setText(captchaProducer.createText()); + captchaDomain.setCode(captchaDomain.getText()); + captchaDomain.setImage(captchaProducer.createImage(captchaDomain.getText())); + } + // 鐢熸垚base64 + try { + // 瀹氫箟瀛楄妭鏁扮粍杈撳嚭娴� + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + // 灏嗗浘鍍忎互 jpg 鐨勫舰寮忥紝鍐欏埌瀛楄妭鏁扮粍杈撳嚭娴佷腑 + ImageIO.write(captchaDomain.getImage(), "jpg", outputStream); + + // 鍐欏叆base64鏍煎紡 + captchaDomain.setBase64("data:image/jpg;base64," + Base64.getEncoder().encodeToString(outputStream.toByteArray())); + // 鍐欏叆鍞竴Token + captchaDomain.setToken(UUID.randomUUID().toString()); + // 杩斿洖缁撴灉 + return captchaDomain; + } catch (Exception e) { + System.out.println(e.getMessage()); + return null; + } + } + + /** + * 娣诲姞鍥剧墖楠岃瘉璁板綍 + * @param po + * @return + */ + public Long addCaptcha(BaCaptcha po) { + baCaptchaMapper.insert(po); + return po.getId(); + } + +} diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/captcha/dto/CaptchaDomain.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/captcha/dto/CaptchaDomain.java new file mode 100644 index 0000000..6124205 --- /dev/null +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/captcha/dto/CaptchaDomain.java @@ -0,0 +1,99 @@ +package com.dy.pipIrrWechat.captcha.dto; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.awt.image.BufferedImage; +import java.io.Serializable; + +/** + * @author ZhuBaoMin + * @date 2024-09-10 11:36 + * @LastEditTime 2024-09-10 11:36 + * @Description 绗笁鏂归獙璇佺爜瀹炰綋绫� + */ + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class CaptchaDomain implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 楠岃瘉鐮佺殑Token + */ + private String token; + + /** + * 楠岃瘉鐮佺殑瀛楃銆傝繑鍥炵殑JSON锛岀姝㈣繑鍥炵粰鍓嶇銆� + */ + @JsonIgnore + private String text; + + /** + * 楠岃瘉鐮佺殑楠岃瘉瀛楃銆傛瘮濡傜畻寮忕殑缁撴灉绛夈�� + */ + @JsonIgnore + private String code; + + /** + * 楠岃瘉鐮佺紦鍐插浘鍍� + */ + @JsonIgnore + private BufferedImage image; + + /** + * 楠岃瘉鐮佸浘鐗囩殑Base64瀛楃涓� + */ + private String base64; + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public BufferedImage getImage() { + return image; + } + + public void setImage(BufferedImage image) { + this.image = image; + } + + public String getBase64() { + return base64; + } + + public void setBase64(String base64) { + this.base64 = base64; + } + + @Override + public String toString() { + return "CaptchaDomain{" + + "token='" + token + '\'' + + ", text='" + text + '\'' + + ", code='" + code + '\'' + + ", image=" + image + + ", base64='" + base64 + '\'' + + '}'; + } +} -- Gitblit v1.8.0