0
点赞
收藏
分享

微信扫一扫

【探花交友】注册登录需求分析


文章目录

​​5、注册登录需求分析​​

​​5.1、业务说明​​

​​5.2、需求分析​​

​​5.3、数据库表​​

​​5.4、实体类​​

​​6、短信验证码​​

​​6.1、阿里云短信服务​​

​​6.2、模板组件​​

5、注册登录需求分析

5.1、业务说明

用户通过手机验证码进行登录,如果是第一次登录则需要完善个人信息,在上传图片时,需要对上传的图片做人像的校验,防止用户上传非人像的图片作为头像。流程完成后,则登录成功。

  • 已注册用户:
  • 输入手机号发送验证码
  • 输入验证码,进行比对完成登录
  • 未注册用户:
  • 输入手机号发送验证码
  • 输入验证码,进行比对,自动注册(保存用户)
  • 完善用户信息

5.2、需求分析

服务端接受客户端请求

Java代码调用第三方服务实现短信返送(发送短信需要运营资质,只能借助第三方实现)

【探花交友】注册登录需求分析_java

5.3、数据库表

数据库使用的mysql:

CREATE TABLE `tb_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`mobile` varchar(11) DEFAULT NULL COMMENT '手机号',
`password` varchar(32) DEFAULT NULL COMMENT '密码,需要加密',
`created` datetime DEFAULT NULL,
`updated` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `mobile` (`mobile`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户表';

CREATE TABLE `tb_user_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) NOT NULL COMMENT '用户id',
`nick_name` varchar(50) DEFAULT NULL COMMENT '昵称',
`logo` varchar(100) DEFAULT NULL COMMENT '用户头像',
`tags` varchar(50) DEFAULT NULL COMMENT '用户标签:多个用逗号分隔',
`sex` int(1) DEFAULT '3' COMMENT '性别,1-男,2-女,3-未知',
`age` int(11) DEFAULT NULL COMMENT '用户年龄',
`edu` varchar(20) DEFAULT NULL COMMENT '学历',
`city` varchar(20) DEFAULT NULL COMMENT '居住城市',
`birthday` varchar(20) DEFAULT NULL COMMENT '生日',
`cover_pic` varchar(50) DEFAULT NULL COMMENT '封面图片',
`industry` varchar(20) DEFAULT NULL COMMENT '行业',
`income` varchar(20) DEFAULT NULL COMMENT '收入',
`marriage` varchar(20) DEFAULT NULL COMMENT '婚姻状态',
`created` datetime DEFAULT NULL,
`updated` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息表';


5.4、实体类

User


@Data
@AllArgsConstructor //满参构造方法
@NoArgsConstructor //无参构造方法
public class User extends BasePojo {

private Long id;
private String mobile;
private String password;

//环信用户信息
private String hxUser;
private String hxPassword;
}


6、短信验证码

6.1、阿里云短信服务

【探花交友】注册登录需求分析_毕设_02

官方网站:短信服务_企业短信营销推广_验证码通知-阿里云

6.1.1、申请签名与模板

使用阿里云短信服务非常简单,仅需要简单的申请和认证即可

阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台

【探花交友】注册登录需求分析_java_03

说明:申请签名时,个人用户只能申请一个并且签名的名称必须为“ABC商城”,否则审核不通过。

申请模板:

【探花交友】注册登录需求分析_spring_04

审核时间需要1~2小时,请耐心等待~

6.1.2、示例代码

文档:SendSms - 发送短信 - 短信服务 - 阿里云:

导入依赖:


<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
<version>2.0.1</version>
</dependency>


package com.tanhua.sso.service;

import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.dysmsapi20170525.models.SendSmsResponseBody;
import com.aliyun.teaopenapi.models.Config;

public class SendSms {

/**
* 使用AK&SK初始化账号Client
* @param accessKeyId
* @param accessKeySecret
* @return Client
* @throws Exception
*/
public static com.aliyun.dysmsapi20170525.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
Config config = new Config()
// 您的AccessKey ID
.setAccessKeyId(accessKeyId)
// 您的AccessKey Secret
.setAccessKeySecret(accessKeySecret)
.setEndpoint("dysmsapi.aliyuncs.com");
// 访问的域名
return new com.aliyun.dysmsapi20170525.Client(config);
}

public static void main(String[] args_) throws Exception {
java.util.List<String> args = java.util.Arrays.asList(args_);
com.aliyun.dysmsapi20170525.Client client = SendSms
.createClient("**********", "**********");

SendSmsRequest sendSmsRequest = new SendSmsRequest()
.setPhoneNumbers( "158****7944") //目标手机号
.setSignName("ABC商城") //签名名称
.setTemplateCode("SMS_204756062") //短信模板code
.setTemplateParam("{\"code\":\"1111\"}"); //模板中变量替换
SendSmsResponse sendSmsResponse = client.sendSms(sendSmsRequest);

SendSmsResponseBody body = sendSmsResponse.getBody();

// code = OK 代表成功
System.out.println(body.getCode() + " " + body.getMessage());
}

}


