[JS 分析] 邮箱地址加密 [email protected]

本文探讨了JavaScript中带有感叹号的函数调用方式及其作用原理,并通过一个具体实例展示了如何解析并还原加密的电子邮件链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0.参考

https://segmentfault.com/q/1010000000117476 javascript里function之前加上感叹号 ' ! ' 会怎么样?

// 这么写会报错,因为这是一个函数定义:
function() {}()

// 常见的(多了一对括号),调用匿名函数:
(function() {})()

// 但在前面加上一个布尔运算符(只多了一个感叹号),就是表达式了,将执行后面的代码,也就合法实现调用
!function() {}()

1.页面表现

https://medium.com/@ageitgey/quick-tip-the-easiest-way-to-grab-data-out-of-a-web-page-in-python-7153cecfca58 使用到 https://apps.sandiego.gov/sdfiredispatch/

由于加载较慢,刚好看到:Please email any questions or concerns to [email protected].

加载完毕后页面显示:Please email any questions or concerns to webmaster@sandiego.gov.

 

2.代码定位

定位页面源代码显示 <p>Please email any questions or concerns to <a href="/cdn-cgi/l/email-protection#b1c6d4d3dcd0c2c5d4c3f1c2d0dfd5d8d4d6de9fd6dec7">

开发者工具全局搜索 email-protection

3.代码分析

关键在于确定代码执行入口:!function()

提取原始链接 # 之后的字符串,

function r:取出传入字符串的两位,十六进制转十进制数字

function n:href 取 # 之后的字符串前两位字母转为十进制密码,遍历剩下的字母,每两位字母转为十进制数字,分别与密码异或,再转字母,追加到结果字符串

 

4.完整代码

 https://www.cnblogs.com/my8100/p/9126202.html

 

5.运行结果

 

转载于:https://www.cnblogs.com/my8100/p/js_email_protection.html

