From 0b24b0d6d37dc8173a618fb8269cb600aaada13a Mon Sep 17 00:00:00 2001 From: Amadeus Date: Fri, 17 May 2024 20:47:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B3=A8=E5=86=8C=E6=8E=A5=E5=8F=A3=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 4 +++ .../example/config/SecurityConfiguration.java | 2 +- .../controller/AuthorizeController.java | 29 ++++++++++++---- .../exception/ValidationController.java | 17 ++++++++++ .../entity/vo/request/EmailRegisterVO.java | 19 +++++++++++ .../com/example/service/AccountService.java | 2 ++ .../service/impl/AccountServiceImpl.java | 34 +++++++++++++++++++ 7 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/example/controller/exception/ValidationController.java create mode 100644 src/main/java/com/example/entity/vo/request/EmailRegisterVO.java diff --git a/pom.xml b/pom.xml index a694854..4987abd 100644 --- a/pom.xml +++ b/pom.xml @@ -79,6 +79,10 @@ spring-security-test test + + org.springframework.boot + spring-boot-starter-validation + diff --git a/src/main/java/com/example/config/SecurityConfiguration.java b/src/main/java/com/example/config/SecurityConfiguration.java index cc8cfb8..d7eb33d 100644 --- a/src/main/java/com/example/config/SecurityConfiguration.java +++ b/src/main/java/com/example/config/SecurityConfiguration.java @@ -43,7 +43,7 @@ public class SecurityConfiguration { public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .authorizeHttpRequests(conf -> conf - .requestMatchers("/api/auth/**").permitAll() + .requestMatchers("/api/auth/**" , "/error").permitAll() .anyRequest().authenticated() ) .formLogin(conf -> conf diff --git a/src/main/java/com/example/controller/AuthorizeController.java b/src/main/java/com/example/controller/AuthorizeController.java index 81c29f8..afff70d 100644 --- a/src/main/java/com/example/controller/AuthorizeController.java +++ b/src/main/java/com/example/controller/AuthorizeController.java @@ -1,14 +1,19 @@ package com.example.controller; import com.example.entity.RestBean; +import com.example.entity.vo.request.EmailRegisterVO; import com.example.service.AccountService; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.Pattern; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import java.util.function.Supplier; + +@Validated @RestController @RequestMapping("/api/auth") public class AuthorizeController { @@ -16,11 +21,21 @@ public class AuthorizeController { @Resource AccountService service; @GetMapping("/ask-code") - public RestBean askVerifyCode(@RequestParam String email, - @RequestParam String type , + public RestBean askVerifyCode(@RequestParam @Email String email, + @RequestParam @Pattern(regexp = "(register|reset)") String type , HttpServletRequest request){ - String message = service.registerEmailVerityCode(type , email , request.getRemoteAddr()); + return this.messageHandle(() -> + service.registerEmailVerityCode(type , email , request.getRemoteAddr())); + } + + @PostMapping("/register") + public RestBean register(@RequestBody @Valid EmailRegisterVO vo){ + return this.messageHandle(()-> service.registerEmailAccount(vo)); + } + private RestBean messageHandle(Supplier action){ + String message = action.get(); return message == null ? RestBean.success() : RestBean.failure(400 , message); } + } diff --git a/src/main/java/com/example/controller/exception/ValidationController.java b/src/main/java/com/example/controller/exception/ValidationController.java new file mode 100644 index 0000000..93a2fdb --- /dev/null +++ b/src/main/java/com/example/controller/exception/ValidationController.java @@ -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 validateException(ValidationException exception){ + log.warn("Resolve [{}: {}]" , exception.getClass().getName(), exception.getMessage()); + return RestBean.failure(400 , "请求参数有误"); + } +} diff --git a/src/main/java/com/example/entity/vo/request/EmailRegisterVO.java b/src/main/java/com/example/entity/vo/request/EmailRegisterVO.java new file mode 100644 index 0000000..b429e53 --- /dev/null +++ b/src/main/java/com/example/entity/vo/request/EmailRegisterVO.java @@ -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; +} diff --git a/src/main/java/com/example/service/AccountService.java b/src/main/java/com/example/service/AccountService.java index 5530672..4aa6e7e 100644 --- a/src/main/java/com/example/service/AccountService.java +++ b/src/main/java/com/example/service/AccountService.java @@ -2,10 +2,12 @@ package com.example.service; import com.baomidou.mybatisplus.extension.service.IService; 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.UserDetailsService; public interface AccountService extends IService , UserDetailsService { public Account findAccountByNameOrEmail(String text); String registerEmailVerityCode(String type , String email , String ip); + String registerEmailAccount(EmailRegisterVO v0); } diff --git a/src/main/java/com/example/service/impl/AccountServiceImpl.java b/src/main/java/com/example/service/impl/AccountServiceImpl.java index 7f96166..a4194d1 100644 --- a/src/main/java/com/example/service/impl/AccountServiceImpl.java +++ b/src/main/java/com/example/service/impl/AccountServiceImpl.java @@ -1,7 +1,9 @@ package com.example.service.impl; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.entity.dto.Account; +import com.example.entity.vo.request.EmailRegisterVO; import com.example.mapper.AccountMapper; import com.example.service.AccountService; 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.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; +import java.util.Date; import java.util.Map; import java.util.Objects; import java.util.Random; @@ -30,6 +34,9 @@ public class AccountServiceImpl extends ServiceImpl imp @Resource StringRedisTemplate stringRedisTemplate; + @Resource + PasswordEncoder encoder; + @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { Account account = this.findAccountByNameOrEmail(username); @@ -61,6 +68,26 @@ public class AccountServiceImpl extends ServiceImpl 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){ return this.query() .eq("username",text).or() @@ -68,6 +95,13 @@ public class AccountServiceImpl extends ServiceImpl imp .one(); } + private boolean existsAccountByEmail(String email){ + return this.baseMapper.exists(Wrappers.query().eq("email",email)); + } + private boolean existsAccountByUsername(String username){ + return this.baseMapper.exists(Wrappers.query().eq("username",username)); + } + private boolean verifyLimit(String ip){ String key = Const.VERIFY_EMAIL_LIMIT + ip; return utils.limitOnceCheck(key , 60);