完成注册功能

This commit is contained in:
lu 2025-01-24 22:06:34 +08:00
parent cc7564b195
commit 67cd04f097
5 changed files with 88 additions and 27 deletions

View File

@ -5,6 +5,7 @@ import com.example.service.AuthorizeService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpSession; import jakarta.servlet.http.HttpSession;
import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Length;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -14,17 +15,32 @@ import org.springframework.web.bind.annotation.*;
public class AuthorizeController { public class AuthorizeController {
private final String EMAIL_REGEX = "^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"; private final String EMAIL_REGEX = "^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
private final String USERNAME_REGEX = "^[a-zA-Z0-9\\u4e00-\\u9fa5]+$";
@Resource @Resource
AuthorizeService service; AuthorizeService service;
@PostMapping("/valid-email") @PostMapping("/valid-email")
public RestBean<String> validEmail(@Pattern(regexp = EMAIL_REGEX) @RequestParam("email") String email, public RestBean<String> validEmail(@Pattern(regexp = EMAIL_REGEX) @RequestParam("email") String email,
HttpSession session) { HttpSession session) {
if (service.sendValidateEmail(email,session.getId())) { String s = service.sendValidateEmail(email, session.getId());
if (s == null) {
return RestBean.success("邮件已发送,请注意查收"); return RestBean.success("邮件已发送,请注意查收");
}else{ }else{
return RestBean.failure(400,"邮件发送失败请检查邮箱地址是否存在,如果还是失败请联系管理员"); return RestBean.failure(400,s);
}
}
@PostMapping("/register")
public RestBean<String> registerUser(@Pattern(regexp = USERNAME_REGEX) @Length(min = 2, max = 8) @RequestParam("username") String username,
@Length(min = 6,max = 16) @RequestParam("password") String password,
@Pattern(regexp = EMAIL_REGEX) @RequestParam("email") String email,
@Length(min = 6, max = 6) @RequestParam("code") String code,
HttpSession session) {
String s = service.validateAndRegister(username, password, email, code, session.getId());
if(s == null){
return RestBean.success("注册成功");
}else{
return RestBean.failure(400,s);
} }
} }
} }

View File

@ -1,6 +1,7 @@
package com.example.mapper; package com.example.mapper;
import com.example.entity.Account; import com.example.entity.Account;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Select;
@ -8,4 +9,7 @@ import org.apache.ibatis.annotations.Select;
public interface UserMapper { public interface UserMapper {
@Select("select * from db_account where username = #{text} or email = #{text}") @Select("select * from db_account where username = #{text} or email = #{text}")
Account findAccountByNameOrEmail(String text); Account findAccountByNameOrEmail(String text);
}
@Insert("insert into db_account (email, username, password) values (#{email}, #{username}, #{password})")
int createAccount(String email, String username, String password);
}

View File

@ -1,7 +1,9 @@
package com.example.service; package com.example.service;
import com.example.entity.Account;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
public interface AuthorizeService extends UserDetailsService { public interface AuthorizeService extends UserDetailsService {
boolean sendValidateEmail(String email,String sessionId); String sendValidateEmail(String email,String sessionId);
String validateAndRegister(String username, String password, String email, String code, String sessionID);
} }

View File