3.6.1.4、实现发送短信方法

配置文件:aliyun.properties


aliyun.sms.accessKeyId = ***********
aliyun.sms.accessKeySecret = ***********
aliyun.sms.domain= dysmsapi.aliyuncs.com
aliyun.sms.signName= ABC商城
aliyun.sms.templateCode= SMS_204756062


需要注意中文编码问题:

【探花交友】注册登录需求分析_毕设_05

读取配置:


package com.tanhua.sso.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@PropertySource("classpath:aliyun.properties")
@ConfigurationProperties(prefix = "aliyun.sms")
@Data
public class AliyunSMSConfig {

private String accessKeyId;
private String accessKeySecret;
private String domain;
private String signName;
private String templateCode;

}


代码实现:

package com.tanhua.sso.service;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.dysmsapi20170525.models.SendSmsResponseBody;
import com.aliyun.teaopenapi.models.Config;
import com.tanhua.sso.config.AliyunSMSConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class SmsService {

@Autowired
private AliyunSMSConfig aliyunSMSConfig;

/**
* 发送短信验证码
*
* @param mobile
* @return
*/
public String sendSms(String mobile) {
//随机生成6位数字验证码
String code = RandomUtil.randomNumbers(6);
try {
Config config = new Config()
.setAccessKeyId(this.aliyunSMSConfig.getAccessKeyId())
.setAccessKeySecret(this.aliyunSMSConfig.getAccessKeySecret())
.setEndpoint(this.aliyunSMSConfig.getDomain());

Client client = new Client(config);
SendSmsRequest sendSmsRequest = new SendSmsRequest()
.setPhoneNumbers(mobile)//目标手机号
.setSignName(this.aliyunSMSConfig.getSignName()) //签名名称
.setTemplateCode(this.aliyunSMSConfig.getTemplateCode()) //短信模板code
.setTemplateParam("{\"code\":\"" + code + "\"}"); //模板中变量替换
SendSmsResponse sendSmsResponse = client.sendSms(sendSmsRequest);
SendSmsResponseBody body = sendSmsResponse.getBody();
if (StrUtil.equals("OK", body.getCode())) {
return code;
}
} catch (Exception e) {
log.error("发送短信验证码失败!" + mobile, e);
}
return null;
}
}

6.2、模板组件

企业开发中,往往将常见工具类封装抽取,以简洁便利的方式供其他工程模块使用。而SpringBoot的自动装配机制可以方便的实现组件抽取。SpringBoot执行流程如下

  1. 扫描依赖模块中META-INF/spring.factories
  2. 执行装配类中方法
  3. 对象存入容器中
  4. 核心工程注入对象,调用方法使用

6.2.1、配置类

tanhua-autoconfig创建配置信息类


@Data
@ConfigurationProperties(prefix = "tanhua.sms")
public class SmsProperties {
private String signName;
private String templateCode;
private String accessKey;
private String secret;
}


6.2.2、发送短信模板对象

tanhua-autoconfig创建模板对象对象发送信息

package com.tanhua.autoconfig.template;

import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.dysmsapi20170525.models.SendSmsResponseBody;
import com.aliyun.teaopenapi.models.Config;
import com.tanhua.autoconfig.properties.SmsProperties;

public class SmsTemplate {

private SmsProperties properties;

public SmsTemplate(SmsProperties properties) {
this.properties = properties;
}

public void sendSms(String mobile,String code) {

try {
//配置阿里云
Config config = new Config()
// 您的AccessKey ID
.setAccessKeyId(properties.getAccessKey())
// 您的AccessKey Secret
.setAccessKeySecret(properties.getSecret());
// 访问的域名
config.endpoint = "dysmsapi.aliyuncs.com";

com.aliyun.dysmsapi20170525.Client client = new com.aliyun.dysmsapi20170525.Client(config);

SendSmsRequest sendSmsRequest = new SendSmsRequest()
.setPhoneNumbers(mobile)
.setSignName(properties.getSignName())
.setTemplateCode(properties.getTemplateCode())
.setTemplateParam("{\"code\":\""+code+"\"}");
// 复制代码运行请自行打印 API 的返回值
SendSmsResponse response = client.sendSms(sendSmsRequest);

SendSmsResponseBody body = response.getBody();

System.out.println(body.getMessage());

}catch (Exception e) {
e.printStackTrace();
}

}

}

6.2.3、自动装配类

tanhua-autoconfig创建自动装配的配置类


package com.tanhua.autoconfig;


import com.tanhua.autoconfig.properties.*;
import com.tanhua.autoconfig.template.*;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

@EnableConfigurationProperties({
SmsProperties.class
})
public class TanhuaAutoConfiguration {

@Bean
public SmsTemplate smsTemplate(SmsProperties properties) {
return new SmsTemplate(properties);
}
}


