注册
1.1. 配置
@Configuration
public class GulimallConfig implements WebMvcConfigurer {
/**
* 视图映射
* @param registry
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
/**
* @GetMapping("/login.html")
* public String loginPage(){
* return "login";
* }
*/
registry.addViewController("/login.html").setViewName("login");
registry.addViewController("/reg.html").setViewName("reg");
}
}
1.2. 整合短信服务
compoent
package com.cwh.gulimall.thirdparty.component;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.dysmsapi20170525.Client;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Slf4j
@ConfigurationProperties(prefix = "spring.cloud.alicloud.sms")
@Data //为这些方法生成getter,setter
@Component
public class SmsClient {
// private static String accessKeyId;
// private static String accessKeySecret;
public static Client createClient() throws Exception {
String accessKeyId = "LTAI5tGW4xdUd5pnea6WHFZw";
String accessKeySecret = "itwGI52mYtcveb6nA5ltU2ZUvTHLGy";
Config config = new Config()
// 配置 AccessKey ID,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
.setAccessKeyId(accessKeyId)
// 配置 AccessKey Secret,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
.setAccessKeySecret(accessKeySecret);
// 配置 Endpoint
config.endpoint = "dysmsapi.aliyuncs.com";
return new Client(config);
}
}
controller
package com.cwh.gulimall.thirdparty.controller;
import com.cwh.gulimall.thirdparty.utils.R;
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 com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.cwh.gulimall.thirdparty.component.SmsClient;
import com.aliyun.dysmsapi20170525.Client;
import static com.aliyun.teautil.Common.toJSONString;
@RestController
@RequestMapping("/sms")
public class SmsSendController {
Client client = SmsClient.createClient();
public SmsSendController() throws Exception {
}
/**
* 提供给其他服务调用
* @param phone
* @param code
* @return
*/
@GetMapping("/sendcode")
public R sendCode(@RequestParam("phone") String phone, @RequestParam("code") String code) throws Exception {
// 构造请求对象,请填入请求参数值
SendSmsRequest sendSmsRequest = new SendSmsRequest()
.setPhoneNumbers("15866638892")
.setSignName("ColinCode商城")
.setTemplateCode("SMS_474140261")
.setTemplateParam("{\"code\":\"" + code + "\"}");
System.out.println("验证码: " + code);
// 获取响应对象
SendSmsResponse sendSmsResponse = client.sendSms(sendSmsRequest);
System.out.println(toJSONString(sendSmsResponse));
return R.ok();
}
}
1.3. 业务接口实现
@ResponseBody
@GetMapping("/sms/sendcode")
public R sendCode(@RequestParam("phone") String phone) throws Exception {
// 1.接口防刷
String redisCode = redisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);
if (StringUtils.isNotEmpty(redisCode)) {
// 60s内不能重发
if ((System.currentTimeMillis() - Long.parseLong(redisCode.split("_")[1])) < 60000) {
return R.error(10002, "验证码频率过高,稍后再试");
}
}
// 2.验证码再次校验 redis:key:phone, value:code
String code = String.valueOf(RandomUtils.nextInt(10000, 100000));
redisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone, code, 10, TimeUnit.MINUTES);
System.out.println("验证码:" + code);
thirdPartFeignService.sendCode(phone, code);
return R.ok();
}
/**
* 重定向携带数据,利用Session原理,将数据放入session中,只要跳到下一个页面,取出数据后,session中的数据就会被删掉
* // TODO 分布式下的session问题
* RedirectAttributes redirectAttributes:模拟重定向携带数据
*
* @param vo
* @param bindingResult
* @param redirectAttributes
* @return
*/
@Transactional
@PostMapping("/register")
public String registry(@Valid UserRegistVo vo, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
if (bindingResult.hasErrors()) {
Map<String, String> errors = bindingResult.getFieldErrors()
.stream().collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
// model.addAttribute("errors", errors);
// 校验出错,转发到注册页
redirectAttributes.addFlashAttribute("errors", errors);
// Request method 'POST' not supported:只是Get请求能映射
return "redirect:http://auth.gulimall.com/reg.html";
}
// 调用远程服务
// 1.校验验证码
String code = vo.getCode();
String redisKey = AuthServerConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone();
String s = redisTemplate.opsForValue().get(redisKey);
if (StringUtils.isNotEmpty(s) && code.equals(s.split("_")[0])) {
// 删除验证码;令牌机制
redisTemplate.delete(redisKey);
// 验证码校验通过
R r = memberFeignService.registry(vo);
if (r.getCode() == 0) {
// 注册成功回到登录页(重定向)
return "redirect:http://auth.gulimall.com/login.html";
} else {
Map<String, String> errors = new HashMap<>();
errors.put("msg", r.getData("msg", new TypeReference<String>() {
}));
redirectAttributes.addFlashAttribute("errors", errors);
return "redirect:http://auth.gulimall.com/reg.html";
}
} else {
Map<String, String> errors = new HashMap<>();
errors.put("code", "验证码错误");
// 校验出错,转发到注册页
redirectAttributes.addFlashAttribute("errors", errors);
// Request method 'POST' not supported:只是Get请求能映射
return "redirect:http://auth.gulimall.com/reg.html";
}
}
@PostMapping("/login")
public String login(UserLoginVo vo, RedirectAttributes redirectAttributes, HttpSession session){
R r = memberFeignService.login(vo);
if(r.getCode() == 0){
MemberRespVo data = r.getData("data", new TypeReference<MemberRespVo>() {
});
session.setAttribute("loginUser", data);
return "redirect:http://gulimall.com";
}else {
Map<String, String> errors = new HashMap<>();
errors.put("msg", r.getData("msg", new TypeReference<String>(){}));
redirectAttributes.addFlashAttribute("errors", errors);
return "redirect:http://auth.gulimall.com/login.html";
}
}
@Override
public void registry(MemberRegistVo vo){
MemberEntity memberEntity = new MemberEntity();
// 检查用户名与手机号是否唯一,为了让controller感知异常,异常机制
checkPhoneUnique(vo.getPhone());
checkUserNameUnique(vo.getUserName());
memberEntity.setUsername(vo.getUserName());
memberEntity.setMobile(vo.getPhone());
memberEntity.setNickname(vo.getUserName());
// 设置默认等级
MemberLevelEntity levelEntity = memberLevelService.getDefaultLevel();
memberEntity.setLevelId(levelEntity.getId());
// 密码加密
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encode = passwordEncoder.encode(vo.getPassword());
memberEntity.setPassword(encode);
this.save(memberEntity);
}
@Override
public void checkPhoneUnique(String phone) throws PhoneExistException {
int count = this.count(new QueryWrapper<MemberEntity>().eq("mobile", phone));
if(count == 1){
throw new PhoneExistException();
}
}
@Override
public void checkUserNameUnique(String name) throws UserNameExistExcept {
int count = this.count(new QueryWrapper<MemberEntity>().eq("username", name));
if(count == 1){
throw new PhoneExistException();
}
}