<think>我们正在讨论如何实现邮箱和手机号验证码功能。根据引用内容,我们可以分别实现这两个功能。下面我将分步骤详细说明如何实现这两个功能,并给出代码示例。 ### 一、邮箱验证码功能实现 引用[1]和引用[3]提供了邮箱验证码的实现方法。主要步骤包括生成验证码、发送验证码到邮箱、验证用户输入的验证码。 #### 1. 生成邮箱验证码 引用[1]中使用了UUID生成一个随机字符串,并截取前8位作为验证码。这种方法可以保证验证码的随机性和安全性。 ```java import java.util.UUID; public class EmailVerificationCodeGenerator { /** * 生成邮箱验证码 * @return 验证码字符串 */ public static String generateEmailCode() { // 使用UUID生成验证码 String uuid = UUID.randomUUID().toString().replace("-", ""); // 截取前8位作为验证码 return uuid.substring(0, 8); } } ``` #### 2. 发送邮箱验证码 引用[3]提到使用Spring Boot发送邮件。这里需要配置邮件服务器(如163邮箱),并利用JavaMailSender发送邮件。 **步骤:** 1. 在Spring Boot项目中添加邮件依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> ``` 2. 配置邮件服务器信息(application.properties): ```properties spring.mail.host=smtp.163.com spring.mail.port=465 spring.mail.username=your_email@163.com spring.mail.password=your_authorization_code # 注意是授权码,不是登录密码 spring.mail.protocol=smtp spring.mail.properties.mail.smtp.ssl.enable=true ``` 3. 编写发送邮件的服务类: ```java import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.stereotype.Service; @Service public class EmailService { private final JavaMailSender mailSender; public EmailService(JavaMailSender mailSender) { this.mailSender = mailSender; } public void sendVerificationCode(String toEmail, String code) { SimpleMailMessage message = new SimpleMailMessage(); message.setFrom("your_email@163.com"); message.setTo(toEmail); message.setSubject("您的验证码"); message.setText("您的验证码是: " + code + ",有效期为2分钟。"); mailSender.send(message); } } ``` #### 3. 验证流程 - 用户请求发送验证码到邮箱。 - 后端生成验证码,并将其与邮箱、生成时间一起存储(通常使用Redis,设置2分钟过期)。 - 用户输入验证码后,后端从Redis中取出验证码进行比对。 ### 二、手机号验证码功能实现 引用[2]和引用[4]提供了手机验证码的实现方法。主要步骤包括生成验证码、发送验证码到手机、验证用户输入的验证码。 #### 1. 生成手机验证码 引用[2]要求验证码为6位数字。我们可以用随机数生成。 ```java import java.util.Random; public class SmsCodeGenerator { /** * 生成6位数字验证码 * @return 验证码字符串 */ public static String generateSmsCode() { Random random = new Random(); int code = random.nextInt(900000) + 100000; // 生成100000到999999之间的随机数 return String.valueOf(code); } } ``` #### 2. 发送手机验证码 实际发送短信需要接入第三方短信服务(如阿里云短信、腾讯云短信等)。这里以模拟发送为例。 **业务规则(引用[2]):** - 验证码长度为六位数字。 - 一个手机号一天只能发送三次验证码,超过三次拒绝发送。 - 验证码有效期为两分钟。 - 发送验证码间隔时间为一分钟(即60秒内不能重复发送)。 **实现步骤:** 1. 使用Redis记录发送次数和最近发送时间,以及存储验证码。 2. 在发送前检查次数和时间间隔。 **示例代码(Spring Boot + Redis):** 添加Redis依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 服务类: ```java import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Service; import java.util.concurrent.TimeUnit; @Service public class SmsService { private final RedisTemplate<String, String> redisTemplate; public SmsService(RedisTemplate<String, String> redisTemplate) { this.redisTemplate = redisTemplate; } public boolean sendVerificationCode(String phoneNumber) { // 检查发送次数:一天内不超过3次 String countKey = "sms:count:" + phoneNumber; String lastTimeKey = "sms:time:" + phoneNumber; // 获取当天已发送次数 Integer count = (Integer) redisTemplate.opsForValue().get(countKey); if (count != null && count >= 3) { return false; // 超过3次 } // 检查时间间隔(60秒内只能发送一次) Long lastTime = redisTemplate.getExpire(lastTimeKey); if (lastTime != null && lastTime > 54000) { // 如果上次发送时间在60秒内(TTL大于54000秒,因为设置60秒过期,所以剩余时间大于0即表示在60秒内) return false; } // 生成验证码 String code = SmsCodeGenerator.generateSmsCode(); // 发送验证码(模拟,实际调用短信接口) // TODO: 调用短信接口发送 // 存储验证码到Redis,有效期2分钟 String codeKey = "sms:code:" + phoneNumber; redisTemplate.opsForValue().set(codeKey, code, 2, TimeUnit.MINUTES); // 更新发送次数 if (count == null) { count = 0; } redisTemplate.opsForValue().set(countKey, String.valueOf(count + 1), 1, TimeUnit.DAYS); // 设置1天过期 // 记录本次发送时间,设置60秒过期,用于间隔控制 redisTemplate.opsForValue().set(lastTimeKey, "1", 60, TimeUnit.SECONDS); return true; } } ``` #### 3. 验证手机验证码 用户提交手机号和验证码后,从Redis中取出验证码进行比对。 ```java public boolean verifySmsCode(String phoneNumber, String code) { String codeKey = "sms:code:" + phoneNumber; String storedCode = redisTemplate.opsForValue().get(codeKey); if (storedCode == null) { return false; // 验证码已过期或不存在 } return storedCode.equals(code); } ``` ### 三、安全注意事项 1. **验证码长度和复杂度**:邮箱验证码通常比手机验证码长(如8位),手机验证码为6位数字,但都需保证随机性。 2. **频率限制**:防止恶意发送,需限制同一手机号/邮箱的发送次数和频率。 3. **有效期**:验证码应设置较短的有效期(如2分钟),减少被爆破的风险。 4. **存储安全**:验证码应存储在缓存(如Redis)中,不要返回给前端,且设置自动过期。 5. **传输安全**:发送验证码的API需进行安全防护(如验证图形验证码、IP限制等),防止被滥用。 ### 四、Spring Security集成 引用[4]提到使用Spring Security实现手机号和验证码认证。我们可以自定义一个认证过滤器,实现手机号+验证码的认证方式。 1. **自定义AuthenticationToken**:创建`SmsCodeAuthenticationToken`继承`AbstractAuthenticationToken`。 2. **自定义AuthenticationProvider**:实现验证码校验逻辑。 3. **配置Spring Security**:将自定义Provider加入安全配置。 由于篇幅限制,这里不展开详细代码,但引用[4]提供了实现思路。 ### 总结 - **邮箱验证码**:使用UUID生成8位随机字符串,通过邮件服务发送,存储于Redis并设置2分钟过期。 - **手机验证码**:生成6位随机数字,通过短信服务发送,需限制发送频率和次数,存储于Redis(2分钟过期)。 - **安全措施**:频率限制、有效期、存储安全是保障验证码安全的关键。 通过以上步骤,即可实现邮箱和手机号的验证码功能。 §§相关问题§§ 1. 如何防止验证码被恶意刷取? 2. 如何选择第三方短信服务商? 3. 邮箱验证码和手机验证码在安全性上有何差异? 4. 在分布式系统中如何实现验证码服务的并发控制?</think>### 邮箱和手机号验证码功能实现指南 以下分步骤说明实现方案,结合引用内容和最佳实践,涵盖生成、发送、验证全流程。 --- #### 一、邮箱验证码功能实现(基于引用[1][3]) ##### 1. 生成验证码 - **要求**:8位随机字符串(比手机验证码更长,安全性更高) - **Java实现**: ```java import java.util.UUID; public class EmailCodeGenerator { public static String generate() { // 生成UUID并移除连字符,截取前8位 return UUID.randomUUID().toString().replace("-", "").substring(0, 8); } } ``` ##### 2. 发送验证码 - **依赖**:Spring Boot Mail + SMTP服务(以163邮箱为例) - **配置步骤**: 1. 开启邮箱SMTP服务(登录163邮箱 → 设置 → POP3/SMTP → 开启服务并获取授权码) 2. `application.properties` 配置: ```properties spring.mail.host=smtp.163.com spring.mail.port=465 spring.mail.username=your_email@163.com spring.mail.password=your_authorization_code # 注意是授权码非登录密码 spring.mail.properties.mail.smtp.ssl.enable=true ``` 3. 发送服务代码: ```java import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; @Service public class EmailService { @Autowired private JavaMailSender mailSender; public void sendCode(String toEmail, String code) { SimpleMailMessage message = new SimpleMailMessage(); message.setFrom("your_email@163.com"); message.setTo(toEmail); message.setSubject("邮箱验证码"); message.setText("您的验证码是: " + code + ",有效期2分钟"); mailSender.send(message); } } ``` ##### 3. 验证流程 ```mermaid sequenceDiagram participant 用户 participant 前端 participant 后端 participant Redis 用户->>前端: 输入邮箱 前端->>后端: 请求发送验证码 后端->>后端: 生成8位验证码 后端->>EmailService: 发送验证码 EmailService-->>用户: 邮件送达 后端->>Redis: 存储[邮箱:验证码] (过期时间120秒) 用户->>前端: 输入验证码 前端->>后端: 提交验证码 后端->>Redis: 查询匹配结果 Redis-->>后端: 返回验证状态 后端-->>前端: 返回验证结果 ``` --- #### 二、手机验证码功能实现(基于引用[2][4]) ##### 1. 生成验证码 - **要求**:6位纯数字,需满足: - 单手机号每日限发3次 - 有效期2分钟 - 发送间隔60秒 - **Java实现**: ```java import java.util.Random; public class SmsCodeGenerator { public static String generate() { return String.format("%06d", new Random().nextInt(999999)); // 6位随机数 } } ``` ##### 2. 发送控制(Redis实现) ```java import org.springframework.data.redis.core.RedisTemplate; @Service public class SmsService { @Autowired private RedisTemplate<String, String> redisTemplate; public boolean sendCode(String phone) { // 检查发送次数(每日≤3次) String countKey = "sms_count:" + phone; Integer count = Integer.valueOf(redisTemplate.opsForValue().get(countKey)); if (count != null && count >= 3) return false; // 检查间隔(60秒内不重复发送) String timeKey = "sms_time:" + phone; if (redisTemplate.hasKey(timeKey)) return false; // 生成并发送 String code = SmsCodeGenerator.generate(); // TODO: 调用第三方短信API(如阿里云短信) // 存储到Redis redisTemplate.opsForValue().set("sms_code:" + phone, code, 2, TimeUnit.MINUTES); // 验证码 redisTemplate.opsForValue().set(timeKey, "1", 60, TimeUnit.SECONDS); // 间隔锁 redisTemplate.opsForValue().increment(countKey, 1); // 计数+1 redisTemplate.expire(countKey, 1, TimeUnit.DAYS); // 每日重置 return true; } } ``` ##### 3. Spring Security集成(引用[4]) ```java public class SmsCodeAuthenticationToken extends AbstractAuthenticationToken { private final String phone; private String code; // 构造器 public SmsCodeAuthenticationToken(String phone, String code) { super(null); this.phone = phone; this.code = code; setAuthenticated(false); } // 验证逻辑 @Override public Object getCredentials() { return code; } @Override public Object getPrincipal() { return phone; } } @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private SmsCodeAuthenticationProvider smsProvider; @Override protected void configure(AuthenticationManagerBuilder auth) { auth.authenticationProvider(smsProvider); // 注册自定义认证器 } } ``` --- #### 三、关键安全措施 1. **防刷机制**: - Redis计数器限制发送频率(如:手机号1分钟/次,邮箱5分钟/次) - 图形验证码前置校验(高危操作前要求输入) 2. **传输安全**: - HTTPS加密传输验证码 - 敏感信息脱敏(日志中不打印完整手机号) 3. **存储安全**: - 验证码必须存Redis/Memcached(不可存数据库) - 设置合理过期时间(推荐2-5分钟) 4. **验证防暴破**: ```java // 错误次数限制(Redis实现) String key = "verify_fail:" + phone; if (redisTemplate.opsForValue().increment(key) > 5) { throw new RuntimeException("验证失败次数过多"); } ``` --- #### 四、前端配合示例(Vue3) ```javascript // 发送验证码(含60秒倒计时) const sendEmailCode = async () => { if (countdown.value > 0) return; await axios.post('/api/send-email-code', { email: form.email }); countdown.value = 60; const timer = setInterval(() => { countdown.value--; if (countdown.value <= 0) clearInterval(timer); }, 1000); }; // 提交验证 const verify = async () => { const res = await axios.post('/api/verify', { phone: form.phone, code: form.code }); if (res.data.success) router.push('/dashboard'); }; ``` --- ### 总结对比 | **功能** | 邮箱验证码 | 手机验证码 | |----------------|-----------------------------------|-----------------------------------| | **验证码长度** | 8位字符串(更高安全性) | 6位数字(易输入性优先) | | **发送限制** | 较宽松(通常5分钟/次) | 严格(1分钟/次,每日≤3次) | | **安全风险** | 邮箱泄露风险 | SIM卡劫持风险 | | **适用场景** | 注册/密码重置等中安全场景 | 登录/支付等高频率操作 | > 实际选择建议: > - 金融类应用优先使用手机验证码+行为验证码双重验证 > - 国际应用优先邮箱验证(避免跨国短信问题) > - 高安全场景可组合使用(如换绑手机需邮箱二次验证)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值