image.png
image.png
image.png
image.png
image.png
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.0.0</version>
</dependency>
生成随机数,我发现生成5位随机数时,如果开头为0,发送的短信只有4位,这里开头加个1,保证短信的正确性
public String authcode_get(String u_phone) {
String authcode = "1" + RandomStringUtils.randomNumeric(5);
redisUtils.set(u_phone, authcode);
return
}
@RequestMapping("/sendSms")
public String sendSms(String mobile) {
// 生成随机验证码并存入缓存中
String code = generateCode();
redisService.set(mobile, code, 300L); // 有效时间5分钟,可根据需求自定义
// 调用短信服务接口发送验证码到指定手机号
boolean result = smsService.sendSms(mobile, code);
if (result) {
return "发送短信验证码成功";
} else {
return "发送短信验证码失败";
}
}
@RequestMapping("/register")
public String register(String mobile, String code) {
// 从缓存中取出短信验证码
String redisCode = redisService.get(mobile);
// 对比短信验证码,如果相同则注册成功,否则注册失败
if (code.equals(redisCode)) {
// 保存用户信息到数据库中
User user = new User();
user.setMobile(mobile);
userRepository.save(user);
return "注册成功";
} else {
return "注册失败,验证码错误";
}
}
@RequestMapping("/register")
public String register(String mobile, String code) {
String redisCode = redisService.get(mobile);
if (code.equals(redisCode)) {
User user = new User();
user.setMobile(mobile);
userRepository.save(user);
return "success"
} else {
}
}
编写登录
@RequestMapping("/login")
public String login(String mobile, String code) {
String redisCode = redisService.get(mobile)
if (code.equals(redisCode) {
return "success"
}
}
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.2.2</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-sms</artifactId>
<version>1.1.0</version>
</dependency>
创建阿里云短信服务所需的AccessKey ID和AccessKey Secret,可以在阿里云官网控制台获取。
aliyun:
accessKeyId: accessKeyId # 阿里云短信服务AccessKey ID
accessKeySecret: accessKeySecret # 阿里云短信服务AccessKey Secret
sms:
signName: 短信签名 # 阿里云短信签名,需要在官网申请
templateCode: 验证码模板ID # 阿里云短信模板ID,需要在官网申请
expireTime: 300 # 短信验证码有效期,单位秒
public interface SmsService {
// 发送短信验证码
boolean sendSms(String mobile)
}
@Service
public class SmsServiceImpl implements SmsService {
@Autowired
private AliyunSmsConfig aliyunSmsConfig;
@Override
public boolean sendSms(String mobile, String code) {
// 创建短信发送请求对象
Config config = new Config()
.setAccessKeyId(aliyunSmsConfig.getAccessKeyId())
.setAccessKeySecret(aliyunSmsConfig.getAccessKeySecret());
Com.Alibaba.Cloudapi101083.Client client = new Com.Alibaba.Cloudapi101083.Client(config);
SendSmsRequest request = new SendSmsRequest()
.setSignName(aliyunSmsConfig.getSignName()) // 设置短信签名
.setTemplateCode(aliyunSmsConfig.getTemplateCode()) // 设置短信模板
.setPhoneNumbers(mobile) // 设置接收短信的手机号码
.setTemplateParam("{\"code\":\"" + code + "\"}"); // 设置短信模板参数,这里只有一个"code"参数,其值为生成的短信验证码
// 调用阿里云短信API发送短信
try {
SendSmsResponse response = client.sendSms(request);
if (response.body.getCode().equals("OK")) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
@Service
public class SmsServiceImpl implements SmsService {
@Autowired
private AliyunProperties aliyunProperties;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private final static String SMS_CODE_PREFIX = "sms:code:";
@Override
public boolean sendSms(String mobile) {
// 生成6位数的随机验证码
String code = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
try {
// 创建调用Aliyun短信服务所需的环境信息
Config config = new Config()
.setAccessKeyId(aliyunProperties.getAccessKeyId())
.setAccessKeySecret(aliyunProperties.getAccessKeySecret());
// 创建发送短信请求对象
Com.Alibaba.Cloudapi101083.Client client = new Com.Alibaba.Cloudapi101083.Client(config);
SendSmsRequest request = new SendSmsRequest()
.setSignName(aliyunProperties.getSms().getSignName())
.setTemplateCode(aliyunProperties.getSms().getTemplateCode())
.setPhoneNumbers(mobile)
.setTemplateParam("{\"code\":\"" + code + "\"}");
// 调用短信服务发送验证码
SendSmsResponse response = client.sendSms(request);
if (response.body.getCode().equals("OK")) {
// 将验证码存入Redis缓存中
redisTemplate.opsForValue().set(SMS_CODE_PREFIX + mobile, code, aliyunProperties.getSms().getExpireTime(), TimeUnit.SECONDS);
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
SmsClient
类beanprivate static final Logger logger = LoggerFactory.getLogger(SmsService.class);
SendSmsResponse res = smsClient.SendSms(req);
// 发送短信验证码成功则将验证码保存到redis缓存中
redisTemplate.opsForValue().set("loginVerifyCode:"+phoneNum, verifyCode, 10, TimeUnit.MINUTES);
image.png
@Resource
private SmsService smsService;
@RequestMapping(value="sendLoginVerifyCode", method = RequestMethod.POST)
@ApiOperation(value = "sendLoginVerifyCode", notes = "发送登录短信验证码")
@ApiImplicitParam(name="paramMap", value = "入参Map", required = true, paramType = "body", dataTypeClass=HashMap.class)
public RespBean<Map<String, Object>> sendLoginVerifyCode(@RequestBody Map<String, String> paramMap) {
String phoneNumber = paramMap.get("phoneNumber");
SendSmsResponse response = smsService.sendLoginVeryCodeMessage(phoneNumber);
SendStatus[] statuses = response.getSendStatusSet();
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("code", statuses[0].getCode());
resultMap.put("message", statuses[0].getMessage());
resultMap.put("phoneNumber", statuses[0].getPhoneNumber());
resultMap.put("fee", statuses[0].getFee());
RespBean<Map<String, Object>> respBean = new RespBean<>(200, "success");
respBean.setData(resultMap);
return respBean;
}
WebSecurityConfig
中放开对这个接口的拦截
@Override
protected void configure(HttpSecurity http) throws Exception {
// 配置跨域
http.cors().configurationSource(corsConfigurationSource());
// 禁用spring security框架的退出登录,使用自定义退出登录
http.logout().disable();
http.authorizeRequests()
.antMatchers("/user/reg").anonymous()
.antMatchers("/sendLoginVerifyCode").anonymous()
//......省略其他代码
}
// UserMapper.java
@Repository
public interface UserMapper {
UserDTO loadUserByPhoneNum(@Param("phoneNum") Long phoneNum);
}
// UserMapper.xml
<select id="loadUserByPhoneNum" resultType="org.wxapp.pojo.dto.UserDTO">
SELECT id, username, nickname, password, phoneNum, .. , updateTime
FROM `user`
WHERE phoneNum = #{phoneNum, jdbcType=BIGINT}
</select>
UserService
类中完成用户注册逻辑
@Override
public int registerUser(UserDTO user) {
// 判断用户是否重复注册
UserDTO userDTO = userMapper.loadUserByUsername(user.getUsername()):
if (userDTO != null) {
return 1;
}
// 插入用户,插入之前先对密码进行加密
user.setPassword(passwordEncoder.encode(user.getPassword()));
user.setEnabled(1); // 用户可用
int result = userMapper.registerUser(user);
// 配置用户的角色,默认都是普通用户
List<Integer> roleIds = Arrays.asList(2);
int i = rolesMapper.setUserRoles(roleIds, user.getId());
boolean b = i == roleIds.size() && result == 1;
}
@RequestMapping(value = "/login_page", method = RequestMethod.GET)
@ApiOperation(value = "loginPage", notes = "尚未登录跳转", produces = "application/json",
consumes = "application/json", response = RespBean.class)
public RespBean loginPage() {
return new RespBean(ResponseStateConstant.UN_AUTHORIZED, "尚未登录,请登录!");
}
@PostMapping("/user/reg")
@ApiOperation(value = "reg", notes = "用户注册", produces = "application/json",
consumes = "application/json", response = RespBean.class)
public RespBean reg(@RequestBody UserDTO user) {
int result = userService.registerUser(user);
if (result == 0) {
//成功
return new RespBean(ResponseStateConstant.SERVER_SUCCESS, "注册成功!");
} else if (result == 1) {
return new RespBean(ResponseStateConstant.DUPLICATE_ERROR, "用户名重复,注册失败!");
} else {
//失败
return new RespBean(ResponseStateConstant.SERVER_ERROR, "注册失败!");
}
}
在security配置类WebSecurityConfig
类中支持匿名访问
仓库地址:https://github.com/webVueBlog/JavaGuideInterview