注册接口实现

This commit is contained in:
Amadeus 2024-05-17 20:47:32 +08:00
parent 89fdab1864
commit 0b24b0d6d3
7 changed files with 99 additions and 8 deletions

View File

@ -79,6 +79,10 @@
<artifactId>spring-security-test</artifactId> <artifactId>spring-security-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -43,7 +43,7 @@ public class SecurityConfiguration {
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http return http
.authorizeHttpRequests(conf -> conf .authorizeHttpRequests(conf -> conf
.requestMatchers("/api/auth/**").permitAll() .requestMatchers("/api/auth/**" , "/error").permitAll()
.anyRequest().authenticated() .anyRequest().authenticated()
) )
.formLogin(conf -> conf .formLogin(conf -> conf

View File

@ -1,14 +1,19 @@
package com.example.controller; package com.example.controller;
import com.example.entity.RestBean; import com.example.entity.RestBean;
import com.example.entity.vo.request.EmailRegisterVO;
import com.example.service.AccountService; import com.example.service.AccountService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping; import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.RequestMapping; import jakarta.validation.constraints.Email;
import org.springframework.web.bind.annotation.RequestParam; import jakarta.validation.constraints.Pattern;
import org.springframework.web.bind.annotation.RestController; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.function.Supplier;
@Validated
@RestController @RestController
@RequestMapping("/api/auth") @RequestMapping("/api/auth")
public class AuthorizeController { public class AuthorizeController {
@ -16,11 +21,21 @@ public class AuthorizeController {
@Resource @Resource
AccountService service; AccountService service;
@GetMapping("/ask-code") @GetMapping("/ask-code")
public RestBean<Void> askVerifyCode(@RequestParam String email, public RestBean<Void> askVerifyCode(@RequestParam @Email String email,
@RequestParam String type , @RequestParam @Pattern(regexp = "(register|reset)") String type ,
HttpServletRequest request){ HttpServletRequest request){
String message = service.registerEmailVerityCode(type , email , request.getRemoteAddr()); return this.messageHandle(() ->
service.registerEmailVerityCode(type , email , request.getRemoteAddr()));
}
@PostMapping("/register")
public RestBean<Void> register(@RequestBody @Valid EmailRegisterVO vo){
return this.messageHandle(()-> service.registerEmailAccount(vo));
}
private RestBean<Void > messageHandle(Supplier<String> action){
String message = action.get();
return message == null ? RestBean.success() : RestBean.failure(400 , message); return message == null ? RestBean.success() : RestBean.failure(400 , message);
} }
} }

View File

@ -0,0 +1,17 @@
package com.example.controller.exception;
import com.example.entity.RestBean;
import jakarta.validation.ValidationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@Slf4j
@RestControllerAdvice
public class ValidationController {
@ExceptionHandler(ValidationException.class)
public RestBean<Void> validateException(ValidationException exception){
log.warn("Resolve [{}: {}]" , exception.getClass().getName(), exception.getMessage());
return RestBean.failure(400 , "请求参数有误");
}
}

View File

@ -0,0 +1,19 @@
package com.example.entity.vo.request;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
@Data
public class EmailRegisterVO {
@Email
String email;
@Length(max = 6 , min = 6)
String code;
@Pattern(regexp = "^[a-zA-Z0-9\\u4e00-\\u9fa5]+$")
@Length(min = 1 , max = 10)
String username;
@Length(min = 6 , max = 20)
String password;
}

View File

@ -2,10 +2,12 @@ package com.example.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.example.entity.dto.Account; import com.example.entity.dto.Account;
import com.example.entity.vo.request.EmailRegisterVO;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
public interface AccountService extends IService<Account> , UserDetailsService { public interface AccountService extends IService<Account> , UserDetailsService {
public Account findAccountByNameOrEmail(String text); public Account findAccountByNameOrEmail(String text);
String registerEmailVerityCode(String type , String email , String ip); String registerEmailVerityCode(String type , String email , String ip);
String registerEmailAccount(EmailRegisterVO v0);
} }

View File

@ -1,7 +1,9 @@
package com.example.service.impl; package com.example.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.entity.dto.Account; import com.example.entity.dto.Account;
import com.example.entity.vo.request.EmailRegisterVO;
import com.example.mapper.AccountMapper; import com.example.mapper.AccountMapper;
import com.example.service.AccountService; import com.example.service.AccountService;
import com.example.utils.Const; import com.example.utils.Const;
@ -12,8 +14,10 @@ import org.springframework.data.redis.core.StringRedisTemplate;
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.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Random; import java.util.Random;
@ -30,6 +34,9 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper , Account> imp
@Resource @Resource
StringRedisTemplate stringRedisTemplate; StringRedisTemplate stringRedisTemplate;
@Resource
PasswordEncoder encoder;
@Override @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Account account = this.findAccountByNameOrEmail(username); Account account = this.findAccountByNameOrEmail(username);
@ -61,6 +68,26 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper , Account> imp
} }
@Override
public String registerEmailAccount(EmailRegisterVO vo) {
String email = vo.getEmail();
String username = vo.getUsername();
String key = Const.VERIFY_EMAIL_DATA + email;
String code = stringRedisTemplate.opsForValue().get(key);
if (code == null) return "请先获取验证码";
if (!code.equals(vo.getCode())) return "验证码输入错误,请重新输入";
if (this.existsAccountByEmail(email)) return "此电子邮件已被其他用户注册";
if (this.existsAccountByUsername(username)) return "此用户名已被他人注册,请更换一个用户名";
String password = encoder.encode(vo.getPassword());
Account account = new Account(null , username ,password , email , "user" , new Date());
if (this.save(account)) {
stringRedisTemplate.delete(key);
return null;
}else {
return "内部错误,请联系管理员";
}
}
public Account findAccountByNameOrEmail(String text){ public Account findAccountByNameOrEmail(String text){
return this.query() return this.query()
.eq("username",text).or() .eq("username",text).or()
@ -68,6 +95,13 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper , Account> imp
.one(); .one();
} }
private boolean existsAccountByEmail(String email){
return this.baseMapper.exists(Wrappers.<Account>query().eq("email",email));
}
private boolean existsAccountByUsername(String username){
return this.baseMapper.exists(Wrappers.<Account>query().eq("username",username));
}
private boolean verifyLimit(String ip){ private boolean verifyLimit(String ip){
String key = Const.VERIFY_EMAIL_LIMIT + ip; String key = Const.VERIFY_EMAIL_LIMIT + ip;
return utils.limitOnceCheck(key , 60); return utils.limitOnceCheck(key , 60);