一.验证码


package com.xunqi.gulimall.auth.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class GulimallWebConfig implements WebMvcConfigurer {
/**·
* 视图映射:发送一个请求,直接跳转到一个页面
* @param registry
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// registry.addViewController("/login.html").setViewName("login");
registry.addViewController("/reg.html").setViewName("reg");
}
}


(1) 验证码倒计时js


$(function () {
$("#sendCode").click(function () {
if ($(this).hasClass("disabled")) {
// 1.进入倒计时效果
} else {
$.get("/sms/sendcode?phone=" + $("#phoneNum").val(), function (data) {
if (data.code != 0) {
layer.msg(data.msg)
}
});

// 2.给指定手机号发送验证码
timeoutChangeStyle()
}
})
})
// 外部变量计时
let num = 60;
function timeoutChangeStyle() {
$("#sendCode").attr("class", "disabled")
if (num == 0) {//可以再次发送
num = 60;
$("#sendCode").attr("class", "");//取消disabled
$("#sendCode").text("发送验证码");
} else {
var str = num + "s 后再次发送";
$("#sendCode").text(str);
// 1s后回调
setTimeout("timeoutChangeStyle()", 1000);
}
num--
}


(2) 阿里云-短信服务


@Data
@ConfigurationProperties(prefix = "spring.cloud.alicloud.sms")
@Component
public class SmsComponent {
private String host;
private String path;
private String skin;
private String sign;
private String appCode;
public String sendSmsCode(String phone, String code){
String method = "GET";
Map<String, String> headers = new HashMap<String, String>();
//最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
headers.put("Authorization", "APPCODE " + this.appCode);
Map<String, String> querys = new HashMap<String, String>();
querys.put("code", code);
querys.put("phone", phone);
querys.put("skin", this.skin);
querys.put("sign", this.sign);
HttpResponse response = null;
try {
response = HttpUtils.doGet(this.host, this.path, method, headers, querys);
//获取response的body
if(response.getStatusLine().getStatusCode() == 200){
return EntityUtils.toString(response.getEntity());
}
} catch (Exception e) {
e.printStackTrace();
}
return "fail_" + response.getStatusLine().getStatusCode();
}
}



@Controller
@RequestMapping("/sms")
public class SmsSendController {
@Autowired
private SmsComponent smsComponent;
/*** 提供给别的服务进行调用的
该controller是发给短信服务的,不是验证的
*/
@GetMapping("/sendcode")
public R sendCode(@RequestParam("phone") String phone, @RequestParam("code") String code){
if(!"fail".equals(smsComponent.sendSmsCode(phone, code).split("_")[0])){
return R.ok();
}
return R.error(BizCodeEnum.SMS_SEND_CODE_EXCEPTION.getCode(), BizCodeEnum.SMS_SEND_CODE_EXCEPTION.getMsg());
}
}


 发送验证码:


@ResponseBody
@GetMapping(value = "/sms/sendCode")
public R sendCode(@RequestParam("phone") String phone) {
//1、接口防刷
String redisCode = stringRedisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);
if (!StringUtils.isEmpty(redisCode)) {
//活动存入redis的时间,用当前时间减去存入redis的时间,判断用户手机号是否在60s内发送验证码
long currentTime = Long.parseLong(redisCode.split("_")[1]);
if (System.currentTimeMillis() - currentTime < 60000) {
//60s内不能再发
return R.error(BizCodeEnum.SMS_CODE_EXCEPTION.getCode(),BizCodeEnum.SMS_CODE_EXCEPTION.getMessage());
}
}
//2、验证码的再次效验 redis.存key-phone,value-code
int code = (int) ((Math.random() * 9 + 1) * 100000);
String codeNum = String.valueOf(code);
String redisStorage = codeNum + "_" + System.currentTimeMillis();
//存入redis,防止同一个手机号在60秒内再次发送验证码
stringRedisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_CACHE_PREFIX+phone,
redisStorage,10, TimeUnit.MINUTES);
thirdPartFeignService.sendCode(phone, codeNum);
return R.ok();
}


4) 后端JSR303校验校验

前端也可以进行校验,此处是后端的验证


@Data
public class UserRegisterVo {// JSR303校验
@Length(min = 6,max = 20,message = "用户名长度必须在6-20之间")
@NotEmpty(message = "用户名必须提交")
private String userName;
@Length(min = 6,max = 20,message = "用户名长度必须在6-20之间")
@NotEmpty(message = "密码必须提交")
private String password;
@NotEmpty(message = "手机号不能为空")
@Pattern(regexp = "^[1]([3-9])[0-9]{9}$", message = "手机号格式不正确")
private String phone;
@NotEmpty(message = "验证码必须填写")
private String code;
}


前面的JSR303校验怎么用:

JSR303校验的结果,被封装到​​BindingResult​​​,再结合​​BindingResult.getFieldErrors()​​方法获取错误信息,有错误就重定向至注册页面


@PostMapping("/register")
public String register(@Valid UserRegisterVo registerVo,
BindingResult result,
RedirectAttributes attributes) {
if (result.hasErrors()){
return "redirect:http://auth.gulimall.com/reg.html";