一:编写注册数据校验接口
1.新建注册实体类对象
@Data
public class UserRegistVO {
/**
* 用户名
*/
@NotEmpty(message="用户名必须提交")
@Length(min = 6,max = 18,message="用户名必须是6到18位字符")
private String userName;
/**
* 密码
*/
@Length(min = 6,max = 18,message="密码必须是6到18位字符")
private String password;
/**
* 手机号
*/
@NotEmpty(message="手机号必须填写")
@Pattern(regexp = "^[1]([3-9])[0-9]{9}$" , message = "手机号码格式有误")
private String phone;
/**
* 验证码
*/
@NotEmpty(message="验证码必须填写")
private String code;
}
2.编写Controller方法,实现用户注册的校验功能
/**
* 用户注册
* @return
*/
@PostMapping("/regist")
public String register(@Validated UserRegistVO vo, BindingResult result, RedirectAttributes redirectAttributes){
if(result.hasErrors()){
Map<String, String> errors = result.getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField,FieldError::getDefaultMessage));
redirectAttributes.addFlashAttribute("errors",errors);
//request method post not supported
//用户注册->/regist----->转发到reg.html,路径映射默认都是get方式访问
//校验出错转发到注册页
return "redirect:http://127.0.0.1:20000/reg.html";
}
//注册成功,回到登录首页,调用远程服务进行注册
//todo
//本服务的话,可以不需要加ip和端口
return "redirect:/login.html";
}
- @Validated可以将实体类返回的错误信息进行校验
- BindingResult 用来接收返回的错误信息
- 然后通过model将错误信息返回到前台
- FieldError::getField是stream表达式,等于 fieldError->fieldError.getField
- redirectAttributes:模拟重定向视图,并且携带参数
二:注册功能实现
1.注册之前,先校验验证码
//1.校验验证码
String code = vo.getCode();
String s = stringRedisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());
if(!StringUtils.isEmpty(s)){
if(code.equals(s.split("_")[0])){
//校验完成以后删除验证码
stringRedisTemplate.delete(AuthServerConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());
//验证码校验通过,真正注册
} else {
//验证码不存在的话,就说明过期了
Map<String, String> errors =new HashMap<>();
errors.put("code","验证码错误");
redirectAttributes.addFlashAttribute("errors",errors);
return "redirect:http://127.0.0.1:20000/reg.html";
}
} else {
//验证码不存在的话,就说明过期了
Map<String, String> errors =new HashMap<>();
errors.put("code","验证码错误");
redirectAttributes.addFlashAttribute("errors",errors);
return "redirect:http://127.0.0.1:20000/reg.html";
}
2.编写远程注册接口
1)会员服务controller编写注册功能
@Data
public class MemberRegistVO {
/**
* 用户名
*/
private String userName;
/**
* 密码
*/
private String password;
/**
* 手机号
*/
private String phone;
}
/**
* 会员注册功能
* @return
*/
@PostMapping("/regist")
public R regist( @RequestBody MemberRegistVO vo){
try {
memberService.regist(vo);
} catch (PhoneExistException e) {
return R.error(BizCodeEnume.PHONE_EXIST_EXCEPTION.getCode(),BizCodeEnume.PHONE_EXIST_EXCEPTION.getMsg());
} catch (UserNameExistException e){
return R.error(BizCodeEnume.USER_EXIST_EXCEPTION.getCode(),BizCodeEnume.USER_EXIST_EXCEPTION.getMsg());
}
return R.ok();
}
2)校验用户名和手机号的唯一性
自定义异常:用户名存在异常和手机号存在异常
public class UserNameExistException extends RuntimeException {
public UserNameExistException() {
super("用户名存在异常");
}
}
public class PhoneExistException extends RuntimeException{
public PhoneExistException() {
super("手机号存在异常");
}
}
去数据库查询,如果已经保存用户名或者手机号,直接将异常抛出去
/**
* 校验手机号唯一性
* @param phone
* @throws PhoneExistException
*/
@Override
public void checkPhoneUnique(String phone) throws PhoneExistException{
MemberDao memberDao = this.baseMapper;
QueryWrapper<MemberEntity> wrapper = new QueryWrapper<>();
wrapper.eq("mobile",phone);
Integer mobileCount = memberDao.selectCount(wrapper);
if(mobileCount>0){
throw new PhoneExistException();
}
}
/**
* 校验用户名唯一性
* @param username
* @throws UserNameExistException
*/
@Override
public void checkUserNameUnique(String username) throws UserNameExistException{
MemberDao memberDao = this.baseMapper;
QueryWrapper<MemberEntity> wrapper = new QueryWrapper<>();
wrapper.eq("username",username);
Integer userNameCount = memberDao.selectCount(wrapper);
if(userNameCount>0){
throw new UserNameExistException();
}
}
- service的方法都是void,没有返回值,上层业务想要获取异常,就抛出去,然后再controller进行捕获
3.将密码加密存储——MD5
1) MD5-Message Digest algorithm 5,信息摘要算法
• 压缩性:任意长度的数据,算出的MD5值长度都是固定的。
• 容易计算:从原数据计算出MD5值很容易。
• 抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
• 强抗碰撞:想找到两个不同的数据,使它们具有相同的MD5值,是非常困难的。
• 不可逆
2) 加盐
• 通过生成随机数与MD5生成字符串进行组合
• 数据库同时存储MD5值与salt值。验证正确性时使用salt进行MD5即可
3)代码实现
//设置密码,MD5不能直接进行加密存储->需要盐值加密,随机值->BCryptPasswordEncoder
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encode = passwordEncoder.encode(vo.getPassword());
entity.setPassword(encode);
注:使用BCryptPasswordEncoder就不需要在数据库维护salt盐值字段了,其可以在加密生成的代码中,融入盐值,完成校验。
4.验证码校验完成后,远程调用会员注册接口
1)新建MemberFeignService
@FeignClient("gulimail-member")
public interface MemberFeignService {
/**
* 会员注册功能
* @return
*/
@PostMapping("/member/member/regist")
public R regist( @RequestBody UserRegistVO vo);
}
2)接口实现成功
/**
* 用户注册
* @return
*/
@PostMapping("/regist")
public String register(@Validated UserRegistVO vo, BindingResult result, RedirectAttributes redirectAttributes){
if(result.hasErrors()){
Map<String, String> errors = result.getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField,FieldError::getDefaultMessage));
redirectAttributes.addFlashAttribute("errors",errors);
//request method post not supported
//用户注册->/regist----->转发到reg.html,路径映射默认都是get方式访问
//校验出错转发到注册页
return "redirect:http://127.0.0.1:20000/reg.html";
}
//注册成功,回到登录首页,调用远程服务进行注册
//1.校验验证码
String code = vo.getCode();
String s = stringRedisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());
if(!StringUtils.isEmpty(s)){
if(code.equals(s.split("_")[0])){
//校验完成以后删除验证码
stringRedisTemplate.delete(AuthServerConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());
//验证码校验通过,真正注册
try {
R r = memberFeignService.regist(vo);
if(r.getCode() == 0){
//成功
return "redirect:/login.html";
} else {
//失败
Map<String, String> errors =new HashMap<>();
errors.put("msg",r.getData(new TypeReference<String>(){}));
redirectAttributes.addFlashAttribute("errors",errors);
return "redirect:http://127.0.0.1:20000/reg.html";
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
//验证码不存在的话,就说明过期了
Map<String, String> errors =new HashMap<>();
errors.put("code","验证码错误");
redirectAttributes.addFlashAttribute("errors",errors);
return "redirect:http://127.0.0.1:20000/reg.html";
}
} else {
//验证码不存在的话,就说明过期了
Map<String, String> errors =new HashMap<>();
errors.put("code","验证码错误");
redirectAttributes.addFlashAttribute("errors",errors);
return "redirect:http://127.0.0.1:20000/reg.html";
}
//todo
//本服务的话,可以不需要加ip和端口
return "redirect:/login.html";
}
三:登录接口实现
1.编写UserLoginVo
@Data
public class UserLoginVO {
private String loginAccount;
private String password;
}
2.编写会员服务controller
/**
* 会员登录功能
* @return
*/
@PostMapping("/login")
public R login( @RequestBody MemberLoginVO vo){
MemberEntity entity = memberService.login(vo);
if(entity!=null){
return R.ok();
} else {
return R.error(BizCodeEnume.LOGINACCOUNT_PASSWORD_INVAILD_EXCEPTION.getCode(),BizCodeEnume.LOGINACCOUNT_PASSWORD_INVAILD_EXCEPTION.getMsg());
}
}
3.编写会员服务service
@Override
public MemberEntity login(MemberLoginVO vo) {
String loginAccount = vo.getLoginAccount();
String password = vo.getPassword();
//1.去数据库查询
MemberDao memberDao = this.baseMapper;
QueryWrapper<MemberEntity> wrapper = new QueryWrapper<>();
wrapper.eq("username",loginAccount).or().eq("mobile",loginAccount);
MemberEntity memberEntity = memberDao.selectOne(wrapper);
if(memberEntity == null){
//登陆失败
return null;
} else {
//1.获取数据库存储的密码
String passwordDb = memberEntity.getPassword();
//2.和前台传过来的密码进行对比
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
boolean matches = passwordEncoder.matches(password, passwordDb);
if(matches){
return memberEntity;
} else {
return null;
}
}
}
4.编写远程调用接口
@FeignClient("gulimail-member")
public interface MemberFeignService {
/**
* 会员注册功能
* @return
*/
@PostMapping("/member/member/regist")
R regist( @RequestBody UserRegistVO vo);
/**
* 会员登录功能
* @return
*/
@PostMapping("/member/member/login")
R login( @RequestBody UserLoginVO vo);
}
5.auth模块调用会员模块
@PostMapping("/login")
public String login(UserLoginVO vo){
//远程登录
R r = memberFeignService.login(vo);
if(r.getCode() == 0){
//成功就去首页
return "redirect:http://127.0.0.1:10000";
} else {
//失败就去登录页
return "redirect:http://127.0.0.1:20000/login.html";
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/84096.html