6.2.4、自动装配配置

根据自动装配原则,在tanhua-autoconfig工程创建 /META-INF/spring.factories文件


org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.tanhua.autoconfig.TanhuaAutoConfiguration


6.2.5、测试

tanhua-app-server工程加入短信配置


tanhua: sms:   signName: 物流云商   templateCode: SMS_106590012   accessKey: LTAI4GKgob9vZ53k2SZdyAC7   secret: LHLBvXmILRoyw0niRSBuXBZewQ30la


编写单元测试类


@RunWith(SpringRunner.class)
@SpringBootTest(classes = AppServerApplication.class)
public class SmsTemplateTest {

//注入
@Autowired
private SmsTemplate smsTemplate;

//测试
@Test
public void testSendSms() {
smsTemplate.sendSms("18618412321","4567");
}
}


3.6.2、SSO短信接口服务

3.6.2.1、mock接口

地址:YApi-高效、易用、功能强大的可视化接口管理平台

【探花交友】注册登录需求分析_spring_06

3.6.2.2、编写接口服务

编写ErrorResult,ErrorResult对象是与前端约定好的结构,如果发生错误需要返回该对象,如果未发生错误响应200即可。


package com.tanhua.sso.vo;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class ErrorResult {

private String errCode;
private String errMessage;
}

SmsController:

package com.tanhua.sso.controller;

import com.tanhua.sso.service.SmsService;
import com.tanhua.sso.vo.ErrorResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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;

import java.util.Map;

@RestController
@RequestMapping("user")
@Slf4j
public class SmsController {

@Autowired
private SmsService smsService;

/**
* 发送短信验证码接口
*
* @param param
* @return
*/
@PostMapping("login")
public ResponseEntity<ErrorResult> sendCheckCode(@RequestBody Map<String, String> param) {
ErrorResult errorResult = null;
String phone = param.get("phone");
try {
errorResult = this.smsService.sendCheckCode(phone);
if (null == errorResult) {
return ResponseEntity.ok(null);
}
} catch (Exception e) {
log.error("发送短信验证码失败~ phone = " + phone, e);
errorResult = ErrorResult.builder().errCode("000002").errMessage("短信验证码发送失败!").build();
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResult);
}

}


SmsService:

package com.tanhua.sso.service;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.dysmsapi20170525.models.SendSmsResponseBody;
import com.aliyun.teaopenapi.models.Config;
import com.tanhua.sso.config.AliyunSMSConfig;
import com.tanhua.sso.vo.ErrorResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;

@Service
@Slf4j
public class SmsService {

@Autowired
private AliyunSMSConfig aliyunSMSConfig;

@Autowired
private RedisTemplate<String, String> redisTemplate;

/**
* 发送短信验证码
*
* @param mobile
* @return
*/
public String sendSms(String mobile) {
//随机生成6位数字验证码
String code = RandomUtil.randomNumbers(6);
try {
Config config = new Config()
.setAccessKeyId(this.aliyunSMSConfig.getAccessKeyId())
.setAccessKeySecret(this.aliyunSMSConfig.getAccessKeySecret())
.setEndpoint(this.aliyunSMSConfig.getDomain());

Client client = new Client(config);
SendSmsRequest sendSmsRequest = new SendSmsRequest()
.setPhoneNumbers(mobile)//目标手机号
.setSignName(this.aliyunSMSConfig.getSignName()) //签名名称
.setTemplateCode(this.aliyunSMSConfig.getTemplateCode()) //短信模板code
.setTemplateParam("{\"code\":\"" + code + "\"}"); //模板中变量替换
SendSmsResponse sendSmsResponse = client.sendSms(sendSmsRequest);
SendSmsResponseBody body = sendSmsResponse.getBody();
if (StrUtil.equals("OK", body.getCode())) {
return code;
}
} catch (Exception e) {
log.error("发送短信验证码失败!" + mobile, e);
}
return null;
}

/**
* 发送短信验证码
* 实现:发送完成短信验证码后,需要将验证码保存到redis中
* @param phone
* @return
*/
public ErrorResult sendCheckCode(String phone) {
String redisKey = "CHECK_CODE_" + phone;

//先判断该手机号发送的验证码是否还未失效
if(this.redisTemplate.hasKey(redisKey)){
String msg = "上一次发送的验证码还未失效!";
return ErrorResult.builder().errCode("000001").errMessage(msg).build();
}

String code = this.sendSms(phone);
if(StrUtil.isEmpty(code)){
String msg = "发送短信验证码失败!";
return ErrorResult.builder().errCode("000000").errMessage(msg).build();
}

//短信发送成功,将验证码保存到redis中,有效期为5分钟
this.redisTemplate.opsForValue().set(redisKey, code, Duration.ofMinutes(5));

return null;
}
}

举报

相关推荐

0 条评论