@ -12,9 +12,9 @@ import org.springframework.mail.SimpleMailMessage;
import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.sql.Time;
import java.util.Optional; import java.util.Optional;
import java.util.Random; import java.util.Random;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -34,6 +34,8 @@ public class AuthorizeServiceImpl implements AuthorizeService {
@Resource @Resource
StringRedisTemplate template; StringRedisTemplate template;
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
@Override @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if(username == null){ if(username == null){
@ -49,22 +51,24 @@ public class AuthorizeServiceImpl implements AuthorizeService {
.roles("user") .roles("user")
.build(); .build();
} }
/**
* 1.先生成对应的验证码
* 2.把邮箱和对应的验证码直接放到Redis里面过期时间3分钟如果此时重新要求发送邮件
* 当剩余时间小于2分钟时允许重新发送
* 3.发送验证码到指定邮箱
* 4.如果发送失败把redis里面的刚刚插入的删除
* 5.用户在注册时再从redis里面取出对应键值对然后看验证码是否一致
*/
@Override @Override
public boolean sendValidateEmail(String email, String sessionId) { public String sendValidateEmail(String email, String sessionId) {
/**
* 1.先生成对应的验证码
* 2.把邮箱和对应的验证码直接放到Redis里面过期时间3分钟如果此时重新要求发送邮件
* 当剩余时间小于2分钟时允许重新发送
* 3.发送验证码到指定邮箱
* 4.如果发送失败把redis里面的刚刚插入的删除
* 5.用户在注册时再从redis里面取出对应键值对然后看验证码是否一致
*/
String key = "email" + sessionId + ":" + email; String key = "email" + sessionId + ":" + email;
if(Boolean.TRUE.equals(template.hasKey(key))){ if(Boolean.TRUE.equals(template.hasKey(key))){
Long expire = Optional.ofNullable(template.getExpire(key, TimeUnit.SECONDS)).orElse(0L); Long expire = Optional.ofNullable(template.getExpire(key, TimeUnit.SECONDS)).orElse(0L);
if(expire > 120) if(expire > 120)
return false; return "请求频繁,请稍后再试";
}
if(mapper.findAccountByNameOrEmail(email) != null){
return "此邮箱以被注册";
} }
Random random = new Random(); Random random = new Random();
int code = random.nextInt(900000) + 100000; int code = random.nextInt(900000) + 100000;
@ -76,10 +80,31 @@ public class AuthorizeServiceImpl implements AuthorizeService {
try{ try{
mailSender.send(message); mailSender.send(message);
template.opsForValue().set(key, String.valueOf(code), 3, TimeUnit.MINUTES); template.opsForValue().set(key, String.valueOf(code), 3, TimeUnit.MINUTES);
return true; return null;
} catch (MailException e){ } catch (MailException e){
e.printStackTrace(); e.printStackTrace();
return false; return "邮件发送失败,请检查邮箱地址是否有效";
}
}
@Override
public String validateAndRegister(String username, String password, String email, String code, String sessionId) {
String key = "email" + sessionId + ":" + email;
if(Boolean.TRUE.equals(template.hasKey(key))){
String s = template.opsForValue().get(key);
if(s == null)return "验证码失效,请重新获取";
if(s.equals(code)){
password = encoder.encode(password);
if (mapper.createAccount(email, username,password) > 0) {
return null;
}else{
return "内部错误,请联系管理员";
}
}else {
return "验证码错误,请检查后提交";
}
}else{
return "请先获取验证码验证邮箱";
} }
} }
} }

View File

@ -54,6 +54,8 @@ const rules ={
const isEmailValid = ref(false) const isEmailValid = ref(false)
const formRef = ref() const formRef = ref()
const coldTime = ref(0)
const onValidate = (prop, isValid) => { const onValidate = (prop, isValid) => {
if(prop === 'email') if(prop === 'email')
isEmailValid.value = isValid isEmailValid.value = isValid
@ -61,7 +63,15 @@ const onValidate = (prop, isValid) => {
const register = () => { const register = () => {
formRef.value.validate((isValid) => { formRef.value.validate((isValid) => {
if(isValid){ if(isValid){
post('/api/auth/register',{
username: form.username,
password: form.password,
email: form.email,
code: form.code
}, (message) => {
ElMessage.success(message)
router.push('/')
})
}else{ }else{
ElMessage.warning('请完整填写注册信息!') ElMessage.warning('请完整填写注册信息!')
} }
@ -73,8 +83,9 @@ const validateEmail = () => {
email: form.email email: form.email
}, (message) => { }, (message) => {
ElMessage.success(message) ElMessage.success(message)
} coldTime.value = 60
) setInterval( () => coldTime.value--, 1000)
})
} }
</script> </script>
@ -88,21 +99,21 @@ const validateEmail = () => {
<div style="margin-top: 50px"> <div style="margin-top: 50px">
<el-form :model="form" :rules="rules" @validate="onValidate" ref="formRef"> <el-form :model="form" :rules="rules" @validate="onValidate" ref="formRef">
<el-form-item prop="username"> <el-form-item prop="username">
<el-input v-model="form.username" type="text" placeholder="用户名"> <el-input v-model="form.username" :maxlength="8" type="text" placeholder="用户名">
<template #prefix> <template #prefix>
<el-icon><User /></el-icon> <el-icon><User /></el-icon>
</template> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
<el-input v-model="form.password" type="password" placeholder="密码"> <el-input v-model="form.password" :maxlength="16" type="password" placeholder="密码">
<template #prefix> <template #prefix>
<el-icon><Lock /></el-icon> <el-icon><Lock /></el-icon>
</template> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password_repeat"> <el-form-item prop="password_repeat">
<el-input v-model="form.password_repeat" type="password" placeholder="重复密码"> <el-input v-model="form.password_repeat" :maxlength="16" type="password" placeholder="重复密码">
<template #prefix> <template #prefix>
<el-icon><Lock /></el-icon> <el-icon><Lock /></el-icon>
</template> </template>
@ -118,14 +129,17 @@ const validateEmail = () => {
<el-form-item prop="code"> <el-form-item prop="code">
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="18"> <el-col :span="18">
<el-input v-model="form.code" type="text" placeholder="请输入验证码"> <el-input v-model="form.code" :maxlength="6" type="text" placeholder="请输入验证码">
<template #prefix> <template #prefix>
<el-icon><EditPen /></el-icon> <el-icon><EditPen /></el-icon>
</template> </template>
</el-input> </el-input>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-button style="width: 100%" @click="validateEmail" type="success" :disabled="!isEmailValid">获取验证码</el-button> <el-button style="width: 100%" @click="validateEmail" type="success"
:disabled="!isEmailValid || coldTime > 0">
{{coldTime > 0 ? '请等待' + coldTime + '秒' : '获取验证码'}}
</el-button>
</el-col> </el-col>
</el-row> </el-row>
</el-form-item> </el-form-item>